HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤩
개발
/
Java
Java
/
💯
Java 기본
/JDK API/
🥍
java.io
🥍

java.io

입출력 I/O 스트림입출력 스트림의 구분바이트 단위 스트림과 문자단위 스트림System클래스의 표준 입출력 멤버InputStreamScanner vs BufferedReader기반 스트림과 보조스트림BufferedInputStream과 BufferedOutputStream(보조 스트림)DataInputStream과 DataOutputStream(보조 스트림)ByteArrayInputStream vs byte[]직렬화(serialization)SerializableExternalizable그외 입출력 클래스들File ManagementFile classFileNotFoundException 발생 시ClassPath에서 File 읽기Java SDKApplicationContext 의 ResourceLoader 인터페이스 이용File로 부터 텍스트 읽기File에 텍스트 쓰기Creating and deleting files and directoriesApache Commons FileUtils and IOUtils
InputStream이란?
java.io vs java.nio

입출력 I/O 스트림

https://www.tutorialspoint.com/java/java_files_io.htm
  • A stream can be limited or endless
  • Java I/O stream은 바이트기반 or 문자기반(character-based) 둘 다 가능함(data를 raw byte로 이해할 것이냐, 문자로 이해할 것이냐)
  • 입출력은 입력을 받는 대상이 뭔지 출력을 하는 대상이 뭔지에 따라 달라지는데 이를 스트림을 통해 추상화하는것(바이트가 오고 가게 됨)
    • 입출력이 구현되는 곳 : 파일디스크, 키보드, 마우스, 네트웍, 메모리 등 모든 자료가 입력되고 출력되는 곳

입출력 스트림의 구분

  • 대상 기준 : 입력 스트림 / 출력 스트림
    • 입력 스트림 : FileInputStream, FileReader, BufferedInputStream, BufferedReader 등
    • 출력 스트림 : FileOutputStream, FileWriter, BufferedOutputStream, BufferedWriter 등
  • 자료의 종류 : 바이트 스트림 / 문자 스트림(문자 단위로 핸들링 할때는 인코딩이 중요함)
  • 기능 : 기반 스트림/ 보조 스트림

바이트 단위 스트림과 문자단위 스트림

  • 바이트 스트림(*Input*, *Output*)
    • FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream 등
      • ObjectInputStream : serialize된 객체 파일을 deserialize할 때 이용
      • PipedInputStream : thread간의 communication을 위해 사용하는 input stream. 한 Thread에서 읽고 다른 Thread로 쓰기작업
      • PrintStream : 데이터를 문자들로 출력하는 기능을 가진 OutputStream
  • 문자 스트림(*read, *write)
    • FileReader, FileWriter, BufferedReader, BufferedWriter, CharArrayReader, CharArrayWriter, InputStreamReader, OutputStreamWriter, PipedReader, PipedWriter, StringReader, StringWriter,,

System클래스의 표준 입출력 멤버

  • System.out.println() : 표준 출력(모니터) 스트림
    • out 변수의 타입이 PrintStream
  • System.in : 표준 입력(키보드) 스트림
    • System.in.read() : 한바이트씩 읽음
      • 60을 입력하면, 6에 해당하는 컴퓨터에서의 비트값인 54가 반환, 0에 해당하는 48이 반환됨 ⇒ 숫자를 그대로 입력받고 싶으면 Scanner의 nextInt 메서드 사용하기
    • 한글 안깨지게 출력하려면 2바이트씩 읽어주어야함 (InputStreamReader)
  • System.err : 표준 에러 출력(모니터) 스트림

InputStream

  • 바이트 단위 입력 스트림 최상위 추상 클래스(한글은 2바이트씩이라 한글입력스트림에 대해서는 깨지게 출력됨)

Scanner vs BufferedReader

  • Scanner는 토큰 기반으로 input에서 읽어들이고, BufferedReader는 한 줄 단위로 읽고 그 줄에서 토큰으로 끊어서 읽어들이기 때문에 Scanner가 읽는데 시간이 조금 더 걸림
  • Scanner가 입력 데이터를 구문 분석하고, BufferedReader는 단순히 문자 시퀀스를 읽기 때문에 스캐너에 비해 조금 더 빠름
  • Scanner로 읽을때 memory를 되게 많이 잡아먹는 이슈가 있음 - 이유가 뭘까..?

기반 스트림과 보조스트림

  • 기반 스트림
    • 대상에 직접 자료를 읽고 쓰는 기능의 스트림
    • input : 쓸 대상, 읽을 대상
  • 보조 스트림
    • 직접 읽고 쓰는 기능은 없이 추가적인 기능을 더해주는 스트림
    • input: InputStream, OutputStream
  • 보조 스트림은 직접 읽고 쓰는 기능은 없으므로 항상 기반 스트림이나 또 다른 보조 스트림을 생성자의 매개 변수로 포함함
예시 : new BufferedReader(new InputStreamReader(System.in));
예시 : new BufferedReader(new InputStreamReader(System.in));

BufferedInputStream과 BufferedOutputStream(보조 스트림)

DataInputStream과 DataOutputStream(보조 스트림)

  • 자료가 메모리에 저장된 상태 그대로 읽거나 쓰는 스트림
    • short 정수면 short 정수.

