자바 개발자 일기 19일차 (FileInputStream)

Shy·2024년 1월 23일

아이티윌

목록 보기
19/22

FileInputStream

FileInputStream은 자바에서 파일로부터 바이트 단위로 데이터를 읽어들이는 데 사용되는 클래스이다.

java.io 패키지에 속해 있으며, 입력 스트림의 하나로, 파일로부터 바이트 단위의 입력을 받는데 적합하다.

특징

  1. 바이트 기반 스트림
    • FileInputStream은 바이트 단위로 데이터를 읽어들인다. 따라서 텍스트 파일 뿐만 아니라 이미지, 비디오 파일과 같은 이진 데이터도 읽을 수 있다.
  2. 파일과의 연결
    • 이 클래스의 객체를 생성할 때, 읽고자 하는 파일의 경로를 지정해야 한다. 파일이 존재하지 않으면 FileNotFoundException이 발생한다.
  3. 읽기 작업
    • read() 메서드를 사용하여 파일로부터 데이터를 읽어들인다. 이 메서드는 읽어들인 바이트 데이터를 반환하거나, 파일 끝에 도달했을 때 -1을 반환한다.
  4. 자원 해제
    • 파일 작업을 마친 후에는 반드시 close() 메서드를 호출하여 자원을 해제해야 한다. 이는 파일 핸들러 누수를 방지하는 데 중요하다.

기본 코드

import java.io.FileInputStream;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("example.txt");
            
            int i;
            while ((i = fis.read()) != -1) {
                System.out.print((char)i);
            }
            
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

이 예제에서는 example.txt 파일을 열어 그 내용을 바이트 단위로 읽고 콘솔에 출력한다. 파일의 끝에 도달할 때까지 read() 메서드를 반복적으로 호출하며, 작업을 마친 후에 close() 메서드로 스트림을 닫는다.

기본 예제 (read)

public class FileInputStream_Ex1 {

    public static void main(String[] args) {
        // 'temp.txt' 파일을 참조하는 File 객체 생성
        File file = new File("temp.txt");
        
        // FileInputStream 객체 선언
        FileInputStream fis = null;
        try {
            // FileInputStream 객체를 생성하여 파일과 연결
            fis = new FileInputStream(file);
            // 파일을 성공적으로 찾아 읽을 준비가 됨을 알림
            System.out.println(">> 파일을 찾아서 읽을 수 있는 객체 생성----");
            
            // 파일에서 첫 번째 바이트를 읽어서 출력
            int readValue = fis.read();
            // 읽은 바이트 값을 정수 형태로 출력
            System.out.println("read() int 값 : " + readValue);
            // 읽은 바이트 값을 문자(char) 형태로 출력
            System.out.println("(char)read() : " + (char)readValue);
            
            // 파일의 나머지 내용을 읽어 화면에 출력
            System.out.println("--- 전체 데이터 읽어서 화면 출력 ----");
            while (true) {
                // 파일에서 바이트를 읽음. 파일 끝에 도달하면 -1을 반환
                readValue = fis.read();
                if (readValue == -1) break; // 파일 끝에 도달했으므로 읽기 종료
                // 읽은 바이트 값을 정수 형태로 출력
                System.out.println("read() int 값 : " + readValue);
                // 읽은 바이트 값을 문자(char) 형태로 출력
                System.out.println("(char)read() : " + (char)readValue); 
            }
            
        } catch (FileNotFoundException e) {
            // 파일이 없을 경우 예외 처리
            System.out.println("[예외발생] " + e.getMessage());
        } catch (IOException e) {
            // 입출력 처리 중 발생하는 예외 처리
            e.printStackTrace();
        } finally {
            // FileInputStream 객체를 닫아 자원 해제
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    // 파일 닫기 과정 중 예외 처리
                    e.printStackTrace();
                }
            }
        }
        
        // 프로그램 종료 메시지 출력
        System.out.println(">>> main() 끝-------------------");
        /* temp.txt
		 * ABCD
		 * 1234
		 * !@#$
		 */

    }
}
>> 파일을 찾아서 읽을 수 있는 객체 생성----
read() int 값 : 65
(char)read() : A
--- 전체 데이터 읽어서 화면 출력 ----
read() int 값 : 66
(char)read() : B
read() int 값 : 67
(char)read() : C
read() int 값 : 68
(char)read() : D
read() int 값 : 10
(char)read() : 

read() int 값 : 49
(char)read() : 1
read() int 값 : 50
(char)read() : 2
read() int 값 : 51
(char)read() : 3
read() int 값 : 52
(char)read() : 4
read() int 값 : 10
(char)read() : 

read() int 값 : 33
(char)read() : !
read() int 값 : 64
(char)read() : @
read() int 값 : 35
(char)read() : #
read() int 값 : 36
(char)read() : $
>>> main() 끝-------------------

기본예제2

