본문 바로가기

프로그래밍/Java

[Java 요약 정리] 12. 입출력(I/O)

1. 입출력(I/O)

1) 입출력(I/O)과 스트림(Stream)

- 입출력: 두 대상 간의 데이터를 주고 받는 것

- 스트림: 데이터를 운반(입출력)하는데 사용되는 연결 통로

- 하나의 스트림으로 입출력을 동시 수행 불가(동시 수행 시 2개의 스트림 필요)

- Binary 파일: 있는 그대로 저장된 파일

- Text 파일: 문자로 저장된 파일


2) 바이트 기반 스트림(InputStream, OutputStream)

- 데이터를 바이트(Byte)단위로 주고 받는다.

- Input스트림과 OutputStream으로 구분

- abstract int read() <-> abstract void write(int b)

- int read(byte[] b) <-> void write(byte[] b)

- int read(byte[] b, int off, int len) <-> void write(byte[] b, int off, int len)


3) 보조스트림

- 목적: 스트림 기능 향상 혹은 새로운 기능 추가

- 독립적인 입출력 수행 불가(기반 스트림에 종속적)

- 보조스트림을 사용한 경우 보조스트림의 close()만 호출하면 닫힘(기반먼저 닫으면 안됨)

- FilterIn(out)putStream: 필터를 이용한 입출력 처리

- BufferedIn(out)putStream: 버퍼를 이용한 입출력 성능 향상(사용도 높음)

- DataIn(out)putStream: 기본형 타입 데이터 처리 기능

- SequenceIn(out)putStream: 두개의 스트림 연결

- LineNumberInputStream(입력): 읽어온 데이터 라인 번호 카운트

- ObjectIn(out)putStream: 데이터를 객체단위로 읽고 쓰는데 사용(주로 파일 이용)

- PrintStream(출력): 버퍼 이용, print관련 기능

- PushbackInputStram(입력): 버퍼를 이용해서 읽어온 데이터를 되돌리는 기능


4) 문자기반 스트림(Reader, Writer)

- 입출력 단위가 문자인 스트림


바이트 기반 스트림

문자 기반 스트림

대상

FileInputStream

FileOutputStream

FileReader

FileWriter

파일

ByteArrayInputStream

ByteArrayOutputStream

CharArrayReader

CharArrayWriter

메모리



바이트 기반 보조스트림

문자 기반 보조 스트림

비고

BufferedInputStream

BufferedOutputStream

BufferedReader

BufferedWriter

버퍼를 이용한 입출력 성능 향상

FilterInputStream

FilterOutputStream

FilterReader

FilterWriter

보조스트림 최고 조상

PrintStream

PrintWriter


Pushback

Reader



2. 바이트 기반 스트림

1) InputStream과 OutputStream

- int availabe(): 읽어올 수 있는 데이터 크기 반환

- void close(): 스트림을 닫고 자원 반환

- void mark(int readlimit): 현재 위치 표시

- boolean markSupported(): mark()와 reset()지원 여부 확인

- abstract int read(): 1byte를 읽어오고 더 이상 읽을 데이터가 없으면 -1 반환)

- int read(byte[] b): b[]의 크기만큼 읽어서 채운 후 데이터의 수 반환

- int read(byte[] b, int off, int len): 최대 len개의 byte를 읽어서 b[]의 off부터 저장

- void reset(): 마지막 mark()로 재위치

- long skip(long n): n만큼 건너뛴다.


2) ByteArrayInputStream과 ByteArrayOutputStream

- void close(): 입력 소스를 닫아서 자원 반환

- void flush(): 버퍼에 있는 모든 내용을 출력 소스에 사용

- abstract void write(int b): 주어진 값을 출력소스에 사용

- void write(byte[] b): b[]에 저장된 모든 내용을 출력소스에 사용

- void write(byte[] b, int off, int len): b[]에서 off부터 len개 만큼 읽어서 사용

3) FileInputStream과 FileOutputStream

- FileInputStream 생성자

(String name): 지정된 파일명을 가진 실제 파일과 연결된 입력스트림 생성

(File file): File 인스턴스로 지정


- FileOutputStream 생성자

(String name): 지정된 파일명을 가진 실제 파일과 연결된 출력스트림 생성

(String name, boolean append): append값 true->덧붙이기 / false-> 덮어쓰기

(File file): File 인스턴스로 지정


*바이트 기반 보조스트림

1) FilterInputStream과 FilterOutputStream

- 모든 바이트기반 보조스트림의 최고 조상

- InputStream or OutputStream 상속을 통한 read(), write() 오버라이딩 필수


