JAVA chap 8. 입출력 스트림과 파일 입출력

2023. 11. 20. 01:17컴퓨터공학 전공공부/자바기반 응용 프로그래밍

1. Stream 

스트림 입출력이란?

 버퍼를 가지고 순차적으로 이루어지는 입출력을 말한다. (스트림은 바이트 흐름)

 

입력 스트림과 출력 스트림

 입력 스트림은 데이터를 전달, 출력 스트림은 데이터를 출력한다.

입력장치 > 입력스트림 > 코드 > 출력스트림 > 출력장치

 

특징

1. 스트림은 단방향이다. (입출력을 동시에 하는 스트림은 없다.)

2. 입출력 스트림의 기본 단위 : 바이트 스트림의 경우 1 바이트, 문자 스트림의 경우 문자 (2 바이트)

3. 문자 스트림에서, 문자가 아닌 바이너리 데이터는 처리하지 못한다.

 

바이트 스트림 클래스, 문자 스트림 클래스 계층 구조

[ 바이트 스트림 ] 입력스트림은 InputStream으로, 출력스트림은 OutputStream으로 끝난다. [ 문자 스트림 ] 입력스트림은 Reader로, 출력스트림은 Writer로 끝난다.

 

스트림의 연결

 표준 입력 스트림 System.in에 InputStreamReader 스트림을 연결한다.

InputStreamReader rd = new InputStreamReader(System.in);
int c = rd.read(); // 키보드에서 문자 읽음

 

 

2. 문자 Stream

문자 스트림

 유니 코드 (2 바이트) 문자를 입출력하는 스트림으로, 이미지와 같은 바이너리 데이터는 입출력할 수 없다.

 

문자 스트림을 다루는 클래스

 Reader/Writer, InputStreamReader/OutputStreamWriter, FileReader/FileWriter

 

FileReader를 이용한 파일 읽기

import java.io.FileReader;
import java.nio.charset.StandardCharsets;

FileReader fin = new FileReader ("c:\\test.txt"); //test 파일을 열고 입력 스트림 객체 fin과 연결

int c;
while ((c = fin.read()) != -1) { //파일 끝까지 한 문자씩 c에 읽어 들임. 파일의 끝을 만나면 read()는 -1 리턴.
	System.out.print((char)c); //바이트 c를 문자로 변환하여 화면에 출력
}

fin.close(); //스트림을 닫음. 파일도 닫힘.

//파일 내부 저장되어 있는 -1과, 파일의 끝을 만나면 리턴되는 -1은 같지 않음.

 

문자 집합과 InputStreamReader를 이용한 텍스트 파일 읽기

  hangul.txt에 저장되어 있는 가나다라  → 이진수의 형태로 fin에 전달 → 이진수의 형태, 바이트 단위로 in에 전달 → '가', '나'와 같은 문자 단위로 in.read()에 전달

FileInputStream fin = new FileInputStream("c:\\Temp\\hangul.txt"); //바이트스트림 fin 생성
InputStreamReader in = new InputStreamReader(fin, "UTF-3"); //UTF-3 : 한글 완성형 확장형 문자 집합으로, 인코딩 셋을 지정.

while((c = in.read()) != -1) {
	System.out.print((char) c);
}

 

FileWriter 사용 예

 c:\Temp\test.txt로의 문자 출력 스트림 생성

FileWriter fout = new FileWriter("c:\\Temp\\test.txt");

 

 파일 쓰기 - 문자 단위 쓰기

FileWriter fout = new FileWriter("c:\\Temp\\test.txt");
fout.write('A'); //문자 'A' 출력
fout.close();

 

 파일 쓰기 - 블록 단위 쓰기

char[] buf = new char [1024];
fout.write(buf, 0, buf.length); //buf[] 배열의 처음부터 배열 크기(1024개 문자)만큼 쓰기

 

 파일 쓰기 - write 메소드

write(char[] cbuf) //한 문자 또는 배열에 있는 내용을 모두 파일에 출력
write(char[] cbuf, int off, int len) //배열의 'off'번째부터 'len'개의 문자 출력
write(int c) //4바이트 데이터 중 하위 2바이트만 잘라서 넣음
write(String str) //문자열을 모두 파일에 출력
write(String str, int off, int len) //문자열의 'off'번째부터 'len'개의 문자 출력

 

3. 바이트 스트림 클래스

바이트 스트림

 바이트 단위의 바이너리 값을 읽고 쓰는 스트림.

 

문자 스트림을 다루는 클래스

 InputStream/OutputStream, FileInputStream/FileOutputStream, DataInputStream/DataOutputStream

 

InputStream/OutputStream

 추상 클래스로써, 직접 객체 생성이 불가능하다. (참조변수 생성은 가능.)

 

FileInputStream/FileOutputStream

 파일로부터 바이트 단위로 읽거나 저장하는 클래스로, 바이너리 파일의 입출력 용도이다.

 

DataInputStream/DataOutputStream

 보조스트림이다. 바이트 단위의 데이터를 우리가 원하는 형태의 데이터로 받거나, 우리가 원하는 형태의 데이터를 바이트 단위로 출력하여 파일에 기록하기 위한 스트림이다.

DataInputStream의 작동
DataOutputStream의 작동

 

4. 버퍼 입출력 스트림

버퍼 스트림

 버퍼란, 데이터를 가진 배열을 뜻한다. 버퍼가 없으면 1바이트나 1워드 단위의 처리만 가능하다. 하지만 버퍼를 가진 스트림 (=버퍼 스트림)이 있으면 입출력 데이터를 일시적으로 저장하는 버퍼를 이용하여 입출력 효율을 개선할 수 있다.

 

버퍼 입출력의 목적

 입출력 시 운영체제의 API 호출 횟수를 줄여 입출력 성능을 개선한다.

 

버퍼 스트림의 종류

 바이트 버퍼 스트림 : BufferedInputStream/BufferedOutputStream

 문자 버퍼 스트림 : BufferedReader/BufferedWriter

 

FileWriter 사용 예

BufferedOutputStream bout = new BufferedOutputStream(System.out, 20); 
//20바이트 크기의 버퍼를 설정하고, System.out 표준 스트림에 출력
//System.out : OutputStream을 상속한 PrintStream 타입의 필드 
FileReader fin = new FileReader("c:\\windows\\system.ini");

int c;
while ((c = fin.read() != -1) { //파일 전체를 읽어 화면에 출력
	bout.write((char)c);
}

fin.close();
bout.close();

 

5. File 클래스

File 클래스

 파일 + 디렉터리 정보를 가지는 클래스다. 파일 이름 변경, 디렉터리 생성 등의 파일 관리가 가능하지만 파일을 읽거나 쓸 수는 없다.

 

File 클래스 사용 예

 파일 객체 생성

File f = new File("c:\\windows\\system.ini"); //지정된 경로명에 있는 정보가 f에 저장

 

 파일 경로명

String filename = f.getName(); //"system.ini"
String path = f.getPath(); //"c:\\windows\\system.ini"
String parent = f.getParent(); //"c:\\windows"

 

 파일인지 디렉터리인지 구분

File f = new File("c:\\Temp");
File[] subfiles = f.listFiles(); //c:\\Temp 파일 및 서브디렉터리 리스트 얻기. 파일 내 파일의 리스트는 제공 x

for (int i=0; i< subfiles.length; i++){
	System.out.print(subfiles[i].getName()); //파일명 출력
    System.out.println("파일 크기:" + subfiles[i].length()); //크기 출력
}