package com.mystudy.io2_fileinputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStream_Ex2 {

    public static void main(String[] args) {
        // 'file/test01.txt' 파일을 참조하기 위한 File 객체 생성
        File file = new File("file/test01.txt");

        // FileInputStream 객체를 위한 참조 변수 선언
        FileInputStream fis = null;
        
        try {
            // FileInputStream 객체 생성. 파일 경로를 직접 문자열로 전달
            fis = new FileInputStream("file/test01.txt");
            // FileInputStream 객체가 성공적으로 생성되었음을 출력
            System.out.println("fis : " + fis );
            
            // 파일에서 데이터를 읽고 출력하는 부분
            int readValue;
            while ((readValue = fis.read()) != -1) {
                // 읽은 데이터를 문자(char)로 변환하여 출력
                System.out.print((char)readValue);
            }
            
        } catch (FileNotFoundException e) {
            // 파일을 찾을 수 없는 경우의 예외 처리
            e.printStackTrace();
        } catch (IOException e) {
            // 파일 읽기 중 발생하는 입출력 예외 처리
            e.printStackTrace();
        } finally {
            // FileInputStream 객체를 닫아 리소스를 해제
            try {
                if (fis != null) fis.close();
            } catch (IOException e) {
                // 파일 닫기 과정 중 발생하는 예외 처리는 여기서 처리
                e.printStackTrace();
            }
        }
       	/* file/test01.txt
		 * ABCDEF
		 * 1234
		 * !@#$
		 */
    }
}
fis : java.io.FileInputStream@15db9742
ABCDEF
1234
!@#$

기본예제3 (byte[] 활용)

package com.mystudy.io2_fileinputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;

public class FileInputStream_Ex3_1 {

    public static void main(String[] args) {
        // 'file/test01.txt' 파일을 참조하기 위한 File 객체 생성
        File file = new File("file/test01.txt");
        
        // FileInputStream 객체를 위한 참조 변수 선언
        FileInputStream fis = null;
        
        try {
            // FileInputStream 객체 생성. File 객체를 사용
            fis = new FileInputStream(file);
            
            // 파일에서 데이터를 읽기 위한 바이트 배열 생성
            byte[] bytes = new byte[10];
            // 배열의 초기 상태 출력 (모든 값이 0으로 초기화됨)
            System.out.println("bytes : " + Arrays.toString(bytes));
            
            // read(byte[] b) 메소드를 사용하여 바이트 배열로 데이터 읽기
            int readCount = fis.read(bytes);
            // 배열에 읽힌 데이터의 수 출력
            System.out.println("읽은갯수 : " + readCount);
            // 읽힌 데이터가 저장된 배열 상태 출력
            System.out.println("bytes : " + Arrays.toString(bytes));
            // 읽힌 데이터를 바이트 단위로 출력하고, 문자로 변환하여 출력
            for (int i = 0; i < readCount; i++) {
                System.out.println("int : " + bytes[i] + ", char : " + (char)bytes[i]);
            }
            System.out.println("---------");
            
            // 다시 한번 데이터를 읽어 출력하는 과정 반복
            readCount = fis.read(bytes);
            System.out.println("읽은갯수 : " + readCount);
            System.out.println("bytes : " + Arrays.toString(bytes));
            for (int i = 0; i < readCount; i++) {
                System.out.println("int : " + bytes[i] + ", char : " + (char)bytes[i]);
            }
            System.out.println("---------");
            
            // 마지막으로 데이터를 읽고 출력
            readCount = fis.read(bytes);
            System.out.println("읽은갯수 : " + readCount);
            System.out.println("bytes : " + Arrays.toString(bytes));
            for (int i = 0; i < readCount; i++) {
                System.out.println("int : " + bytes[i] + ", char : " + (char)bytes[i]);
            }
            System.out.println("---------");
            
        } catch (FileNotFoundException e) {
            // 파일을 찾을 수 없을 때 예외 처리
            e.printStackTrace();
        } catch (IOException e) {
            // 입출력 과정 중 오류 발생 시 예외 처리
            e.printStackTrace();
        } finally {
            // FileInputStream 객체를 닫아 리소스 해제
            try {
                if (fis != null) fis.close();
            } catch (IOException e) {
                // 파일 닫기 과정 중 오류 발생 시 예외 처리
            }
        }
    }
}
bytes : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
읽은갯수 : 10
bytes : [65, 66, 67, 68, 69, 70, 10, 49, 50, 51]
int : 65, char : A
int : 66, char : B
int : 67, char : C
int : 68, char : D
int : 69, char : E
int : 70, char : F
int : 10, char : 

int : 49, char : 1
int : 50, char : 2
int : 51, char : 3
---------
읽은갯수 : 6
bytes : [52, 10, 33, 64, 35, 36, 10, 49, 50, 51]
int : 52, char : 4
int : 10, char : 

int : 33, char : !
int : 64, char : @
int : 35, char : #
int : 36, char : $
---------
읽은갯수 : -1
bytes : [52, 10, 33, 64, 35, 36, 10, 49, 50, 51]
---------

반복문 처리(내 코드)

package com.mystudy.io2_fileinputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;

public class FileInputStream_Ex3_2_my {