ByteArrayInputStream vs byte[]

  • input이 항상 byte[] 면, stream을 쓸 필요가 없음
  • 그러나, ByteArrayInputStream을 쓴다는 것은 해당 byte가 읽기 전용이라는 것을 강하게 암시할 수 있고 input이 가끔 byte[] 이고, 또는 file일 수도 있고, network connection일 수 있다면 ByteArrayInputStream을 통해 byte의 stream 이라는 추상화를 적용할 수 있음.
    • "a stream of bytes, and I don't care where they come from."
ByteArrayInputStream을 쓰면 좋은 예시
  • You're writing a library that takes bytes and processes them somehow (maybe it's an image processing library, for instance). Users of your library may supply bytes from a file, or from a byte[] in memory, or from some other source. So, you provide an interface that accepts an InputStream — which means that if what they have is a byte[], they need to wrap it in a ByteArrayInputStream.
  • You're writing code that reads a network connection. But to unit test that code, you don't want to have to open up a connection; you want to just supply some bytes in the code. So the code takes an InputStream, and your test provides a ByteArrayInputStream.
 

직렬화(serialization)

  • 인스턴스의 상태를 그대로 파일 저장하거나 네트웍으로 전송하고 (serialization) 이를 다시 복원(deserialization) 하는 방식
  • 직렬화는 인스턴스의 내용이 외부로 유출되는 것이므로 프로그래머가 해당 객체에 대한 직렬화 의도를 표시해야 함 → implements Serializable
  • transient : 직렬화 하지 않으려는 멤버 변수에 사용함 (Socket등 직렬화 할 수 없는 객체)

Serializable

  • 대부분 거의 이걸로 많이 씀

Externalizable

그외 입출력 클래스들

  • Scanner 클래스
  • File 클래스 : 입출력 기능은 없고, 파일의 이름, 경로, 읽기 전용 등의 속성을 알 수 있음
  • RandomAccessFile 클래스 : 입출력 클래스 중 유일하게 파일에 대한 입력과 출력을 동시에 할 수 있는 클래스
    • 파일 포인터가 있어서 읽고 쓰는 위치의 이동이 가능함

File Management

File class

  • File class constructor를 부른다고 해서 File System에 바로 파일이 생성되는 것이 아님
  • 파일 생성 위해서는 createNewFile() 메서드를 호출해야 함
  • File 클래스가 data를 담고 있기 위해서는 File System에 생성되어야 함

FileNotFoundException 발생 시

  • new File(”.”) 로 getAbsolutePath() 호출하여 현재 경로를 확인
  • 해당 현재 경로 기준으로 파일을 위치시켜서 파일 읽으면 잘 찾을 수 있음

ClassPath에서 File 읽기

Java SDK

// Class 를 이용하여 classpath의 파일 읽기 // src/main/resources 아래에서 절대 경로를 넣어주어야 함 @Test public void givenFileNameAsAbsolutePath_whenUsingClasspath_thenFileData() { String expectedData = "Hello, world!"; Class clazz = FileOperationsTest.class; InputStream inputStream = clazz.getResourceAsStream("/fileTest.txt"); String data = readFromInputStream(inputStream); Assert.assertThat(data, containsString(expectedData)); } // ClassLoader를 이용하여 classpath의 파일 읽기 // src/main/resources 를 루트로 해서 파일 경로 넣어주면 됨 ClassLoader classLoader = getClass().getClassLoader(); // 현재 클래스의 클래스로더 InputStream inputStream = classLoader.getResourceAsStream("fileTest.txt"); String data = readFromInputStream(inputStream);

ApplicationContext 의 ResourceLoader 인터페이스 이용

💻
Resource

File로 부터 텍스트 읽기

@Test void name() { String path = "/Users/geuno/Downloads/index.html"; File f = new File(path); try (BufferedReader reader = new BufferedReader(new FileReader(f))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } }

File에 텍스트 쓰기

Java - 파일에 Text(String) 쓰는 방법
  • BufferedWriter
  • PrintWriter
  • FileOutputStream
  • Files

Creating and deleting files and directories

@Test void listFilesInDirectory() { String path = "/Users/geuno/Downloads"; File f = new File(path); File[] files = f.listFiles(); for (File file : files) { System.out.println(file.getName()); } } @Test void createFile() throws IOException { String path = "/Users/geuno/Downloads/a.txt"; File f = new File(path); f.createNewFile(); } @Test void createDirectoryAndCreateDelete() throws IOException { String path = "/Users/geuno/Downloads/a/b/a.txt"; File f = new File(path); try { f.mkdirs(); f.createNewFile(); f.delete(); } catch (IOException e) { System.out.println(e); } }

Apache Commons FileUtils and IOUtils

[Baeldung ] Apache Commons IO
  • FileUtils class. 기능들
    • writing to a file
    • reading from a file
    • make a directory including parent directories
    • copying files and directories
    • deleting files and directories
    • converting to and from a URL
    • listing files and directories by filter and extension
    • comparing file content
    • file last changed date
    • calculating a checksum
  • IOUtils class : general I/O stream manipulation methos
    • This class provides static utility methods for input/output operations.
    • closeQuietly - these methods close a stream ignoring nulls and exceptions
    • toXxx/read - these methods read data from a stream
    • write - these methods write data to a stream
    • copy - these methods copy all the data from one stream to another
    • contentEquals - these methods compare the content of two streams