입출력 스트림
입출력이란 입력(Input)과 출력(Output)을 줄여서 부르는 것으로 두 대상 간의 데이터를 주고받는 것을 의미한다.
데이터를 주고 받을 때 스트림(Stream)이라는 것을 사용하게 되는데 데이터를 입출력하는 데 사용되는 연결 통로를 뜻한다.
하나의 스트림으로 입출력을 동시에 수행할 수 없는 단방향 통신만 가능하다. (동시에 하려면 2개의 스트림이 필요)
바이트 기반 스트림
바이트 기반 스트림은 데이터를 바이트 단위로 주고 받는다.
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream("C:\\test\\abc.txt");
fileOutputStream = new FileOutputStream("C:\\test\\abc4.txt");
byte[] bytes = fileInputStream.readAllBytes();
for (int i = 0; i < bytes.length; i++) {
fileOutputStream.write(bytes[i]);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fileInputStream != null) fileInputStream.close();
if (fileOutputStream != null) fileOutputStream.close();
}
}
파일을 주고받는 스트림을 살펴보면 위의 코드와 같다.
위의 코드를 간단히 설명해 보면 test 경로에 있는 abc.txt 파일을 같은 test 경로에 abc4.txt 파일로 내용을 복사하는 코드이다.
코드를 살펴보면 먼저 FileInputStream과 FileOutputStream 변수를 생성해 준다. 그 후 try-catch 문을 통해서 입출력에 대한 예외 처리를 진행하게 된다.