    public static void main(String[] args) {
        // 'file/test01.txt' 파일을 참조하기 위한 File 객체 생성
        File file = new File("file/test01.txt");
        
        // FileInputStream 객체를 위한 참조 변수 선언
        FileInputStream fis = null;
        
        try {
            // FileInputStream 객체 생성
            fis = new FileInputStream(file);
            
            // 파일에서 데이터를 읽기 위한 바이트 배열 생성
            byte[] bytes = new byte[10];
            // 배열의 초기 상태 출력
            System.out.println("bytes : " + Arrays.toString(bytes));
            
            // read(byte[] b) 메소드를 사용하여 바이트 배열로 데이터 읽기
            int readCount = fis.read(bytes);
            
            // do-while 루프를 사용하여 파일 끝까지 데이터 읽기
            do {
                // 읽힌 데이터를 바이트 단위로 출력하고, 문자로 변환하여 출력
                for (int i = 0; i < readCount; i++) {
                    System.out.println("int : " + bytes[i] + ", char : " + (char)bytes[i]);
                }
                // 다음 데이터 읽기
                readCount = fis.read(bytes);
            } while(readCount != -1); // 파일 끝에 도달할 때까지 반복
            
        } catch(FileNotFoundException e) {
            // 파일을 찾을 수 없을 때 예외 처리
            e.printStackTrace();
        } catch(IOException e) {
            // 입출력 과정 중 오류 발생 시 예외 처리
            e.printStackTrace();
        } finally {
            // FileInputStream 객체를 닫아 리소스 해제
            try {
                if(fis != null) fis.close();
            } catch(IOException e) {
                // 파일 닫기 과정 중 오류 발생 시 예외 처리
                e.printStackTrace();
            }
        }
    }
}
bytes : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
int : 65, char : A
int : 66, char : B
int : 67, char : C
int : 68, char : D
int : 69, char : E
int : 70, char : F
int : 10, char : 

int : 49, char : 1
int : 50, char : 2
int : 51, char : 3
int : 52, char : 4
int : 10, char : 

int : 33, char : !
int : 64, char : @
int : 35, char : #
int : 36, char : $

반복문 처리(강사님 코드)

package com.mystudy.io2_fileinputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;

public class FileInputStream_Ex3_2 {

    public static void main(String[] args) {
        // 실습: FileInputStream_Ex3_1 파일을 반복문으로 변경
        FileInputStream fis = null;
        
        try {
            // 0. 사용할 파일 객체 생성
            File file = new File("file/test01.txt"); // 'file/test01.txt' 파일 참조를 위한 File 객체 생성
            
            // 1. 파일을 읽어서 작업할 객체 생성(FileInputStream)
            fis = new FileInputStream(file); // 파일로부터 데이터를 읽기 위한 FileInputStream 객체 생성
            
            // 2. 객체 사용 파일데이터 읽어서 화면 출력
            byte[] bytes = new byte[10]; // 읽은 데이터를 저장할 바이트 배열 생성

            // 파일에서 데이터를 읽고 화면에 출력하는 while 루프
            int readCnt;
            while ((readCnt = fis.read(bytes)) != -1) { // 파일 끝에 도달할 때까지 반복
                // 읽은 데이터를 문자(char)로 변환하여 출력
                for (int i = 0; i < readCnt; i++) {
                    System.out.print((char) bytes[i]);
                }
            }
            
        } catch (FileNotFoundException e) {
            // 지정된 파일이 존재하지 않을 때의 예외 처리
            e.printStackTrace();
        } catch (IOException e) {
            // 파일 읽기 과정 중 오류 발생 시의 예외 처리
            e.printStackTrace();
        } // 주의: 여기에 리소스 해제를 위한 finally 블록이 추가되어야 함
    }
}
ABCDEF
1234
!@#$

파일로부터 바이트 단위의 입력을 받는데 적합하다?

그럼 한 글자당으로 입력 받는데 적절하다는 것인가?

맞다. FileInputStream은 파일에서 데이터를 바이트 단위로 읽는 데 적합하다는 뜻이다. 이것은 한 글자를 읽는 것과 관련이 있을 수 있다. 텍스트 파일의 경우, 대부분의 문자가 바이트로 표현된다. 하지만 이것은 문자 인코딩에 따라 달라질 수 있다. 예를 들어, ASCII 인코딩을 사용하는 영어 문자는 대부분 한 글자당 한 바이트를 사용하지만, UTF-8 인코딩을 사용하는 한글은 한 글자당 여러 바이트를 사용할 수 있다.

FileInputStream을 사용하여 텍스트 파일을 읽을 때, 각 바이트는 해당하는 문자로 해석된다. 그러나 이것은 문자 인코딩에 따라 다르게 해석될 수 있으므로, 정확한 문자 읽기를 위해서는 적절한 인코딩을 고려해야 한다. 또한, 이진 파일을 읽을 때에는 바이트 단위의 데이터가 문자로 해석되지 않고 원시 데이터로 처리된다.

profile
신입사원...

0개의 댓글