자바 I/O

Moom2n·2024년 3월 20일
0

Java

목록 보기
24/26

- 개념

input 과 output 이 존재한다.

모든 I/O 는 Byte 단위와 Char 단위로 나누어지는데

Byte 단위는 InputStream 과 OutputStream 이 최상위 클래스이고,

Char 단위는 Reader 와 Writer 가 최상위 클래스이다.

Ex). FileInputStream / FileOutputStream 와 FileReader / FileWriter 가 있다.

이 중 BufferdReader 클래스는 readLine() 등의 메소드를 가지고 있다.

- Byte 단위 입출력

import java.io.FileInputStream;
import java.io.FileOutputStream;

public class byteinput {
    static final String PATH = "./IO_test.txt";
    public static void main(String[] args) {

        try {
            FileInputStream fis = new FileInputStream(PATH);
            FileOutputStream fos = new FileOutputStream("output.txt");

            int readData = -1;
            byte[] buffer = new byte[512];

            while ((readData = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, readData);
            }

            fis.close();
            fos.close();
        } catch(Exception e) {
            System.err.println(e);
        }
    }
}

실행결과

- 다양한 타입의 입출력

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class io_test {
    static final String PATH = "./output.txt";

    public static void main(String[] args) {

        try (
            DataOutputStream out = new DataOutputStream(new FileOutputStream(PATH));
            DataInputStream in = new DataInputStream(new FileInputStream(PATH));
        ){
            out.writeInt(100);
            out.writeBoolean(false);
            out.writeDouble(50.5);

            int i = in.readInt();
            boolean b = in.readBoolean();
            double d = in.readDouble();

            System.out.println(i);
            System.out.println(b);
            System.out.println(d);

        } catch(Exception e) {
            System.err.println(e);
        }
    }
}

실행결과

100
false
50.5

위의 사진과 같이 String 형으로 저장된게 아니므로, 우리가 읽을 수 없는 값으로 파일에는 표시된다.

- Char 단위 입출력

클래스 이름이 ReaderWriter 로 끝난다.

키보드로부터 입력을 받을 시 Char 단위로 입력을 받는데, 우리는 문자열로 입력을 받아야 한다. 키보드는 System.in 이 나타내고 있다. java.lang 패키지 안에 있다.

System.inin 의 타입은 input stream 이다.

BufferedReader 클래스는 한 줄씩 입력을 받을 수 있는 메소드를 가지고 있다.

키보드로부터 입력을 받아야 하는데, BufferedReader 클래스의 생성자의 타입은 Reader 타입이므로, System.in 을 바로 이용할 수 없다.

고로 System.inReader 의 형태로 바꿔줘야 하는데 이를 InputStreamReader 클래스가 한다.

이처럼 객체에 추가적인 요건(기능)을 동적으로 첨가하는 방식을 "데코레이터 패턴" 이라고 한다.

콘솔에 입출력

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class charinput {
    public static void main(String[] args) {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
            String line = br.readLine();
            System.out.println(line);
        } catch (Exception e) {
            System.err.println(e);
        }
    }
}

실행결과

nice	//입력한 값
nice	//출력된 값

파일에 입출력

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;

public class charinput {
    public static void main(String[] args) {
        try (
            BufferedReader br = new BufferedReader(new FileReader("./IO_test.txt"));
            PrintWriter pw = new PrintWriter(new FileWriter("./output.txt"))
        ) { 
            String line;
            
            while((line = br.readLine()) != null) {
                pw.println(line);
            }

        } catch (Exception e) {
            System.err.println(e);
        }
    }
}

실행결과

- 버퍼

프로그램 입출력 시 버퍼를 사용한다.

Ex). scanner.nextInt() 다음 scanner.nextLine() 입력 불가

데이터 통로 역할을 스트림이 한다. 흐름은 항상 한쪽 방향으로만 이용한다. 출력 스트림입력 스트림 이 그래서 분리되어 있어야 한다.

그러나 이는 매우 비효율적인 방법이다. 문자를 하나씩 옮기기 때문

임시기억공간을 "버퍼"라고 한다.

버퍼의 입력이 끝난 것은 엔터로 구분한다.

버퍼에서 내용을 scanner.nextInt() 가 꺼내오는데, 45 정수만 꺼내오고,

scanner.nextLine()\n 을 가져온다.

고로 문제가 발생된다.


OutputStream 객체가 Buffer 를 관리한다.

하나의 완충장치 이자, 카트라고 생각하면 된다.

스트림이 데이터를 버퍼로 흘려보낸다.

PrintStream -> BufferedOutputStream -> OutputStream -> 버퍼 -> 화면 출력

Socket 을 이용한 BufferReader 와 BufferWriter 실습

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class Quiz07 {
    static class Receiver extends Thread {
        BufferedReader input;

        public Receiver(BufferedReader input) {
            this.input = input;
        }

        @Override
        public void run() {
            char[] buffer = new char[2048];

            try {
                while (!Thread.currentThread().isInterrupted()) {
                    int length;
                    length = input.read(buffer);
                    System.out.println("서버에서 보낸 메시지 : " + new String(buffer, 0, length));
                }
            } catch (IOException ignore) {
                //
            }
        }
    }

    public static void main(String[] args) {
        String host = "localhost";
        int port = 12345;

        if (args.length > 0) {
            host = args[0];
        }

        try {
            if (args.length > 1) {
                port = Integer.parseInt(args[1]);
            }
        } catch (NumberFormatException ignore) {
            System.err.println("Port가 올바르지 않습니다.");
            System.exit(1);
        }

        try (Socket socket = new Socket(host, port);
                BufferedReader terminalIn = new BufferedReader(new InputStreamReader(System.in));      // InputStreamReader 가 stream 의 byte 를 reader의 char 로 변환
                BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                BufferedWriter output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {     // OutputStreamWriter 가 stream 의 byte 를 writer 의 char 로 변환
            System.out.println("서버에 연결되었습니다.");

            Receiver receiver = new Receiver(input);

            receiver.start();

            String line;
            while ((line = terminalIn.readLine()) != null) {
                if (line.trim().equals("exit")) {
                    break;
                }
                output.write(line);
                output.flush();
            }

        } catch (IOException e) {
            System.err.println(e);
        }
    }
}

실행결과

로컬 컴퓨터에서 exit 를 입력해야만 프로그램이 종료한다.

0개의 댓글

관련 채용 정보