try문에서 FileInput과 OutputStream 객체를 생성하고 매개 변수로 파일의 경로를 지정해 주는데 이때 InputStream으로 파일의 내용을 읽어오고 OutputStream으로 파일을 작성하고 저장하게 된다.
바이트 기반의 스트림이기 때문에 파일의 내용을 바이트 단위로 읽어와서 byte[] 배열에 저장하고 해당 바이트 배열의 값들을 OutputStream의 write 메서드를 통해서 작성하게 된다. 그 후 OutputStream 객체를 생성할 때 미리 지정해 둔 경로에 파일이 만들어지게 된다.
문자 기반 스트림
문자 기반 스트림은 입출력 단위가 문자(char, 2 바이트)인 스트림을 의미한다.
public static void main(String[] args) throws IOException {
FileReader fileReader = null; // 한글 처리도 가능함
FileWriter fileWriter = null;
try {
fileReader = new FileReader("C:\\test\\abc.txt");
fileWriter = new FileWriter("C:\\test\\abc3.txt");
while (fileReader.read() != -1) {
fileWriter.write(fileReader.read());
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fileReader != null) fileReader.close();
if (fileWriter != null) fileWriter.close();
}
}
기존의 바이트 기반 스트림은 한글을 표현하기 힘들다는 단점이 존재한다. 이러한 문제는 문자 기반 스트림으로 해결할 수 있는데 입출력 단위가 문자로 되어 있기 때문에 한글을 표현하는데 문제가 없다.
위의 코드는 바이트 기반 스트림과 같은 내용이다. 지정된 경로의 파일을 읽어와서 같은 내용을 새로운 파일로 옮기는 코드이다.
먼저 FileReader와 FileWriter 변수를 생성하고 try-catch 문에서 객체를 생성한다.
객체를 생성할 때는 매개변수로 경로를 지정해 준다.
그 후 fileReader의 read() 메서드를 통해서 해당 파일의 내용을 읽어와서 fileWriter의 write() 메서드를 통해서 파일을 작성하게 된다.
보조 스트림
스트림의 기능을 향상하거나 새로운 기능을 추가하기 위해 사용되는 스트림이다.
말 그대로 스트림을 보조하기 위한 것이기 때문에 독립적으로 입출력을 수행할 수 없다.
public static void main(String[] args) throws IOException {
FileReader fileReader = null;
FileWriter fileWriter = null;
BufferedReader br = null;
try {
fileReader = new FileReader("C:\\test\\abc.txt");
fileWriter = new FileWriter("C:\\test\\abc3.txt");
br = new BufferedReader(fileReader);
while (br.read() != -1) {
fileWriter.write(br.read());
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null) fileReader.close();
if (fileWriter != null) fileWriter.close();
}
}
위의 코드는 보조 스트림을 사용한 예시로 BufferedReader를 사용한 코드이다.
문자 기반 스트림 예제 코드에서 BufferedReader만 추가했다. 해당 보조 스트림을 통해서 더 빠른 입출력 처리를 할 수 있게 된다.
소켓 통신을 이용한 입출력 스트림
소켓 통신의 예제로 채팅 프로그램을 많이 개발하는데 입출력 스트림을 이용해서 구현해 봤다.
public static void main(String[] args) throws IOException {
try {
// 연결하는 코드
ServerSocket socket = new ServerSocket(9000);
Socket cs = socket.accept();
// 받는 코드
InputStream is = cs.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader bir = new BufferedReader(isr);
String data = bir.readLine();
System.out.println(data);
br.close();
// 보내는 코드
OutputStream os = cs.getOutputStream();
OutputStreamWriter output = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(output);
Scanner sc = new Scanner(System.in);
System.out.print("메세지를 입력해주세요. :");
String msg = sc.next();
bw.write(msg + "\n");
bw.flush();
bw.close();
} catch (IOException e) {
e.getMessage();
}
}
먼저 서버 코드를 살펴보게 되면 서버 소켓을 생성하면서 포트번호를 설정하게 되고 클라이언트의 연결을 기다리게 된다.
클라이언트와 연결이 되면 클라이언트에서 입력한 메시지를 InputStream으로 받고 InputStreamReader를 통해서 데이터를 읽게 된다. 이때 BufferedReader를 사용하여 데이터 처리 효율성을 높인다.
그 후 읽은 문자를 String으로 저장한다.
클라이언트에서 보낸 메세지를 처리했다면 서버에서 메세지를 보내는 방법을 알아보자.
먼저 메세지를 보내기 위해서는 OutputStream 객체를 가져오고 해당 객체를 OutputStreamWriter 매개변수로 전달해 준다.
데이터 처리 효율성을 높이기 위해 BufferedWriter를 사용하여 처리하고 Scanner를 통해서 받은 메시지를 write() 메서드를 통해서 클라이언트로 전달하게 된다.
BufferedWriter의 write() 메서드는 개행기능이 없기 때문에 따로 개행처리를 해줘야 하고 버퍼를 잡아 놓기 때문에 반드시 flush()와 close()를 호출해서 스트림을 닫아줘야 한다.
public class ChattingClient {
public static void main(String[] args) throws IOException {
// 서버와 연결하는 코드
Socket cs = new Socket("서버IP", 9000);
// 보내는 코드
OutputStream os = cs.getOutputStream();
OutputStreamWriter output = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(output);
Scanner sc = new Scanner(System.in);
System.out.print("메시지를 입력해주세요. : ");
String msg = sc.next();
bw.write(msg + "\n");
bw.flush();
// 받는 코드
InputStream is = cs.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader bir = new BufferedReader(isr);
String data = bir.readLine();
System.out.println(data);
bir.close();
}
}
클라이언트 코드도 살펴보면 먼저 소켓을 생성하여 서버와 연결한다.
그다음 서버에 메시지를 보내기 위해서 OutputStream을 생성하고 OutputStreamWriter 객체를 만들어준다. 해당 객체를 BufferedWriter 보조 스트림으로 전달하여 처리 효율을 높였다.
클라이언트로부터 입력받은 메시지를 write() 메서드를 통해서 작성하여 전달해 준다.
서버로부터 데이터를 전달받는 코드는 앞서 서버에서 작성한 코드와 동일하다. (데이터를 주고받는 것이 서버나 클라이언트나 크게 다르지 않기 때문)
'자바' 카테고리의 다른 글
[Java] - JVM(Java Virtual Machine) (0) | 2023.12.21 |
---|---|
[Java] - 스레드 (1) | 2023.11.29 |
[Java] - JDK? JVM? JRE? 이게 다 무슨 소리지? (0) | 2023.11.26 |
[Java] - Optional (0) | 2023.11.19 |
[Java] - 람다 (0) | 2023.11.17 |
입출력 스트림
입출력이란 입력(Input)과 출력(Output)을 줄여서 부르는 것으로 두 대상 간의 데이터를 주고받는 것을 의미한다.
데이터를 주고 받을 때 스트림(Stream)이라는 것을 사용하게 되는데 데이터를 입출력하는 데 사용되는 연결 통로를 뜻한다.
하나의 스트림으로 입출력을 동시에 수행할 수 없는 단방향 통신만 가능하다. (동시에 하려면 2개의 스트림이 필요)
바이트 기반 스트림
바이트 기반 스트림은 데이터를 바이트 단위로 주고 받는다.
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream("C:\\test\\abc.txt");
fileOutputStream = new FileOutputStream("C:\\test\\abc4.txt");
byte[] bytes = fileInputStream.readAllBytes();
for (int i = 0; i < bytes.length; i++) {
fileOutputStream.write(bytes[i]);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fileInputStream != null) fileInputStream.close();
if (fileOutputStream != null) fileOutputStream.close();
}
}
파일을 주고받는 스트림을 살펴보면 위의 코드와 같다.
위의 코드를 간단히 설명해 보면 test 경로에 있는 abc.txt 파일을 같은 test 경로에 abc4.txt 파일로 내용을 복사하는 코드이다.
코드를 살펴보면 먼저 FileInputStream과 FileOutputStream 변수를 생성해 준다. 그 후 try-catch 문을 통해서 입출력에 대한 예외 처리를 진행하게 된다.

