문자 스트림 클래스
- 문자 스트림은 2바이트의 유니코드 문자를 단위로 입출력
- 문자화되지 않는 바이너리 정보(ex: 이미지)들은 문자 스트림 클래스에서 처리 불가
※ 바이너리 코드: 컴퓨터가 이해할 수 있는 이진코드(0과 1로 구성)
바이트 코드: 가상 머신(VM)이 이해할 수 있는 이진코드
- 문자 입력 스트림은 바이트들을 전달받고 이 바이트들을 '로컬 문자 집합'에 있는 문자인지 비교하여 문자로 변환
- 로컬 문자 집합에서 찾을 수 없는 경우 문자가 아니거나 문자 집합이 잘못 설정되어 있는 경우임
FileReader 생성자
FileReader, Reader, InputStreamReader의 공통 주요 메소드
FileReader를 이용한 텍스트 파일 읽기
파일 입력 스트림 생성
FileReader fin = new FileReader("c:\\text.txt");
//FileReader로 파일 입력 스트림을 생성하고 c:\\test.txt 파일을 연결하는 코드
- FileReader의 생성자는 c:\test.txt 파일을 찾아 열고 파일과 스트림을 연결
- 이때 c:\test.txt 파일은 문자들로만 구성된 텍스트 파일
파일 읽기
int c;
while((c=fin.read())!=-1){ //문자 하나를 c에 읽어들임
System.out.println((char)c); //c를 화면에 출력
}
- fin.read()는 연결된 파일로부터 문자 하나를 읽어 리턴
- 파일의 끝(EOF, End Of File)을 만나면 -1을 리턴
※ 문자를 읽어들이는 데 char이 아닌 int 타입 변수를 사용하는 이유
- char로 리턴받게 되면 0xFF를 리턴하므로 EOF 처리 불가
- int로 0xFFFFFFFF를 리턴받아 강제 타입 변환
char[] buf = new char[1024]; //1KB
int n = fin.read(buf); //한 번에 1024개의 문자를 읽어 buf[]에 저장하고 실제 읽은 문자 수 리턴
- 파일이 큰 경우 한 번에 한 문자씩 읽으면 읽는 속도가 느림
- 한 번에 한 블록(버퍼 크기)만큼 읽는 read() 사용
- 파일에 남아 있는 문자의 개수가 1024개보다 작을 때, read()는 실제로 읽은 문자의 개수를 리턴
※ 버퍼란?
읽고 쓸 데이터를 저장하는 배열
스트림 닫기
fin.close();
- 파일 읽기가 더 이상 필요 없으면 close() 메소드를 호출하여 입력 스트림을 닫음
- 닫힌 스트림으로부터는 더 이상 읽을 수 없음
파일 입출력과 예외 처리
1. 파일 경로명이 틀린 경우
- FileReader 생성자는 FileNotFoundException을 발생시킴
FileReader fn = new FileReader("c:\\test.txt"); //FileNotFoundException 발생 가능
2. 파일 읽기, 쓰기, 닫기를 하는 동안 입출력 오류 발생
- read(), write(), close() 메소드는 IOException 예외 발생
int c = fin.read(); //IOException 발생 가능
>> try-catch 블록 필요
try{
FileReader fin = new FileReader("c:\\test.txt");
...
int c = fin.read();
...
fin.close();
} catch(FileNotFoundException e){
System.out.println("파일을 열 수 없음"); //생략 가능
} catch(IOException e){
System.out.println("입출력 오류");
}
- FileNotFoundException은 IOException을 상속받으므로 catch(IOException e){ }문만 있어도 무방
문자 집합과 InputStreamReader를 이용한 텍스트 파일 읽기
- InputStreamReader는 스트림에 입력되는 바이트 데이터를 문자 집합을 통해 문자로 변환
- 이를 위해 InputStreamReader 생성자에 문자 집합 지정 필요
- 읽어들인 바이트들이 문자 집합에 속하지 않는 경우 해독할 수 없는 글자가 됨
InputStreamReader 생성자
1. InputStreamReader로 문자 입력 스트림 생성
- InputStreamReader는 바이트 스트림을 전달받아 문자 정보로 변환하는 스트림 객체
FileInputStream fin = new FileInputStream("c:\\Temp\\hangul.txt");
- 텍스트 파일을 읽기 위해 바이트 파일 입력 스트림 생성
InputStreamReader in = new InputStreamReader(fin, "MS949");
//fin으로부터 읽어 들인 바이트들을 문자로 인코딩하기 위한 문자 집합을 MS949에 저장
- InputStreamReader 객체 생성
- 윈도우에서 디폴트로 사용하는 문자 집합이 MS949이므로 InputStreamReader 생성자에 MS949 문자 집합을 생성
2. 파일 읽기
- in.read()는 문자 집합의 인코딩 규칙에 따라 fin에게 파일로부터 필요한 바이트들을 읽도록 지시
- 읽어 들인 바이트들이 MS949 문자 집합에 정의된 문자인지 찾아 한글 문자를 리턴
+
라고 교재에 나와 있어서 적기는 했는데 MS949로 인코딩하면 오류가 납니다
MS949 대신 UTF-8을 사용해보세요
이제 보니 메모장에도 UTF-8로 돼 있네요(우측 하단)
fin=new FileInputStream("c:\\Temp\\hangul.txt");
in=new InputStreamReader(fin, "UTF8");
int c;
FileWriter를 이용한 텍스트 파일 쓰기
FileWriter와 OutputStreamWriter 생성자
FileWriter와 OutputStreamWriter 주요 메소드
예제 8-1 FileReader를 이용하여 c:\windows\system.ini 파일을 읽어 화면에 출력하는 프로그램 작성
import java.io.*;
public class FileReaderEx {
public static void main(String[] args) {
FileReader fin=null;
try {
fin=new FileReader("c:\\windows\\system.ini");
int c;
while((c=fin.read())!=-1) {
System.out.print((char)c);
}
fin.close();
}
catch(IOException e) {
System.out.println("입출력 오류");
}
}
}
>> 실행
예제 8-2 InputStreamReader을 이용하여 MS949 문자 집합으로 한글 텍스트 파일을 일고 출력
※ Temp 폴더에 hangul.txt 파일이 미리 작성되어 있어야 함
저는 UTF8로 했어요
import java. io.*;
public class FileReadHangulSuccess {
public static void main(String[] args) {
InputStreamReader in=null;
FileInputStream fin=null;
try {
fin=new FileInputStream("c:\\Temp\\hangul.txt");
in=new InputStreamReader(fin, "UTF8");
int c;
System.out.println("인코딩 문자 집합은 "+in.getEncoding()); //문자 집합 이름 리턴
while((c=in.read())!=-1){
System.out.print((char)c);
}
in.close();
fin.close();
}
catch(IOException e) {
System.out.println("입출력 오류");
}
}
}
>>실행
예제 8-3 InputStreamReader의 문자 집합을 US-ASCII로 지정하여 한글 파일을 읽고 출력
- 문자 집합 지정이 잘못된 예
import java.io.*;
public class FileReadingHangulFail {
public static void main(String[] args) {
InputStreamReader in=null;
FileInputStream fin=null;
try {
fin=new FileInputStream("c:\\Temp\\hangul.txt");
in=new InputStreamReader(fin, "US-ASCII");
int c;
System.out.println("인코딩 문자 집합은 "+in.getEncoding());
while((c=in.read())!=-1){
System.out.print((char)c);
}
in.close();
fin.close();
}
catch(IOException e){
System.out.println("입출력 오류");
}
}
}
>> 실행
예제 8-4 Scanner를 이용하여 입력받은 데이터를 c:\Temp\test.txt 파일에 저장하는 프로그램 작성
import java.util.*;
import java.io.*;
public class FileWriterEx {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
FileWriter fout=null;
int c;
try {
fout=new FileWriter("c:\\Temp\\test.txt");
while(true) {
String line=scanner.nextLine();
if(line.length()==0) break;
fout.write(line, 0, line.length()); //읽은 문자열 파일에 저장
fout.write("\r\n", 0, 2); //줄바꿈
}
fout.close();
}
catch(IOException e) {
System.out.println("입출력 오류");
}
scanner.close();
}
}
>>실행
이렇게 입력하면
Temp 폴더에 test.txt 파일이 생성되고 입력한 내용 저장
'java > 개념' 카테고리의 다른 글
버퍼 입출력과 파일 입출력 (0) | 2024.06.23 |
---|---|
바이트 스트림과 파일 입출력 (0) | 2024.06.20 |
입출력 스트림 (0) | 2024.06.19 |
제네릭과 배열 (0) | 2024.06.10 |
제네릭 만들기 (0) | 2024.06.10 |