기본 콘텐츠로 건너뛰기

방송대 방통대 Java프로그래밍 9강 - java.io 패키지와 스트림 - 요약 노트 시험족보 예상문제 - 올에이클래스

Java프로그래밍 9강 - java.io 패키지와 스트림

Java프로그래밍 9강 - java.io 패키지와 스트림

이번 강의에서는 Java 프로그램이 파일, 키보드, 화면과 데이터를 주고받는 통로인 스트림을 학습한다. 바이트 스트림과 캐릭터 스트림, 기본 스트림과 보조 스트림의 차이를 이해하고, 파일·콘솔 입출력에 필요한 java.io 클래스와 주요 메소드를 코드에 적용한다.

제1장 입출력 스트림의 개념

1. 스트림이란 무엇인가

Java 프로그램은 스트림을 통해 입출력을 수행한다. 입력 스트림은 데이터 생산자인 소스와 프로그램을 연결하고, 출력 스트림은 프로그램과 데이터 소비자인 목적지를 연결한다. 파일, 키보드, 화면, 메모리처럼 데이터의 출발지와 도착지가 달라도 스트림을 사용하면 유사한 방식으로 프로그램을 작성할 수 있다.

스트림은 데이터 생산자 또는 소비자와 프로그램 사이에서 데이터가 흐르는 통로이다. 데이터는 수도관을 따라 흐르듯이 정해진 한 방향으로 전달되며 순차적으로 접근한다. 따라서 입력과 출력에는 서로 다른 스트림이 필요하다.

핵심: 입력 스트림은 외부 데이터를 프로그램으로 읽어 오며 데이터 소스가 지정되어야 한다. 출력 스트림은 프로그램의 데이터를 외부로 내보내며 데이터 목적지가 지정되어야 한다.

2. 처리 단위에 따른 분류

스트림은 처리하는 데이터 단위에 따라 바이트 스트림과 캐릭터 스트림으로 나뉜다. 바이트 스트림은 byte 단위로 데이터를 처리하며 클래스 이름이 주로 InputStream 또는 OutputStream으로 끝난다. 캐릭터 스트림은 char 단위로 문자를 처리하며 클래스 이름이 주로 Reader 또는 Writer로 끝난다.

구분입력 계열출력 계열처리 단위
바이트 스트림InputStreamOutputStreambyte
캐릭터 스트림ReaderWriterchar

3. 기본 스트림과 보조 스트림

기본 스트림은 파일이나 메모리 같은 실제 입출력 대상과 직접 연결되어 입출력 기능을 제공한다. FileInputStream, FileOutputStream, FileReader, FileWriter가 대표적이다.

보조 스트림은 자체적으로 입출력 대상과 직접 연결되지 못한다. 대신 기본 스트림을 감싸 버퍼링, 기본 자료형 처리, 형식화 출력, 행 번호 관리, 바이트와 문자 간 변환 같은 부가 기능을 제공한다.

FileInputStream fis = new FileInputStream("text.txt");
BufferedInputStream bis = new BufferedInputStream(fis);

프로그램에서 스트림을 선택할 때는 먼저 입력인지 출력인지, 문자 단위인지 바이트 단위인지, 보조 기능이 필요한지를 결정한다. 보조 스트림이 필요하다면 기본 스트림 객체를 먼저 만들고 이를 보조 스트림 생성자의 인자로 전달한다.

제2장 바이트 스트림과 캐릭터 스트림

1. InputStream 클래스

InputStream은 바이트 단위 입력 스트림 클래스 중 최상위 추상 클래스이다. 하위 입력 클래스는 공통적으로 read(), available(), skip(), mark(), reset() 같은 메소드를 물려받는다.

메소드기능
abstract int read()입력 스트림에서 1바이트를 읽어 정수로 반환한다.
int read(byte[] b)여러 바이트를 배열에 저장하고 읽은 바이트 수를 반환한다.
int read(byte[] b, int off, int len)최대 len바이트를 읽어 배열의 off 위치부터 저장한다.
int available()현재 스트림에서 읽을 수 있는 바이트 수를 반환한다.
long skip(long n)입력 스트림에서 지정한 수만큼 바이트를 건너뛴다.
void mark(int readlimit)현재 읽기 위치를 표시한다.
void reset()mark()로 표시한 위치로 되돌린다.

인자 없는 read()는 1바이트를 읽지만 반환형이 int이다. 이렇게 해야 0부터 255까지의 바이트 값과 입력 끝을 뜻하는 -1을 함께 구분할 수 있다.

2. OutputStream 클래스