try문에서 FileInput과 OutputStream 객체를 생성하고 매개 변수로 파일의 경로를 지정해 주는데 이때 InputStream으로 파일의 내용을 읽어오고 OutputStream으로 파일을 작성하고 저장하게 된다.
바이트 기반의 스트림이기 때문에 파일의 내용을 바이트 단위로 읽어와서 byte[] 배열에 저장하고 해당 바이트 배열의 값들을 OutputStream의 write 메서드를 통해서 작성하게 된다. 그 후 OutputStream 객체를 생성할 때 미리 지정해 둔 경로에 파일이 만들어지게 된다.
문자 기반 스트림
문자 기반 스트림은 입출력 단위가 문자(char, 2 바이트)인 스트림을 의미한다.
public static void main(String[] args) throws IOException {
FileReader fileReader = null; // 한글 처리도 가능함
FileWriter fileWriter = null;
try {
fileReader = new FileReader("C:\\test\\abc.txt");
fileWriter = new FileWriter("C:\\test\\abc3.txt");
while (fileReader.read() != -1) {
fileWriter.write(fileReader.read());
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fileReader != null) fileReader.close();
if (fileWriter != null) fileWriter.close();
}
}
기존의 바이트 기반 스트림은 한글을 표현하기 힘들다는 단점이 존재한다. 이러한 문제는 문자 기반 스트림으로 해결할 수 있는데 입출력 단위가 문자로 되어 있기 때문에 한글을 표현하는데 문제가 없다.
위의 코드는 바이트 기반 스트림과 같은 내용이다. 지정된 경로의 파일을 읽어와서 같은 내용을 새로운 파일로 옮기는 코드이다.
먼저 FileReader와 FileWriter 변수를 생성하고 try-catch 문에서 객체를 생성한다.
객체를 생성할 때는 매개변수로 경로를 지정해 준다.
그 후 fileReader의 read() 메서드를 통해서 해당 파일의 내용을 읽어와서 fileWriter의 write() 메서드를 통해서 파일을 작성하게 된다.
보조 스트림
스트림의 기능을 향상하거나 새로운 기능을 추가하기 위해 사용되는 스트림이다.
말 그대로 스트림을 보조하기 위한 것이기 때문에 독립적으로 입출력을 수행할 수 없다.
public static void main(String[] args) throws IOException {
FileReader fileReader = null;
FileWriter fileWriter = null;
BufferedReader br = null;
try {
fileReader = new FileReader("C:\\test\\abc.txt");
fileWriter = new FileWriter("C:\\test\\abc3.txt");
br = new BufferedReader(fileReader);
while (br.read() != -1) {
fileWriter.write(br.read());
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null) fileReader.close();
if (fileWriter != null) fileWriter.close();
}
}
위의 코드는 보조 스트림을 사용한 예시로 BufferedReader를 사용한 코드이다.
문자 기반 스트림 예제 코드에서 BufferedReader만 추가했다. 해당 보조 스트림을 통해서 더 빠른 입출력 처리를 할 수 있게 된다.
소켓 통신을 이용한 입출력 스트림
소켓 통신의 예제로 채팅 프로그램을 많이 개발하는데 입출력 스트림을 이용해서 구현해 봤다.
public static void main(String[] args) throws IOException {
try {
// 연결하는 코드
ServerSocket socket = new ServerSocket(9000);
Socket cs = socket.accept();
// 받는 코드
InputStream is = cs.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader bir = new BufferedReader(isr);
String data = bir.readLine();
System.out.println(data);
br.close();
// 보내는 코드
OutputStream os = cs.getOutputStream();
OutputStreamWriter output = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(output);
Scanner sc = new Scanner(System.in);
System.out.print("메세지를 입력해주세요. :");
String msg = sc.next();
bw.write(msg + "\n");
bw.flush();
bw.close();
} catch (IOException e) {
e.getMessage();
}
}
먼저 서버 코드를 살펴보게 되면 서버 소켓을 생성하면서 포트번호를 설정하게 되고 클라이언트의 연결을 기다리게 된다.
클라이언트와 연결이 되면 클라이언트에서 입력한 메시지를 InputStream으로 받고 InputStreamReader를 통해서 데이터를 읽게 된다. 이때 BufferedReader를 사용하여 데이터 처리 효율성을 높인다.
그 후 읽은 문자를 String으로 저장한다.
클라이언트에서 보낸 메세지를 처리했다면 서버에서 메세지를 보내는 방법을 알아보자.
먼저 메세지를 보내기 위해서는 OutputStream 객체를 가져오고 해당 객체를 OutputStreamWriter 매개변수로 전달해 준다.
데이터 처리 효율성을 높이기 위해 BufferedWriter를 사용하여 처리하고 Scanner를 통해서 받은 메시지를 write() 메서드를 통해서 클라이언트로 전달하게 된다.
BufferedWriter의 write() 메서드는 개행기능이 없기 때문에 따로 개행처리를 해줘야 하고 버퍼를 잡아 놓기 때문에 반드시 flush()와 close()를 호출해서 스트림을 닫아줘야 한다.
public class ChattingClient {
public static void main(String[] args) throws IOException {
// 서버와 연결하는 코드
Socket cs = new Socket("서버IP", 9000);
// 보내는 코드
OutputStream os = cs.getOutputStream();
OutputStreamWriter output = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(output);
Scanner sc = new Scanner(System.in);
System.out.print("메시지를 입력해주세요. : ");
String msg = sc.next();
bw.write(msg + "\n");
bw.flush();
// 받는 코드
InputStream is = cs.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader bir = new BufferedReader(isr);
String data = bir.readLine();
System.out.println(data);
bir.close();
}
}
클라이언트 코드도 살펴보면 먼저 소켓을 생성하여 서버와 연결한다.
그다음 서버에 메시지를 보내기 위해서 OutputStream을 생성하고 OutputStreamWriter 객체를 만들어준다. 해당 객체를 BufferedWriter 보조 스트림으로 전달하여 처리 효율을 높였다.
클라이언트로부터 입력받은 메시지를 write() 메서드를 통해서 작성하여 전달해 준다.
서버로부터 데이터를 전달받는 코드는 앞서 서버에서 작성한 코드와 동일하다. (데이터를 주고받는 것이 서버나 클라이언트나 크게 다르지 않기 때문)
'자바' 카테고리의 다른 글
[Java] - JVM(Java Virtual Machine) (0) | 2023.12.21 |
---|---|
[Java] - 스레드 (1) | 2023.11.29 |
[Java] - JDK? JVM? JRE? 이게 다 무슨 소리지? (0) | 2023.11.26 |
[Java] - Optional (0) | 2023.11.19 |
[Java] - 람다 (0) | 2023.11.17 |