1. 자바에서의 입출력
1.1 입출력이란
1.2 스트림(stream)
- 어느 한쪽에서 다른 쪽으로 데이터를 전달할 때, 두 대상을 연결하고 데이터를 전송할 연결통로.
- 단방향통신만 가능. (하나의 스트림으로 입출력을 동시에 처리할 수 X)
- 동시에 수행하려면, 입력스트림과 출력스트림 총 2개의 스트림이 필요함.
- Queue와 같은 FIFO구조로 되어있다고 생각하면 됨.
1.3 바이트기반 스트림- InputStream, OutputStream
입력스트림 | 출력스트림 | 입출력 대상의 종류 |
FileInputStream | FileOutputStream | 파일 |
ByteArrayInputStream | ByteOutputStream | 메모리(byte 배열) |
PipedInputStream | PipedOutputStream | 프로세스(프로세스간의 통신) |
AudioInputStream | AudioOutputStream | 오디오장치 |
- 입출력의 단위가 1 byte.
1.4 보조 스트림
- 데이터 입출력 기능은 없지만, 스트림의 기능을 향상시키거나 새로운 기능을 추가할 수 있음.
-> 스트림을 먼저 생성한 다음에 이를 이용해서 보조스트림을 생성해야 함.
// 먼저 기반스트림 생성.
FileInputStream fis = new FileInputStream("test.txt");
// 기반스트림을 이용해서 보조스트림을 생성.
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(); // 보조스트림인 BufferedInputStream으로부터 데이터를 읽음.
- 보조스트림 BufferedInputStream은 버퍼만을 제공함.
입력 | 출력 | 설명 |
FilterInputStream | FilterOutputStream | 필터를 이용한 입출력 처리 |
BufferedInputStream | BufferedOutputStream | 버퍼를 이용한 입출력 성능향상 |
DataInputStream ★ | DataOutputStream | int, float와 같은 기본형 단위로 데이터 처리 |
SequenceInputStream | - | 두 개의 스트림을 하나로 연결 |
ObjectInputStream ★★ | ObjectOutputStream | 데이터를 객체단위로 읽고 쓰는데 사용. 주로 파일을 이용하며 객체 직렬화와 관련있음 |
- | PrintStream | 버퍼를 이용하며, 추가적인 print관련 기능(print, printf, println메서드) |
PushbackInputStream | - | 버퍼를 이용해서 읽어 온 데이터를 다시 되돌리는 기능(unread, push back to buffer) |
1.5 문자기반 스트림- Reader, Writer
- Java에서는 한 문자를 의미하는 char형이 2 byte이기 때문에 바이트기방의 스트림으로 2 byte인 문자를 처리하는 데는 어려움이 있음.
-> 이를 보안하기 위해 문자기반 스트림 제공됨.
- 문자데이터를 입출력할 때는 바이트기반 스트림 대신 문자기반 스트림을 사용할 것.
바이트기반 스트림 | 문자기반 스트림 |
FileInputStream FileOutputStream |
FileReader FileWriter |
ByteArrayInputStream ByteArrayOutputStream |
CharArrayReader CharArrayWriter |
PipedInputStream PipedOutputStream |
PipedReader PipedWriter |
StringbufferReader StringbufferWriter |
보조스트림도 똑같이 InputStream은 Reader로 OutputStream은 Writer로 바꾸면 됨.
2. 바이트기반 스트림
2.1 InputStream과 OutputStream
InputStream메서드명 | 설명 |
void mark(int readlimit) | 현재위치 표시해 둠. 후에 reset()에 의해서 표시해 놓은 위치로 다시 돌아갈 수 있음. readlimit은 되돌아갈 수 있는 byte의 수. |
void reset() | 스트림에서의 위치를 마지막으로 mark()이 호출되었던 위치로 되돌림. |
int available() | |
void close() | |
boolean markSupported() | |
abstract int read() | |
int read(byte[] b) | |
int read(byte[] b, int off, int len) | 최대 len개의 byte를 읽어서, 배열 b의 지정된 위치(off)부터 저장함. 실제로 읽어올 수 있는 데이터가 len개보다 적을 수 있음. |
long skip(long n) |
OutputStream메서드명 | 설명 |
void close() ★ | 입력소스를 닫음으로써 사용하고 있던 자원을 반환함. |
void flush() | 스트림의 버퍼에 있는 모든 내용을 출력소스에 씀. |
abstract void write(int b) | 주어진 값을 출력소스에 씀. |
void write(byte[] b) | |
void write(byte[] b, int off, int len) |
2.2 ByteArrayInputStream과 ByteArrayOutputStream
- 메모리, 즉 바이트배열에 데이터를 입출력 하는데 사용되는 스트림.
- 주로 다른 곳에 입출력하기 전에 데이터를 임시로 바이트배열에 담아서 변환 등의 작업을 하는데 사용됨.
2.3 FileInputStream과 FileOutputStream ★
생성자 | 설명 |
FileInputStream(String name) | |
FileInputStream(FIle file) | |
FileInputStream(FileDescripter fdObj) | |
FileOutputStream(String name) | 지정된 파일이름을 가진 실제 파일과 연결된 FileOutputStream을 생성 |
FileOutputStream(String name, boolean append) | appnend를 true로 하면, 출력시 기존 파일내용의 마지막에 덧붙임.(이어쓰기) false면, 기존 파일내용을 덮어씀. |
FileOutputStream(File file) | 파일의 이름을 File인스턴스로 지정해줌. |
FileOutputStream(File file, boolean append) | |
FileOutputStream(FileDescriptor fdObj) | 파일 디스크립터로 FileOutputStream 생성 |
package chap15;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
public class FileStreamEx {
public static void main(String[] args)throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\bo bo\\Documents\\target.txt");// 예외처리 해야함.
FileReader fr = new FileReader("C:\\Users\\bo bo\\Documents\\target.txt");
int b = 0;
while((b = fis.read()) != -1) {// read() 한번에 1byte씩
System.out.println(b + " ::: " + (char)b);
}
System.out.println("--절취선--");
b = 0;
while((b = fr.read()) != -1) {// read() 한번에 1char씩
System.out.println(b + " ::: " + (char)b);
}
fis.close();
fr.close();
// b = fis.read();
// System.out.println(b);
// read한 번씩 cursor 한 칸씩.
// End Of File -1
// 0 ~ 255
}
}
target.txt에
======
abcd
1234
가나다라
======
미리 저장해 둠.
<파일복사 구현하기>
package chap15;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class FileStreamEx2 {
public static void main(String[] args) throws IOException {
// 파일 복사 구현하기
FileInputStream fis = new FileInputStream("C:\\Users\\bo bo\\Documents\\target.txt");
FileOutputStream fos = new FileOutputStream("C:\\Users\\bo bo\\Documents\\target2.txt", true);
// 파일의 총 크기= 26 byte
byte[] bArr = new byte[8];
// fis.read(bArr);
// System.out.println(Arrays.toString(bArr));
// System.out.println(fis.available());// 남은 가용 byte 수
// bArr = new byte[8];
// fis.read(bArr);
// System.out.println(Arrays.toString(bArr));
// System.out.println(fis.available());
//
// bArr = new byte[8];
// fis.read(bArr);
// System.out.println(Arrays.toString(bArr));
//
// bArr = new byte[8];
// fis.read(bArr);
// System.out.println(Arrays.toString(bArr));
//
// bArr = new byte[8];
// fis.read(bArr);
// System.out.println(Arrays.toString(bArr));
while(fis.available() > 0) {
int len = fis.read(bArr);// 읽고
fos.write(bArr, 0, len); // 쓰고
}
fis.close();
fos.close();
}
}
fis.read(bArr); 하면 파일복사가 제대로 안 된다. 왜지?
target2.txt에
======
34
가나다라
======
로 저장됨.ㅠ 저 줄을 지워보니 정상적으로
======
abcd
1234
가나다라
======
가 생성되는데...
아무튼 텍스트파일을 다룰 땐 문자기반 스트림인 FileReader/FileWriter를 사용하자.
3. 바이트기반의 보조스트림
3.1 FilterInputStream과 FilterOutputStream
3.2 BufferedInputStream과 BufferedOutputStream
package chap15;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferedOutStreamEx1 {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("123.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos, 5); // buffer의 크기를 5
for(int i = 65 ; i <= 65+25 ; i++) {
bos.write(i);
}
bos.close(); // fos.close();하면 Z가 출력 안 됨.
}
catch (IOException e) {
e.printStackTrace();
}
}
}
3.3 DataInputStream과 DataOutputStream
- 데이터를 읽고 쓰는데 있어서 8가지 기본 자료형의 단위로 읽고 쓸 수 있다는 장점.
- 출력하는 형식은 각 기본 자료형 값을 16진수로 표현하여 저장함.
- ex) int값을 출력한다면, 4byte의 16진수로 출력.
package chap15;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamEx1 {
public static void main(String[] args) {
FileOutputStream fos = null;
DataOutputStream dos = null;
try {
fos = new FileOutputStream("sample.txt");
dos = new DataOutputStream(fos); // 보조스트림
dos.writeInt(Integer.MIN_VALUE); // 정수(int)를 작성 4
dos.writeFloat(20); // float 4
dos.writeBoolean(true); // boolean 1byte라서 txt파일 크기가 9 byte
dos.writeLong(10); // 자료형이 가진 크기를 그대로 활용함.
dos.close();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
sample.txt 생성.
package chap15;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class DataInputStreamEx1 {
public static void main(String[] args) throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("sample.txt"));
System.out.println(dis.readInt());
System.out.println(dis.readFloat());
System.out.println(dis.readBoolean());
System.out.println(dis.readLong()); // readLong대신 readInt 두 개 쓸 수도 있음
// System.out.println(dis.readInt());
// System.out.println(dis.readInt());
dis.close();
}
}
package chap15;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class DataInputStreamEx2 {
public static void main(String[] args) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(10);
dos.writeFloat(20.f);
dos.writeBoolean(true);
dos.write(0);
dos.write(0);
dos.write(0);
dos.write(10); // write 4개가 writeInt
dos.writeChar('A');
dos.writeChar('\uac00');
dos.writeChars("가가가");
dos.writeUTF("가A"); // utf에선 A를 1바이트 취급
byte[] result = baos.toByteArray();
// byte -128 ~ 127 > 256가지
// unsigned, signed
String[] hex = new String[result.length];
for(int i = 0 ; i < result.length ; i++) {
if(result[i] < 0) {
hex[i] = String.format("%02x", result[i] + 256); // -128 ~ -1 을 128 ~ 255로
}
else {
hex[i] = String.format("%02x", result[i]);
}
}
System.out.println("10진수: " + Arrays.toString(result));
System.out.println("16진수: " + Arrays.toString(hex));
}
}
- 자바의 자료형인 byte의 범위가 부호 있는 1byte 정수의 범위인 -128~127이기 때문에 -1로 인식함.
-> 그래서 이 256을 더해서 이 값을 0~266사이의 값으로 변환한 것.
- ByteArray스트림을 사용하면 byte단위의 데이터 변환 및 조작이 가능함.
3.4 SequenceInputStream
3.5 PrintStream
4. 문자기반 스트림
4.1 Reader와 Writer
4.2 FileReader와 FileWriter
4.3 PipedReader와 PipedWriter
4.4 StringReader와 StringWriter
5. 문자기반의 보조스트림
5.1 BufferedReader와 BufferedWriter
5.2 InputStreamReader와 OutputStreamWriter
- 바이트기반 스트림을 문자기반 스트림으로 연결시켜주는 역함.
- 그리고 바이트기반 스트림의 데이터를 지정된 인코딩의 문자데이터로 변환하는 작업을 수행함.
- 자바의 세계는 문자!
package chap15;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class InputStreamReaderEx {
public static void main(String[] args) throws IOException {
URL url = new URL("https://ncs.go.kr/index.do");
InputStream is = url.openStream(); // 바이트기반스트림
InputStreamReader isr = new InputStreamReader(is); // 바이트 > 문자
BufferedReader br = new BufferedReader(isr); // 보조스트림
String input = "";
for(int i = 1 ; (input = br.readLine()) != null ; i++) {
System.out.println(i + ":::" +input);
}
br.close();
}
}
6. 표준입출력과 File
6.1 표준입출력 - System.in, System.out, System.err
package chap15;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
public class StandardIOEx3 {
public static void main(String[] args) throws IOException {
PrintStream ps = new PrintStream(new FileOutputStream("std_test.txt")); // 보조스트림 사용
System.setOut(ps); // 보조스트림 변경
System.out.println("헬로우월드1"); // txt파일로 들어감
System.out.println("헬로우월드2"); // txt파일로 들어감
System.out.println("헬로우월드3"); // txt파일로 들어감
System.err.println("헬로우월드");
// 상수
// 값이 "한번 정해지면" 변하지 않는 것.
System.out.println(File.separator); // 한번 값이 정해지는 게 요인에 의해 값이 다름. 그래서 소문자.
// windows \
// linux /
System.out.println(Integer.MAX_VALUE); // 코드 작성 당시 불변값
System.out.println(String.CASE_INSENSITIVE_ORDER);
}
}
6.2 표준입출력의 대상변경 - setOut(), setErr(), setIn()
6.3 RandomAccessFile
- 이 클래스의 가장 큰 장점은 파일의 어느 위치에나 읽기/쓰기가 가능하다는 것.
- 내부적으로 파일 포인터를 사용하는데, 입출력 시에 작업이 수행되는 곳이 바로 파일 포인터가 위치한곳이 됨.
6.4 File
package chap15;
import java.io.File;
import java.io.IOException;
public class FileEx1 {
public static void main(String[] args) throws IOException {
File f = new File("D:\\workspace\\chap15\\src\\chap15\\FileEx1.java");
String fileName = f.getName();
int pos = fileName.lastIndexOf(".");
System.out.println("경로제외 파일 이름:: " + fileName);
System.out.println("확장자 제외 파일 이름:: " + fileName.substring(0, pos));
System.out.println("확장자:: " + fileName.substring(pos+1));
System.out.println("경로 포함 파일이름:: " + f.getPath());
System.out.println("파일의 절대경로:: " + f.getAbsolutePath());
System.out.println("파일의 정규경로:: " + f.getCanonicalPath());
System.out.println("파일이 속해 있는 디렉토리1:: " + f.getParent());
System.out.println("파일이 속해 있는 디렉토리2:: " + f.getParentFile().getParentFile());
System.out.println();
System.out.println("패스 구분자" + File.pathSeparator);
System.out.println("구분자" + File.separator);
System.out.println();
System.out.println("user dir:: " + System.getProperty("user.dir"));
System.out.println("sun.boot.class.path:: " + System.getProperty("sun.boot.class.path"));
// System.getProperties("user.dir");
// 소유자
// 그룹
// 손님
// 읽기
// 실행하기
// 쓰기
// chmod 777 누구에게나 모든 권한 다 줌
// 755 그룹, 손님한텐 쓰기 권한 빼고 줌.
}
}
'JAVA' 카테고리의 다른 글
16장- 네트워킹 21. 02. 16. (0) | 2021.02.17 |
---|---|
15장- 입출력 I/O 끝 21. 02. 16. (0) | 2021.02.17 |
11장- 컬렉션 프레임웍 21 . 02. 08. (0) | 2021.02.09 |
04장- 조건문과 반복문 21. 02. 03. (0) | 2021.02.04 |
21. 01. 27. 03장- 연산자 (0) | 2021.01.27 |