Java IO - InputStream 정리 [ByteArray, File, Buffered, Socket] (4/21)

세젤게으름뱅이·2025년 6월 3일

Spring Webflux

목록 보기
16/16

Java IO

  • Java 1.0에서 처음 도입
  • 파일과 네트워크에 데이터를 읽고 쓸 수 있는 API 제공
  • byte 단위로 읽고 쓸 수 있는 stream (Inputstream과 Outputstream)
  • blocking 동작

InputStream

  • Closable 구현. 명시적으로 close하거나 try-with-resource 사용 가능
    • Closable : close() 메소드를 갖고 있음.
    • close()로 직접 닫거나, try-with-resource로 닫음
  • read : stream으로 데이터를 읽고, 읽은 값을 반환
    • -1 이라면 EOF (End Of File)
  • close : stream을 닫고 더 이상 데이터를 읽지 않음
public abstract class InputStream implements Closeable {
    public abstract int read() throws IOException;
    public void close() throws IOException {}

InputStream 구현체

  • 어떤 source로부터 데이터를 읽을지에 따라 다양한 구현체 존재
    - source란 디스크에 있는 데이터

ByteArrayInputStream

  • byte array로부터 값을 read
  • 메모리가 source가 된다
  • ByteArrayInputStream의 역할은 이미 메모리에 존재하는 byte 배열을 읽는데 사용

FileInputStream

  • file로부터 byte 단위로 값을 read
  • file 객체나 path를 통해서 FileInputstream을 열 수 있다
  • read하는 동안 application에서 blocking 발생

BufferedInputStream

  • 다른 inputStream과 조합해서 사용
  • 임시저장 공간인 buffer를 사용
  • 한번 read를 호출할 때 buffer 사이즈만큼 미리 조회
  • 그 이후 read를 호출할 때 미리 저장한 buffer 데이터 반환

요약

  • BufferedInputStream = Buffer + FileInputstream
  • FileInputstream은 한번에 여러 byte read (예 : 8192byte씩)
  • 8192byte만큼 Buffer에 저장
  • 이후 read시 buffer에서 꺼내감
  • 매번 디스크에 접근해서 1byte씩 읽을 필요 X
var file = new File(BufferedInputStreamExample.class
        .getClassLoader()
        .getResource("data.txt").getFile()); 
try (var fis = new FileInputStream(file)) {
        try (var bis = new BufferedInputStream(fis)) {
			var value = 0; 
        while ((value = bis.read()) != -1) {
        log.info("value: {}", (char) value);
        }

serverSocket accept

  • serverSocket을 open하여, 외부 요청을 수신
  • bind, accept를 통해서 serverSocket open 준비

요약

  1. socket - bind - listen : Socket이 특정주소로 open
  2. accept : accept 상태 대기
  3. socket - connect - connect request : Socket 연결 요청
  4. read : read 상태 돌입
  5. write : 요청에 대한 응답
  6. close - EOF notification : 종료

serverSocket read

  • accept가 끝나면 client의 socket을 반환
  • client socket의 getInputstream으로 해당 socket의 Inpustream에 접근

요약

  1. Server는 accept 상태에서 blocking
  2. accept에서 연결이 성사되는 시점에 Client의 socket 정보 획득
  3. 해당 Client Socket으로 InputStream을 통해 데이터를 전달 받음

SocketInputStream

  • SocketInputStream은 public이 아니기 때문에 직접 접근이 불가능
    • public이 아님
    • 캡슐화 목적 : 내부 구현을 숨겨, 외부에 최소한의 인터페이스만 공개
    • 안정성 목적 : 사용자가 잘못 구현하거나 오용할 가능성 차단
  • socket.getInputStream으로만 접근 가능
  • blocking이 발생
/**
        *
        *
        * This stream extends FileInputStream to implement a 
 * SocketInputStream. Note that this class should <b>NOT </b> be 
 * public.
        */
class SocketInputStream extends FileInputStream { 

SocketInputStream 예시

// 서버 소켓 생성
ServerSocket serverSocket = new ServerSocket(8080); 

// 클라이언트 접속 대기
Socket clientSocket = serverSocket.accept();
var inputStream = clientSocket.getInputStream();

// 클라이언트로부터 데이터를 읽어들임
try (BufferedInputStream bis = new BufferedInputStream(inputStream)) {
    // 1KB 크기의 버퍼 생성
    byte[] buffer = new byte[1024];
    int bytesRead = bis.read(buffer);
    String inputLine = new String(buffer, 0, bytesRead); 
    log.info("bytes: {}", inputLine); 
    }
clientSocket.close();
serverSocket.close()
  • serverSocket.accept() : client와 connect될 때까지 blocking 상태
  • new BufferedInputStream(inputStream) 1byte씩 읽지않고, buffer를 사용
profile
🤦🏻‍♂️

0개의 댓글