input 과 output 이 존재한다.
모든 I/O 는 Byte 단위와 Char 단위로 나누어지는데
Byte 단위는 InputStream 과 OutputStream 이 최상위 클래스이고,
Char 단위는 Reader 와 Writer 가 최상위 클래스이다.
Ex). FileInputStream / FileOutputStream 와 FileReader / FileWriter 가 있다.
이 중 BufferdReader
클래스는 readLine()
등의 메소드를 가지고 있다.
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 형으로 저장된게 아니므로, 우리가 읽을 수 없는 값으로 파일에는 표시된다.
클래스 이름이 Reader
나 Writer
로 끝난다.
키보드로부터 입력을 받을 시 Char 단위로 입력을 받는데, 우리는 문자열로 입력을 받아야 한다. 키보드는 System.in
이 나타내고 있다. java.lang
패키지 안에 있다.
System.in
의 in
의 타입은 input stream
이다.
BufferedReader
클래스는 한 줄씩 입력을 받을 수 있는 메소드를 가지고 있다.
키보드로부터 입력을 받아야 하는데, BufferedReader
클래스의 생성자의 타입은 Reader
타입이므로, System.in
을 바로 이용할 수 없다.
고로 System.in
을 Reader
의 형태로 바꿔줘야 하는데 이를 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
-> 버퍼
-> 화면 출력
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 를 입력해야만 프로그램이 종료한다.