2) BufferedInputStream과 BufferedOutputStream

-  입출력 효율을 높이기 위해 버퍼(byte[])를 사용하는 보조스트림

- BufferedInputStream의 생성자

(InputStream in, int size) -> 지정된 크기의 버퍼를 갖는 입력 인스턴스 생성

(InputStream in) -> 8192byte 크기의 버퍼를 갖는 입력 인스턴스 생성

- BufferedOutputStream의 생성자

(OutputStream in, int size) -> 지정된 크기의 버퍼를 갖는 출력 인스턴스 생성

(OutputStream in) -> 8192byte 크기의 버퍼를 갖는 출력 인스턴스 생성

- BufferedOutputStream의 메소드

flush(): 버퍼의 모든 내용을 출력소스에 출력 후 버퍼를 비움

close(): flush()를 호출해서 모든 내용 출력 후 인스턴스의 모든 자원 반환


3) SequenceInputStream

- 여러 입력스트림을 연결(하나처럼 사용)

- 생성자

(Enumeration e): e에 저장된 순서대로 입력스트림 연결

(InputStream s1, InputStream s2): s1과 s2를 연결


4) PrintStream

- 데이터를 다양한 형식의 문자로 출력하는 기능을 제공(System.out이 PrintStream)

- 생성자에서 autoFlush의 값을 true로 하면 print메소드 호출 및 개행문자 출력시 자동 flush

- PrintStream보다 PrintWriter를 사용할것을 권장


3. 문자 기반 스트림

1) Reader와 Writer

- 문자기반 스트림의 최고 조상

- Reader의 메소드

abstract void close(): 입력 스트림을 닫고 자원 반환

void mark(int readlimit): 현재 위치 표시

boolean markSupported(): mark()와 reset() 지원 여부 반환

int read(): 입력소스로부터 하나의 문자를 읽어와서 char범위의 정수 반환(마지막엔 -1 반환)

int read(char[] c): c[]의 크기만큼 읽어서 c[]에 저장, 데이터의 개수 or -1 반환

abstract int read(char[] c, int off int len): 최대 len개의 문자를 읽어서 c[]의 off위치부터 저장

boolean ready(): 입력소스로부터 데이터를 읽을 준비가 되어있는지 반환

void reset(): 마지막으로 mark()가 호출된 곳으로 위치로 재위치

long skip(long n): 현재 위치에서 n만큼 건너뜀


- Writer의 메소드

abstract void close(): 출력스트림을 닫고 자원 반환

abstract void flush(): 스트림의 버퍼에 있는 모든 내용을 출력 소스에 사용

void write(int b): b를 출력소스에 사용

void write(char[] c): c[]를 출력소스에 사용

abstract void write(char[] c, int off, int len): c[]에서 off번째부터 len 길이만큼 출력소스에 사용

void write(String str): str을 출력소스에 사용

void write(String str, int off, int len): str에서 off부터 len개 만큼 출력소스로 사용



2) FileReader와 FileWriter

- 문자기반 파일의 입출력에 사용


3) StringReader와 StringWriter

- CharArrayReader/Writer처럼 메모리 입출력에 사용

- StringWriter에 출력되는 데이터는 내부의 StringBuffer에 저장

- 메소드

StringBuffer getBuffer(): 출력한 데이터가 저장된 StringBuffer를 반환

String toString(): StringBuffer에 저장된 문자열 반환


*문자기반 보조스트림

1) BufferedReader와 BufferedWriter

- 입출력 효율을 높이기 위해 버퍼(char[])를 사용하는 보조스트림

- 라인 단위의 입출력 용이

- 메소드

String readLine(): 한 라인을 읽어온다

void newLine(): '라인 구분자'를 출력


2) InputStreamReader와 OutputStreamWriter

- 바이트 기반 스트림을 문자기반 스트림처럼 사용 가능

- 인코딩 변환을 통해 입출력 가능

- Input(Output)StreamReader의 생성자와 메소드(Input, Ouput 내용 동일)

((In)putStream in): OS에서 사용하는 기본 인코딩의 문자로 변환하는 스트림 생성

((In)putStream in, String encoding): 지정된 인코딩을 사용하는 스트림 생성

String getEncoding(): (In)putStreamReader의 인코딩 반환


4. 표준 입출력과 File

1) 표준 입출력 System.in / System.out / System.err

- 표준 입출력: 콘솔을 통한 데이터의 입출력

- JVM 시작시 자동으로 생성되는 스트림


2) RandomAccesFile

- 하나의 스트림으로 파일 입출력을 모두 수행

- 다른 스트림들과 달리 Object의 자손

