Dev_bob

[JAVA]입출력 스트림과 파일 입출력 본문

전공수업정리/Java

[JAVA]입출력 스트림과 파일 입출력

킹대왕너구리 2024. 5. 27. 18:00

8.1 자바의 입출력 스트림

 

스트림 - 연속적인 데이터 흐름 혹은 데이터를 전송하는 소프트웨어 모듈

 

스트림 입출력 - 버퍼를 갖고 순차적으로 이루어지는 입출력

 

입력 스트림 - 입력 장치로부터 자바 프로그램으로 데이터를 전달

출력 스트림 - 출력 장치로 데이터 출력

 

입출력 스트림 특징

-스트림은 단방향 입니다. 입력과 출력을 동시에 하는 스트림은 없습니다.

-스트림의 양 끝에는 입출력 장치자바 응용프로그램이 연결됩니다.

자바 프로그램입력 스트림 출력 스트림 연결하고 입출력 스트림입출력 장치를 제어합니다.

-스트림을 통해 흘러가는 기본단위바이트문자 입니다.

-스트림은 선입선출, 즉 FIFO(first in first out) 구조이다.

 

--------------------------------------------------------------------------------------------------------------------

 

입출력 스트림

-바이트 스트림

-문자 스트림

-버퍼 스트림

-바이트 버퍼 스트림

-문자 버퍼 스트림

 

 

입출력 스트림 기본 단위

바이트 스트림 문자스트림
-바이트 스트림의 경우 : 바이트
입출력되는 데이터를 단순 바이트로 처리
클래스 이름이 공통적으로Stream으로 끝남
바이트를 단위로 다루는 스트림, 스트림에 들어오고 나가는 단순 바이너리(비트들)로 다룸.
문자이든 이미지 바이트든 상관 없음
-문자 스트림의 경우 : 문자(자바에서는 문자 1개-> 2바이트)
문자만! 입출력하는 스트림
문자가 아닌 바이너리 데이터는 스트림에서 처리 못함
클래스 이름이 공통적으로 Reader/Writer로 끝남
유니코드(2바이트) 문자를 입출력하는 스트림
문자로 표현되지 않은 데이터는 다루지 못함.
이미지, 동영상과 같은 바이너리 데이터는 입출력 불가
<바이트 스트림 클래스>
InputStream/OutputStream

추상클래스
바이트 스트림을 다루는 모든 클래스의 슈퍼 클래스
FileInputStream/FileOutputStream
파일로부터 바이트 단위로 읽거나 저장하는 클래스
바이너리 파일의 입출력 용도
DataInputStream/DataOutputStream
자바 기본 데이터 타입의 값을 바이너리 값 그대로 입출력
문자열도 바이너리 형태로 입출력
<문자 스트림을 다루는 클래스>
Reader/Writer
InputStreamReader/OutputStreamWriter
FileReader/FileWriter

 

스트림 연결

InputStreamReader rd = new InputStreamReader(System.in);

System.in - 표준 입력 스트림 (? s 1 입력) / System.in은 사용자 키 입력 받고 바이트 정보를 내보냅니다.

rd(InputStreamReader)-InputStreamReader의 객체인 rd는 바이트 스트림을 문자로 구성하여 프로그램으로 전달합니다.

 

문자 스트림 클래스

문자스트림 - 2바이트의 유니코드 문자 단위로 입출력하는 스트림

 

FileReader를 통한 텍스트 파일 읽기

FileReader 클래스 생성자, 메소드 : 텍스트 파일을 읽는데 사용됨

 

file과 스트림 연결

FileReader fin = new FileReader("c:\\test.txt");

FileReader 파일 입력 스트림 생성 , FileReader로 스트림을 파일(c:\test.txt)과 연결

FileReader의 생성자는 C:\test.txt파일을 찾아서 열고, 파일과 스트림을 연결한다.

위에서 언급했듯이, c:\test.txt파일은 문자들로만 구성된 텍스트 파일이다.

 

fin.read()

fin.read()는 연결된 파일로 부터 문자를 하나 읽어 리턴하며, 파일의 끝을 만나면 -1을 리턴한다.

fin.read()로 파일 전체를 읽어 화면에 출력하는 코드는 다음과 같다.

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

 