OutputStream은 바이트 단위 출력 스트림 클래스의 최상위 추상 클래스이다. write()로 데이터를 기록하고, flush()로 남은 데이터를 최종 목적지에 보내며, close()로 스트림과 자원을 닫는다.

메소드기능
abstract void write(int b)1바이트 데이터를 출력 스트림에 쓴다.
void write(byte[] b)바이트 배열의 모든 데이터를 쓴다.
void write(byte[] b, int off, int len)배열의 off부터 len바이트를 쓴다.
void flush()스트림에 남은 데이터를 최종 목적지로 보낸다.
void close()출력 스트림을 닫고 관련 자원을 반환한다.

3. Reader 클래스

Reader는 입력용 캐릭터 스트림의 최상위 추상 클래스이다. read()는 문자 하나를 읽고, read(char[] cbuf)는 여러 문자를 문자 배열에 저장한다. ready()는 읽을 데이터가 준비되었는지를 알려 주며, close()는 스트림을 닫는다.

메소드기능
int read()문자 하나를 읽어 반환한다.
int read(char[] cbuf)문자들을 배열에 저장하고 읽은 문자 수를 반환한다.
boolean ready()스트림에서 읽을 준비가 되었으면 true를 반환한다.
abstract void close()입력 스트림을 닫고 자원을 반환한다.

4. Writer 클래스

Writer는 출력용 캐릭터 스트림의 최상위 추상 클래스이다. 문자 하나, 문자 배열, 문자열 전체 또는 문자열의 일부를 출력할 수 있다. flush()close()의 역할은 바이트 출력 스트림과 같다.

메소드기능
void write(int c)문자 하나를 출력 스트림에 쓴다.
void write(char[] cbuf)문자 배열의 모든 문자를 쓴다.
void write(String str)문자열을 출력한다.
void write(String str, int off, int len)문자열의 off부터 len개의 문자를 쓴다.
void flush()남은 데이터를 최종 목적지로 보낸다.
abstract void close()출력 스트림을 닫고 자원을 반환한다.

제3장 File 클래스로 파일과 디렉터리 다루기

1. File 객체의 의미

File 클래스는 파일이나 디렉터리를 경로로 표현한다. 상대 경로나 절대 경로를 가질 수 있고, 해당 경로의 정보를 조회하거나 파일과 디렉터리를 생성·삭제하는 조작 기능을 제공한다. 이름과 달리 파일 내용을 읽고 쓰는 입출력 메소드는 제공하지 않으며, 실제 데이터 입출력에는 별도의 스트림 클래스가 필요하다.

File myFile1 = new File("D:\\workspace\\Test\\src");
File myFile2 = new File("notepad.exe");

Java 문자열에서 역슬래시 자체를 표현하려면 \\처럼 두 번 적는다. 운영체제의 경로를 나타내는 문자열과 Java 소스 코드 안의 이스케이프 표기를 구분해야 한다.

2. 주요 정보 조회와 조작 메소드

메소드기능
exists()지정된 경로의 파일 또는 디렉터리가 실제로 존재하는지 검사한다.
isDirectory()지정된 경로가 디렉터리인지 검사한다.
isFile()지정된 경로가 파일인지 검사한다.
getName()파일 또는 디렉터리의 이름을 반환한다.
getPath()경로 전체를 반환한다.
length()파일의 크기를 바이트 단위로 반환한다.
createNewFile()지정된 파일을 새로 생성한다.
delete()지정된 파일 또는 디렉터리를 삭제한다.
mkdir()마지막 단계의 디렉터리 하나를 생성한다.
mkdirs()필요한 상위 경로를 포함해 디렉터리들을 생성한다.
list()디렉터리 항목의 이름을 문자열 배열로 반환한다.
listFiles()디렉터리 항목을 File 객체 배열로 반환한다.
getParent()상위 디렉터리 이름을 반환한다.
getParentFile()상위 디렉터리를 File 객체로 반환한다.
static listRoots()파일 시스템의 루트 디렉터리를 File 배열로 반환한다.

3. 디렉터리 내용 출력 예

File file = new File("c:\\windows");
File[] files = file.listFiles();
int i = 0;
while (i < files.length) {
    System.out.print(files[i].getPath());
    System.out.println("\t" + files[i].length());
    i++;
}

listFiles()가 반환한 각 File 객체에서 전체 경로와 크기를 얻는다. 이 코드는 파일 내용을 읽는 것이 아니라 디렉터리 항목의 메타정보를 조회한다는 점이 중요하다.

제4장 RandomAccessFile과 임의 위치 접근