- 생성자: file에 읽기쓰기를 위한 인스턴스 생성 // mode: r(읽기), rw(쓰기)

(File file, String mode) (String fileName, String mode)

- 메소드

long getFilePointer(): 파일 포인터 위치 반환

long length(): 파일의 크기 반환(단위 byte)

void seek(long pos): 파일 포인터 위치 변경(처음부터 pos크기만큼)

void setLength(long newLength): 파일 크기를 지정된 길이로 변경

int skipBytes(int n): n byte만큼 건너뜀


3) File

- 파일과 디렉토리를 다루는데 사용되는 클래스

- 생성자

(String fileName) : fileName을 위한 File인스턴스 생성(경로값 포함, 미포함시 실행경로)

(String pathName, String fileName) (File pathName, String fileName): 파일과 경로 분리


- 경로 관련 메소드

String getName(): 파일명 반환

String getPath(): 파일의 경로 반환

String getAbsolutePath(), File getAbsoluteFile(): 파일의 절대 경로 반환

String getParent(), File getParentFile(): 파일의 조상 디렉토리 반환

String getCanonicalPath(), File getCanonicalFile(): 파일의 정규 경로 반환


- 멤버변수

static String pathSeparator, static char pathSeparatorChar: OS에서 사용하는 경로 구분자

static String separator, static char separatorChar: OS에서 사용하는 이름 구분자


- 파일 관련 메소드

boolean canRead(): 읽기 가능 여부 확인

boolean canWrite(): 쓰기 가능 여부 확인

boolean exists(): 파일이 존재 여부 확인

boolean isAbsolute(): 절대경로명 여부 확인

boolean isDirectory(): 디렉토리 확인

boolean isFile(): 파일 확인

boolean isHidden(): 숨김 여부 확인(존재하지 않을 시 false반환)

int compareTo(File pathname): 주어진 파일, 디렉토리 비교 반환(같으면 0, 다르면 -1 or 1

boolean createNewFile(): 빈 파일 생성(이미 존재시 미생성)

static File createTempFile(String prefix, String suffix): 임시파일을 임시디렉토리에 생성

static File createTempFile(String prefix, String suffix, File directory): 임시파일 지정 경로 생성

boolean delete(): 파일 삭제

void deleteOnExit(): 응용 프로그램 종료시 파일 삭제(주로 임시파일 삭제 용도)

boolean equals(Object obj): 파일 비교

long length(): 파일 크기 반환

String[] list(): 디렉토리의 파일 목록 반환(디렉토리 포함)

String[] list(FilenameFilter filter): FilenameFilter인스턴스에 구현된 조건에 맞는 파일 반환

File[] listFiles(): 디렉토리의 파일 목록을 File배열로 반환(디렉토리 포함)

static File[] listRoots(): 컴퓨터 파일시스템의 root의 목록 반환(C:\ d:\ 등등)


5. 직렬화(Serialization)

1) 직렬화란?

- 객체를 연속적인 데이터로 변환하는 것(객체 저장을 위해 필수)

- 객체의 인스턴스 변수들의 값을 일렬로 나열하는 것


2) ObjectInputStream, ObjectOutputStream

- 객체를 직렬화하여 입출력 할 수 있게 해주는 보조스트림

- 객체를 파일에 저장하는 방법

FileOutputStream fos = new FileOutputStream("objectfile.ser");

ObjectOutputStream out = new ObjectOutputStream(fos);

out.writeObject(new UserInfo());

- 파일에 저장된 객체를 다시 읽어오는 방법

FileInputStream fis = new FileInputStream("objectfile.ser");

ObjectInputStream out = new ObjectInputStream(fis);

UserInfo info = (UserInfo)in.readObject();


3) 직렬화 가능한 클래스 만들기

- java.io.Serializable 인터페이스를 구현해야만 직렬화 가능

- 제어자 transient가 붙은 인스턴스변수는 직렬화 대상에서 제외

- Serializable을 구현하지 않은 클래스의 인스턴스도 직렬화 대상에서 제외

- Serializable을 구현하지 않은 조상의 멤버들은 직렬화 대상에서 제외

- read(write)Object()를 오버라이딩하면 자유롭게 직렬화 가능


4) 직렬화 가능한 클래스의 버전관리

- 직렬화, 역직렬화 시 클래스가 같은지 확인

- 직렬화시 클래스의 버전(SerialVersionUID)을 자동계산해서 저장

- 클래스 버전을 수동관리하려면 클래스 내에 별도로 정의

- serialver.exe는 클래스의 serialVersionUID를 자동 생성