근데 이상한 점이 있다. char타입의 값을 읽어야하는데 왜 int타입의 변수 c를 사용하는 것일까?그 이유는 파일의 끝 (EOF)을 처리하는 과정에 있다.스트림이나 파일에 -1값이 있을 수 있다. 그렇다면 c=fin.read()!=-1에서 혼돈이 올 수 있다고 생각된다.하지만 이것은 아니다!int 타입의 -1 :  0xFFFFFFFF char 타입의 -1: 0x000000FF

 

블록read()

char [] buf=new char [1024]//1024는 1KB이다.
int n=fin.read(buf);//한번에 1024개의 문자를 읽어 buf[]에 저장하고 실제 읽은 문자수 리턴

파일의 큰 경우에 fin.read()를 사용하게 되면 읽는 속도가 너무 느리다. 이럴때는 fin.read(블록) 하여 블록만큼 읽는 read()를 활용하면 된다.

버퍼란 읽고 쓸 데이터를 저장하는 배열을 부르는 용어다. 문자의 개수가 1024개보다 작을때, read()는 읽은 문자의 개수를 리턴한다.

 

스트림 닫기 close()

파일 읽기가 필요 없으면 다음과 같이 close 메소드를 호출해 입력 스트림을 닫는다.

fin.close();

 

 

 

 

 

파일 입출력과 예외 처리

파일의 경로명이 틀린경우-FileNotFoundException 발생

파일 읽기,쓰기,닫기를 하는 동안 입출력 오류가 발생한 경우 - IOException 발생

 

import java.io.*; // 입출력 관련 클래스를 사용하기 위해 java.io 패키지를 임포트

public class FileReaderEx {

    public static void main(String[] args) {
        FileReader fin = null; // FileReader 타입의 변수 fin을 선언하고 초기화

        try {
            // "c:\\windows\\system.ini" 파일을 읽기 위해 FileReader 객체를 생성하고 fin 변수에 할당
            fin = new FileReader("c:\\windows\\system.ini");
            int c; // 파일에서 읽은 문자를 저장할 변수 c를 선언

            // 파일 끝까지 한 문자씩 읽어서 c에 저장, -1이면 파일 끝을 의미
            while ((c = fin.read()) != -1) {
                // 읽은 문자를 출력, (char)c로 캐스팅하여 문자로 출력
                System.out.print((char) c);            
            }
            // 파일 읽기가 끝나면 파일을 닫음
            fin.close();
        }
        // 입출력 과정에서 예외가 발생하면 이를 처리
        catch (IOException e) {
            // 예외가 발생하면 "입출력오류" 메시지를 출력
            System.out.println("입출력오류");
        }
    }
}

try catch문에서 IOException e만 다루는 이유는 FileNotFoundExceptionIOException의 하위 클래스이기 때문입니다. IOException을 캐치할 때 FileNotFoundException도 함께 처리됩니다.

 

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

InputStreamReader - 스트림에 입력되는 바이트 데이터를 문자 집합을 통해 문자로로 변환한다.

따라서 문자집합을 지정해야 한다. 만약 읽어 들인 바이트들이 문자 집합에 속하지 않는 경우 해독할 수 없는 글자가 된다.

 

생성자 설명
InputStreamReader(InputStream in) in으로부터 읽는 기본 문자 집합의 InputStreamReader생성
InputStreamReader(InputStream in,Charset cs) in으로부터 읽는 cs 문자 집합의 InputStreamReader생성
InputStreamReader(InputStream in,String charsetName) in으로부터 읽는 charsetName 문자 집합의 InputStreamReader 생성

 

InputStreamReader로 문자 입력 스트림 생성

//텍스트 파일 읽기
FileInputStream fin = new FileInputStream("c:\\Temp\\hangul.txt");
//객체 생성하기
InputStreamReader in = new InputStreamReader(fin,"Ms949");

fin으로 읽어 들인 바이트들을 '한글 확장 완성형 문자 집합'에 있는 코드로 저장 -> MS949

 

MS949는 한글 문자를 표현하기 위해 사용되었던 인코딩 방식 중 하나로, 주로 윈도우 환경에서 사용되었습니다. 현재는 유니코드(UTF-8)로 대부분 전환되었지만, MS949로 인코딩된 기존 데이터나 문서를 처리할 필요가 있을 때 사용됩니다.

import java.io.*;

public class FileReadHangulSuccess {