1. 랜덤 액세스 파일

RandomAccessFile은 파일의 임의 위치에서 읽기와 쓰기 연산을 지원한다. 파일을 열고, 파일 포인터가 가리키는 위치부터 바이트 단위로 데이터를 읽거나 쓴다. 순차 스트림처럼 처음부터 끝까지 이동할 필요 없이 seek()로 원하는 위치를 지정할 수 있어 큰 바이트 배열처럼 사용할 수 있다.

생성자는 File 객체나 파일 이름과 모드를 받는다. 모드 "r"은 읽기 전용이고 "rw"는 읽기와 쓰기를 모두 허용한다.

RandomAccessFile(File file, String mode)
RandomAccessFile(String name, String mode)

2. 주요 메소드와 파일 포인터

메소드기능
int read()현재 파일 포인터 위치에서 1바이트를 읽는다.
int read(byte[] b)파일의 바이트를 배열에 저장한다.
int read(byte[] b, int off, int len)최대 len바이트를 배열의 off부터 저장한다.
void seek(long pos)파일 포인터를 지정한 바이트 위치로 이동한다.
void write(byte[] b)바이트 배열의 내용을 파일에 쓴다.
void write(byte[] b, int off, int len)배열 일부를 현재 위치부터 파일에 쓴다.

3. 역순 읽기 예제

try (RandomAccessFile raf =
        new RandomAccessFile("c:\\java\\test.txt", "rw")) {
    for (int i = 0; i < 10; i++)
        raf.write(i);

    for (int i = 9; i >= 0; i--) {
        raf.seek(i);
        System.out.print(raf.read());
    }
} catch (Exception e) {
    System.out.println(e);
}

첫 반복문은 0부터 9까지를 각 1바이트로 기록한다. 두 번째 반복문은 파일 포인터를 9에서 0까지 역순으로 옮긴 뒤 그 위치의 바이트를 읽으므로 출력 결과는 9876543210이다.

제5장 파일 입력과 출력 스트림

1. FileInputStream과 FileOutputStream

FileInputStreamFileOutputStream은 파일에서 바이트 단위로 데이터를 읽고 쓰는 기본 스트림이다. 이미지나 오디오 파일처럼 이진 데이터를 다룰 때 특히 유용하다. 입력 스트림은 기존 파일과 연결되고, 출력 스트림은 대상 파일이 없으면 새로 생성해 연결한다.

클래스주요 생성자용도
FileInputStreamFileInputStream(File file)
FileInputStream(String name)
기존 파일에서 바이트 입력
FileOutputStreamFileOutputStream(String name)
FileOutputStream(File file, boolean append)
파일에 바이트 출력, append로 이어 쓰기 선택

2. 파일 복사 예제

File inFile = new File("c:\\Java\\Main.java");
File outFile = new File("c:\\Java\\FileTemp.java");

try (InputStream is = new FileInputStream(inFile);
     OutputStream os = new FileOutputStream(outFile)) {
    int nData = is.read();
    while (nData != -1) {
        os.write(nData);
        nData = is.read();
    }
} catch (Exception e) {
    System.out.println(e);
}

read()가 반환한 한 바이트를 write()로 새 파일에 기록한다. 입력 끝에 도달하면 read()-1을 반환해 반복이 종료된다. try-with-resources 구문은 정상 종료뿐 아니라 예외가 발생했을 때도 스트림 자원을 닫아 준다.

3. FileReader와 FileWriter

FileReaderFileWriter는 텍스트 파일을 문자 단위로 읽고 쓰는 기본 스트림이다. 문자 데이터를 대상으로 하므로 문자 처리 코드에서 바이트 스트림보다 목적이 분명하다.

클래스생성자 예
FileReaderFileReader(File file), FileReader(String fileName)
FileWriterFileWriter(File file), FileWriter(String fileName), FileWriter(File file, boolean append)

제6장 콘솔 입출력

1. Console 클래스

Console은 콘솔 입출력을 제공하는 클래스이다. 키보드 입력과 화면 출력을 편리하게 지원하고, 명령 프롬프트처럼 콘솔 환경에서 사용자와 상호작용할 때 사용한다. System.console()로 현재 환경에 연결된 Console 객체를 얻는다.

메소드기능
String readLine()콘솔에서 한 행을 문자열로 읽는다.
char[] readPassword()입력 내용을 화면에 보이지 않게 비밀번호를 읽는다.
PrintWriter writer()콘솔과 연결된 PrintWriter를 반환한다.
Reader reader()콘솔과 연결된 Reader를 반환한다.
printf()형식 문자열을 이용해 콘솔에 출력한다.

2. 이름과 비밀번호 입력 예제

String name;
char[] pw;
Console con = System.console();

System.out.print("name : ");
name = con.readLine();
System.out.print("password : ");
pw = con.readPassword();

con.printf("name : %s%n", name);
con.printf("password : %s%n", new String(pw));

readPassword()의 반환형은 문자열이 아니라 char[]이다. 예제에서는 출력하기 위해 new String(pw)로 변환한다. Console은 실행 환경에 따라 제공되지 않을 수 있으므로 사용 전 System.console()의 결과를 확인할 필요가 있다.

제7장 보조 스트림과 스트림 변환

1. 보조 스트림을 연결하는 원리

보조 스트림은 기본 스트림의 성능이나 편의성을 높인다. 자체적으로 파일과 연결되지 않고 생성자의 인자로 다른 스트림을 받기 때문에 기본 스트림을 보조 스트림으로 감싼다고 표현한다. 프로그램은 가장 바깥쪽 보조 스트림을 사용해 입출력하면 된다.

FileInputStream fis = new FileInputStream("text.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
제공 기능대표 보조 스트림
버퍼링BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter
Java 기본 자료형 읽기·쓰기DataInputStream, DataOutputStream
객체 읽기·쓰기ObjectInputStream, ObjectOutputStream
다양한 출력 형식PrintStream, PrintWriter
텍스트 행과 행 번호 처리LineNumberReader
바이트·문자 스트림 연결InputStreamReader, OutputStreamWriter

2. LineNumberReader

LineNumberReaderBufferedReader의 서브클래스로, 텍스트를 행 단위로 읽고 행 번호를 관리하는 기능을 제공한다. 주요 메소드는 read(), readLine(), getLineNumber(), skip(long)이다.

try (FileReader fr = new FileReader(
        new File("c:\\Java\\Main.java"));
     LineNumberReader rd = new LineNumberReader(fr)) {
    String line;
    while ((line = rd.readLine()) != null) {
        System.out.println(line);
    }
} catch (Exception e) {
    System.out.println(e);
}

readLine()은 한 행을 문자열로 반환하고 입력 끝에서는 null을 반환한다. 따라서 바이트 입력의 종료값 -1과 행 단위 문자 입력의 종료값 null을 구분해야 한다.

3. InputStreamReader

InputStreamReader는 바이트 입력 스트림을 캐릭터 입력 스트림으로 변환한다. 바이트로 들어오는 데이터를 지정한 문자 인코딩에 따라 문자로 해석하도록 연결하며, 생성자는 InputStreamCharset 또는 문자 집합 이름을 받는다.

try (InputStreamReader isr =
        new InputStreamReader(System.in, "euc-kr")) {
    int i;
    while ((i = isr.read()) != '끝') {
        System.out.print((char) i);
    }
} catch (Exception e) {
    System.out.println(e);
}

위 코드는 바이트 입력인 System.in을 문자 입력 스트림으로 변환하고 지정한 인코딩으로 문자를 읽는다. 반대 방향으로 캐릭터 출력 스트림을 바이트 출력 스트림에 연결할 때는 OutputStreamWriter를 사용한다.

구분: InputStreamReader는 바이트 입력 → 문자 입력 변환이고, OutputStreamWriter는 문자 출력 → 바이트 출력 변환이다.

핵심 개념 정리

  • 스트림은 데이터 생산자·소비자와 프로그램을 연결하는 단방향 데이터 통로이다.
  • 바이트 입력·출력의 최상위 추상 클래스는 InputStreamOutputStream이고, 문자 입력·출력은 ReaderWriter이다.
  • 기본 스트림은 실제 대상과 직접 연결되며, 보조 스트림은 다른 스트림을 감싸 성능과 기능을 보완한다.
  • File은 경로와 파일·디렉터리 정보를 표현하지만 파일 내용을 직접 읽고 쓰지는 않는다.
  • RandomAccessFile은 파일 포인터와 seek()를 이용해 임의 위치에서 바이트를 읽고 쓴다.
  • FileInputStream·FileOutputStream은 바이트 파일 입출력, FileReader·FileWriter는 문자 파일 입출력에 사용한다.
  • Console은 행 입력, 비밀번호 입력, 형식 출력을 지원한다.
  • LineNumberReader는 행 단위 읽기와 행 번호 기능을 제공하고, InputStreamReader는 바이트 입력을 문자 입력으로 변환한다.

최종 정리: Java 입출력 클래스는 먼저 방향, 처리 단위, 연결 대상을 기준으로 선택한다. 그다음 버퍼링·자료형 처리·행 번호·문자 인코딩 같은 기능이 필요하면 기본 스트림에 보조 스트림을 연결한다. 읽기의 종료값과 파일 포인터의 위치를 정확히 다루고, 사용이 끝난 스트림은 try-with-resources 또는 close()로 반드시 정리해야 한다.

예상문제 20선

1. 프로그램이 외부 데이터 소스로부터 데이터를 읽어 오는 통로는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
입력 스트림은 데이터 생산자인 외부 소스와 프로그램을 연결해 데이터를 읽어 온다.

2. 캐릭터 출력 스트림 클래스의 이름에 주로 붙는 말은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
문자 단위 출력 클래스는 Writer 계열이며, 문자 입력 클래스는 Reader 계열이다.

3. 보조 스트림에 관한 설명으로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
보조 스트림은 기본 스트림을 생성자 인자로 받아 성능이나 편의 기능을 덧붙인다.

4. InputStream.read()가 입력 끝에서 반환하는 값은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
인자 없는 read()는 바이트 값을 정수로 반환하고 더 읽을 데이터가 없으면 -1을 반환한다.

5. 출력 스트림에 남아 있는 데이터를 최종 목적지로 보내는 메소드는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
flush()는 출력 스트림 내부에 남은 데이터를 목적지로 밀어 보낸다.

6. 문자 배열에 여러 문자를 읽어 저장하는 Reader 메소드는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
Reader.read(char[])는 문자들을 읽어 문자 배열에 저장하고 읽은 문자 수를 반환한다.

7. File 클래스에 관한 설명으로 옳지 않은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
File은 경로와 메타정보를 다루며, 파일 내용의 입출력은 별도의 스트림이 담당한다.

8. 필요한 상위 디렉터리까지 함께 생성하는 File 메소드는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
mkdirs()는 경로에 필요한 상위 디렉터리까지 만들며, mkdir()는 마지막 디렉터리 하나를 만든다.

9. 디렉터리의 항목을 File 객체 배열로 반환하는 메소드는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
listFiles()는 각 항목을 File 객체로 반환하고, list()는 이름을 문자열로 반환한다.

10. RandomAccessFile의 파일 포인터를 지정한 위치로 옮기는 메소드는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
seek(long pos)는 파일 포인터를 지정한 바이트 위치로 직접 이동시킨다.

11. RandomAccessFile을 읽기와 쓰기가 모두 가능한 모드로 여는 문자열은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
"r"은 읽기 전용이고 "rw"는 읽기와 쓰기 겸용 모드이다.

12. 이미지와 같은 이진 파일을 바이트 단위로 읽는 데 알맞은 기본 스트림은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
FileInputStream은 파일에서 바이트 단위로 데이터를 읽는 기본 입력 스트림이다.

13. 파일 복사 반복문 while (nData != -1)에서 조건이 의미하는 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
-1은 바이트 입력의 끝을 뜻하므로 그 전까지 읽은 값을 출력 스트림에 쓴다.

14. 텍스트 파일을 문자 단위로 출력하는 기본 스트림은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
FileWriter는 텍스트 파일에 문자 단위 출력을 수행하는 기본 스트림이다.

15. Console에서 입력 문자가 화면에 표시되지 않도록 비밀번호를 읽는 메소드는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
readPassword()는 비밀번호를 노출하지 않고 읽으며 char[]를 반환한다.

16. Java 기본 자료형을 그대로 읽고 쓰는 기능을 제공하는 보조 스트림의 조합은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
DataInputStreamDataOutputStream은 Java 기본 자료형 단위의 입출력을 지원한다.

17. 객체를 스트림을 통해 읽고 쓰는 기능을 제공하는 클래스 조합은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
ObjectInputStreamObjectOutputStream은 객체 단위의 읽기와 쓰기를 지원하는 보조 스트림이다.

18. LineNumberReader에 관한 설명으로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
LineNumberReader는 행 단위 읽기와 현재 행 번호 관리 기능을 제공한다.

19. LineNumberReader.readLine()이 입력 끝에서 반환하는 값은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
행 단위 입력 메소드 readLine()은 더 읽을 행이 없으면 null을 반환한다.

20. 바이트 입력 스트림을 지정한 문자 인코딩의 캐릭터 입력 스트림으로 바꾸는 클래스는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
InputStreamReader는 바이트 입력과 문자 입력을 연결하며 문자 집합을 지정할 수 있다.

댓글