	public static void main(String[] args) {
		InputStreamReader in=null;	//문자 스트림을 다루는 클래스 InputStreamReader
		FileInputStream fin = null;//바이트 스트림을 다루는 모든 클래스의 슈퍼클래스
		
		try {
			fin=new FileInputStream("C:\\Temp\\hangul.txt");//파일 가져오기
			in=new InputStreamReader(fin,"MS949");//fin으로부터 읽어들인 바이트를 문자집합 "MS949"를 통해 한글문자를 리턴함
			int c;
			
			System.out.println("인코딩 문자 집합은"+in.getEncoding());	//getEncoding은 in 객체의 문자집합의 이름을 리턴합니다.
			while((c=fin.read())!=-1) {//문자 값이 EOF가 아닐때까지 한글자씩 읽기
				System.out.print((char)c);	//문자 하나씩 출력
			}
			in.close();//InputStreamReader 스트림 닫기
			fin.close();//FileInputStream 스트림닫기
		}catch(IOException e) {
			System.out.println("입출력오류");	//입출력오류 예외처리
		}

	}

}

 

FileWriter를 이용한 텍스트 파일 쓰기

 

파일 출력 스트림 생성

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

 

FileWriter 생성자는 c:\Temp\test.txt 파일을 열어 스트림과 연결한다. 파일이 없다면 빈 파일 생성한다. 이미 파일이 있는 경우 덮어쓰기를 진행한다.

 

파일쓰기

 

fout스트림의 write() 메소드를 이용하면 문자 단위로 파일에 저장할 수 있다.

fout.write('A');

한글자씩 저장할 수도 있지만, 문자 단위로 파일에 저장할 수도 있다. (한블록씩)

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

 

스트림닫기

fout.close();

 

예제 키보드 입력을 파일로 저장하기

import java.io.*;	//입출력을 위한 클래스를 사용하기 위해 java.io.패키지를 임포트
import java.util.*; // 유틸리티 클래스를 사용하기 위해 java.util. 패키지를 임포트

public class FileWriterEx {

	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);//사용자로부터 입력을 받기 위해 객체 생성
		FileWriter fout=null;//FileWriter 타입 변수 fout 선언 및 초기화
		try {
			fout=new FileWriter("c:\\Temp\\test.txt");//지정된 파일에 쓰기위한 FileWriter 객체 생성
			while(true) {//무한루프
				String line=scanner.nextLine();//사용자로부터 한줄 입력받기
				if(line.length()==0)//Enter를 치면 입력된 문자열의 길이가 0이됨
					break;//루프종료
				fout.write(line,0,line.length());//입력된 문자열을 파일에 씀, 0부터 문자열의 길이만큼
				fout.write("\r\n",0,2);//윈도우 방식 줄바꿈 문자를 파일에 씀
			}
			fout.close();//FileWriter 객체 닫기 
		}catch(IOException e) {
			System.out.println("입출력 오류");
		}
		scanner.close();

	}

}

 

버퍼 스트림

버퍼

컴퓨팅에서 버퍼(buffer, 문화어: 완충기억기)는 데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 그 데이터를 보관하는 메모리의 영역이다. 버퍼링(buffering)이란 버퍼를 활용하는 방식 또는 버퍼를 채우는 동작을 말한다.

 

바이트 버퍼 스트림 문자 버퍼 스트림
바이트 단위의 바이너리 데이터를 처리하는 버퍼 스트림 유니코드의 문자 데이터만 처리하만 처리하는 버퍼 스트림
BufferedInputStream/BufferedOutputStream BufferedReader/BufferedWriter

 


버퍼 출력 스트림 생성

BufferedOutputStream out=new BufferedOutputStream(System.out,5);

스트림 출력

fin=new FileReader("C:\\Temp\\test2.txt");	//파일 읽어오기
BufferedOutputStream out=new BufferedOutputStream(System.out,5);//버퍼의 크기를 5로 설정 바이트 단위로 5만큼 읽어 문자 출력
while ((c=fin.read())!=-1) {//fin.read()로 한글자씩 있는데 EOF가 나올 떄까지 반복
	out.write(c);//c에서 읽은 값을 out(버퍼 스트림)에 쓴다.
}

 

버퍼에 남아있는 데이터 출력

out.flush();//버퍼에 남아있는 문자 모두 출력

스트림 닫기

fin.close();//문자스트림 클래스 FileReader 닫기
out.close();//바이트 스트림 BufferedOutputStream 닫기

 

적용예제

import java.io.*;
import java.util.Scanner;


public class BufferedIOEx {
	public static void main(String[] args) {
		FileReader fin=null;//FileReader 변수 fin 선언
		int c;
		try {
			fin=new FileReader("C:\\Temp\\test2.txt");	//파일 읽어오기
			BufferedOutputStream out=new BufferedOutputStream(System.out,5);//버퍼의 크기를 5로 설정 바이트 단위로 5만큼 읽어 문자 출력
			//BufferedOutputStream out=new BufferedOutputStream(new OutputStreamWriter(System.out),5); 한글을 출력하려면 다음과 같이 하면 됨.
			while ((c=fin.read())!=-1) {//fin.read()로 한글자씩 있는데 EOF가 나올 떄까지 반복
				out.write(c);//c에서 읽은 값을 out(버퍼 스트림)에 쓴다.
			}
			//파일 데이터가 모두 출력된 상태
			new Scanner(System.in).nextLine();//Enter키를 누른다면
			out.flush();//버퍼에 남아있는 문자 모두 출력
			fin.close();//문자스트림 클래스 FileReader 닫기
			out.close();//바이트 스트림 BufferedOutputStream 닫기
		}catch(IOException e) {
			e.printStackTrace();
		}
	}
}

 

File 클래스

File 클래스

파일 관리 작업을 지원하는 클래스, File 클래스의 경로명은 java.io.File이다.

java.io경로에 있다고 해서 입출력 기능이 있지는 않다.

getName(),getPath(),getParent()

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

 

isFile(), isDirectory()

if(f.isFile()) // 파일인 경우
	System.out.println(f.getPath() + "는 파일입니다.");
else if(f.isDirectory()) // 디렉터리인 경우
	System.out.println(f.getPath() + "는 디렉터리입니다.");

관련 예제

import java.io.File;

public class FileEx {
	
	public static void listDirectory(File dir) {//디렉토리에 포함된 파일,서브디렉토리이름, 크기, 수정시간 출력 메소드
		System.out.println("-----"+dir.getPath()+"의 서브리스트입니다.-----");
		
		File[] subFiles=dir.listFiles();//디렉토리에 포함된 파일과 디렉토리 이름의 리스트 얻기
		
		for(int i=0;i<subFiles.length;i++) {
			File f=subFiles[i];
			long t=f.lastModified();//마지막으로 수정된 시간
			System.out.print(f.getName());
			System.out.print("\t파일크기:"+f.length());
			System.out.printf("\t수정한시간:%tb %td %ta %tT\n",t,t,t,t);//포멧출력
			
		}
	}

	public static void main(String[] args) {
		File f1=new File("C:\\windows\\system.ini");//파일 받아오기
		System.out.println(f1.getPath()+", "+f1.getParent()+", "+f1.getName());//path는 경로, getParent는 부모경로,getName은 파일 이름
		
		String res="";//String 변수 res 빈칸으로 초기화
		if(f1.isFile()) res="파일";//파일인지 확인하고 초기화
		else if(f1.isDirectory()) res="디렉토리";//디렉토리인지 확인하고 초기화
		System.out.println(f1.getPath()+"는 "+res + "입니다.");
		
		File f2=new File("c:\\Temp\\java_sample");//새로 만들고자 하는 디렉토리 생성
		if(!f2.exists()) {
			f2.mkdir();//존재하지 않으면 디렉토리 생성
		}
		listDirectory(new File("c:\\Temp")); //c:\Temp에 있는 파일 리스트 출력
		f2.renameTo(new File("C:\\Temp\\javasample")); //이름 변경
		
		listDirectory(new File("c:\\Temp"));
		
	}

}

 

'전공수업정리 > Java' 카테고리의 다른 글

[JAVA]자바 GUI기초, AWT와 스윙(Swing)  (4) 2024.06.02
[JAVA]StringBuffer 클래스  (0) 2024.05.16
[JAVA]String 클래스  (2) 2024.05.15
[JAVA]Object class,프로세스,스레드,toString(),equal()  (1) 2024.05.15
[JAVA] 모듈  (2) 2024.05.10