java.io
자바의 기본적인 입출력 API 제공
(파일 시스템, 콘솔, 바이트 단위 입출력, 문자 단위 입출력)
입력 스트림 : 키보드 / 파일 / 프로그램으로부터 프로그램으로 들어오는 데이터를 받는 방법,도구
출력 스트림 : 프로그램에서 모니터 / 파일 / 프로그램으로 나가는 데이터를 다루는 방법, 도구
그림, 멀티미디어, 문자 등 모든 종류의 데이터 주고 받을 수 있음
InputStream
- XXXInputStream
OutputStream
- XXXOutputStream
문자만 주고 받을 수 있음
Reader
- XXXReader
Writer
- XXXWriter
바이트 기반 입력 스트림의 최상위 클래스로 추상 클래스이며 주요 메소드로는 read()
,read(byte[] b)
,read(byte[] b, int off, int len)
,close()
가 있음
바이트 기반 출력 스트림의 최상위 클래스로 추상 클래로 주요 메소드로는 write(int b)
,write(byte[] b)
,write(byte[] b, int off, int len)
,flush()
,close()
가 있음
문자 기반 입력 스트림의 최상위 클래스로 추상 클래스이며 주요 메소드로는 read()
,read(char[] cbuf)
,read(char[] cbuf, int off, int len)
,close()
가 있음
문자 기반 출력 스트림의 최상위 클래스로 추상 클래스이며 주요 메소드로는 write(int c)
,write(char[] cbuf)
,write(char[] cbuf, int off, int len)
,write(String str)
,write(String str, int off, int len)
, flush()
, close()
가 있음
시스템을 사용하기 위해 키보드로 입력 받고 화면으로 출력하는 소프트웨어로 터미널, 명령 프롬프트, console 뷰가 있음
2byte를 차지함
캐리지 리턴 (13)
라인피트 (10)
으로 구성되기 때문
콘솔에서 입력된 문자열을 쉽게 읽을 수 있도록 Console 클래스 제공
readLine()
: 엔터키 입력 전의 모든 문자열 읽음
readPassword()
: 키보드 입력 문자를 콘솔에 보여주지 않고 문자열 읽음
Console 클래스는 문자열을 읽을 수는 있지만 기본 타입 값을 바로 읽을 수는 없는 점을 보안해서 byte, boolean, short, int, long, float, double, String 값을 읽음
파일 시스템의 파일을 표현하는 클래스로 파일 크기/속성/이름 등의 정보를 제공하며 생성 및 삭제 기능을 제공하며 디렉토리 생성하고 그 내부에 존재하는 파일 리스트 얻어내는 기능을 제공함
File file = new File("C:\\Temp\\file.txt");
boolean isExist = file.exists();
createNewFile()
,mkidr()
,mkdirs()
, delete()
파일로부터 바이트 단위로 읽어 들일 떄 사용되어 그림, 오디오, 비디오, 텍스트파일 등 모든 종류의 파일 읽어올 수 있음
FileInputStream 객체가 생성될 떄 파일과 직접 연결되어 존재하지 않는 파일의 경우 FileNotFoundException이 발생되며 try-catch문으로 예외처리 해야함
파일에 바이트 단위로 데이터 저장할 때 사용되어 모든 종류의 데이터를 파일로 저장 가능
파일이 이미 존재할 경우 데이터를 출력하게 되면 파일을 덮어쓰기 때문에 기존 내용 끝에 데이터 추가하기 위해서는
FileOutputStream fis = new FileOutputStream("aaa", true);
등으로 처리함
텍스트 파일로부터 데이터 읽어 들일 때 사용하여 문자 단위로만 읽기 때문에 텍스트가 아닌 파일은 읽어올 수 없으며 FileReader 객체가 생성될 때 파일과 직접 연결되기 때문에 파일이 존재하기 않으면 FileNotFoundException 발생시키므로 try-catch문으로 예외 처리 해야함
텍스트 파일에 문자 데이터 저장할 때 사용하여 텍스트가 아닌 데이터를 파일로 저장할 수 없다
다른 스트림과 연결되어 문자 변환/입출력 성능 향상/기본 데이터 타입 입출력/객체 입출력 등의 기능을 제공하는 스트림으로 여러개의 보조 스트림을 연결해 체인처럼 이용할 수 있음
보조스트림 변수 = new 보조스트림(연결스트림)
소스 스트림이 바이트 기반 스트림이지만 데이터가 문자일 경우 사용할 수 있음
Reader/Writer는 문자 단위로 입출력하기 때문에 바이트 기반 스트림보다는 편리하며 문자셋의 종류 지정 가능하여 다양한 문자 입출력할 수 있음
InputStream is = System.in;
Reader reader = new Reader(is);
FileInputStream fis = new FileInputStream("C:/Temp/file.txt");
Reader reader = new InputStreamReader(fis);
FileOutputStream fos = new FileOutputStream("C:/Temp/file.txt");
Writer writer = new OutputStreamWriter(fos);
입출력 성능에 영향을 미치는 입출력 소스(하드디스크, 느린 네트워크)에 버퍼를 이용해 해결하는 스트림
입출력 소스 대신 버퍼와 작업함으로서 실행 성능 향상시켜 쓰기 속도 향상 시키고 버퍼가 차제 됐을 때 데이터를 한 번에 하드 디스크로 보내면서 출력 횟수도 줄여줌
BufferedInputStream bis = new BufferedInputStream(byteInputStream);
BufferedReader br = new BufferedReader(StringInputStream);
BufferedOutputStream bos = new BufferedOutputStream(byteOutputStream);
BufferedWriter bw = new BufferedWriter(StringOuputStream);
DataInputStream dis = new DataInputStream(byteInputStream);
DataOutputStream dos = new DataOutputStream(byteOutputStream);
PrintStream ps = new PrintStream(byteOutputStream);
PrintWriter pw = new PrintWriter(StringOutputStream);
객체를 파일/네트워크로 입출력할 수 있는 기능 제공,
Serializable 인터페이스를 구현한 클래스만 직렬화할 수 있음
ObjectInputStream ois = new ObjectInputStream(byteInputStream);
Object value = (Object) ois.readObject()l
ObjectOutputStream oos = new ObjectOutputStream(byteOutputStream);
oos.write(object);
필드를 일렬로 늘어뜨린 바이트 데이터로 전환할 수 있음
직렬화 객체와 역직렬화 객체가 같은 클래스임을 알려주는 식별자 역할을 하며 컴파일 할 때마다 값이 달라지므로 불가피한 수정이 있을 경우 명시적으로 serialVersionUUID 선언
writeObject는 직렬화 직전에 자동 호출되며 추가 직렬화할 내용 작성 가능하고, readObject()는 역직렬화 직전에 자동호출되어 추가 역직렬화 내용을 작성할 수 있음
부모 클래스가 Serializable을 구현하지 않고 자식 클래스만 구현된 경우 부모 클래스는 직렬화 대상에서 제외되기 때문에 추가적인 절차가 필요함
여러대의 컴퓨터를 통신 회선으로 연결한 것으로
홈 네트워크는 컴퓨터가 방마다 있고 이를 유-무선 통신 회선으로 연결한 것, 지역 네트워크는 회사, 건물, 특정 영역에 존재하는 컴퓨터를 통신 회선으로 연결한 것, 인터넷은 지역 네트워크를 통신회선으로 연결한 것이다.
서버는 서비스를 제공하는 프로그램으로 클라이언트의 연결을 수락하고 요청 내용을 처리한 후 응답을 보내는 역할을 하며, 클라이언트는 서비스를 받는 프로그램으로 네트워크 데이터를 필요로하는 모든 애플리케이션이 해당됨
1. 클라이언트 -> 서버 : 연결 요청
2. 서버 : 연결 수락
3. 클라이언트 -> 서버 : 처리 요청
4. 서버 : 처리
5. 서버 -> 클라이언트 : 응답(처리 결과)
네트워크 상에서 컴퓨터를 식별하는 번호로 네트워크 어댑터(Lan 카드)마다 할당되는 주소로 xxx.xxx.xxx.xxx 형식으로 표현됨
같은 컴퓨터 내에서 프로그램을 식별하는 번호로 클라이언트는 서버 연결 요청시 IP 주소와 Port를 같이 제공함
java.net.InetAddress
를 통해 얻을 수 있음
IP 주소를 표현한 클래스로 로컬 컴퓨터의 IP 주소 뿐만 아니라 도메인 이름을 DNS에서 검색한 후 IP 주소 가져오는 기능 제공함
InetAddress ia = InetAddress.getLocalHost();
InetAddress ia = InetAddress.getByName(String host);
InetAddress[] iaArr = InetAddress.getAllByName(String host);
String ip = InetAddress.getHostAddress();
연결 지향적 프로토콜로 시간 소요가 있으며, 통신 선로가 고정되러 전송 속도가 느려질 수 있지만 데이터를 정확하고 안정적으로 전달하는 방식임
java.net API
의 ServerSocker, Socket을 통해 이용 가능함
//ServerSocket 생성 및 바인딩
ServerSocket serverSocket = new ServerSocket(5001);
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("127.0.0.1", 5001));
//연결 수락
try{
Socket socket = serverSocket.accept();
}catch(Exception e){
}
//연결된 클라이언트 IP 주소 얻기
InetSocketAddress socketAddress = (InetSocketAddress) socket.getRomoteSocketAddress();
System.out.println(socketAddress.getHostName());
System.out.println(socketAddress.getPort());
System.out.println(socketAddress.toString());
//포트 언바인딩
serverSocket.close();
//Socket 생성 및 연결 요청
try{
Socket socket = new Socket("localhost", 5001);
Socket socket = new Socket(new InetSocketAddress("localhost", 5001));
} catch (UnknownHostException e){
//Ip 표기 방법 잘못된 경우
} catch (IOException e){
// 해당 포트의 서버에 연결 불가능한 경우
}
socket = new Socket();
socket.connect(new InetSocketAddress("localhost", 5001));
//연결 끊기
try{
socket.close();
}catch(IOException e){}
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
String data = "send data";
byte[] byteArr = data.getBytes("UTF-8");
OutputStream outputStream = socket.getOutputStream();
outputStream.write(byteArr);
outputStream.flush();
byte[] byteArr = new byte[100];
InputStream inputStream = socket.getInputStream();
int readByteCount = inputStream.read(byteArr);
String data = new String(byteArr, 0, readByteCount, "UTF-8");
상대방이 데이터를 보내는 경우 읽은 바이트 수 반환
상대방이 정상적으로 Socket.close() 호출하는 경우 -1 반환
상대방이 비정상적으로 종료한 경우 IOException 발생
블로킹(대기상태)가 되는 메소드에는 ServerSocket.accept()
, Socket Constructor / Socket.connect()
, Socket.read() / Socket.write()
가 있음
스레드가 블로킹되는 경우 다른 작업 수행하지 못하기 때문에 병렬처리가 필요하며, UI 생성/변경 스레드에서 블룅 메소드를 호출하지 않도록 해야함
스레드 풀은 스레드 수를 제한해서 사용하기 때문에 갑작스런 클라이언트의 폭증은 작업 큐의 작업량만 증가시킬 뿐, 스레드의 수는 변함이 없어 서버의 성능은 완만히 저하되지만 대기하는 작업량이 많아 개별 클라이언트에서 응답 늦게 받을 수도 있음
비연결 지향적 프로토콜로 연결 절차 없이 발신자가 일방적으로 데이터를 발산하여 TCP보다는 빠르게 데이터 전송할 수 있고, 통신 선로가 고정적이지 않기 때문에 데이터 패킷들이 서로 다른 통신 선로를 통해 전달될 수 있어 먼저 보낸 패킷이 나중에 보낸 패킷보다 늦게 도착 가능하며, 데이터 손실이 발생할 수 있어 데이터 전달 신뢰성이 떨어진다는 특징이 있다.
java.net
API의 DatagramSocket
, DatagramPacket
사용
DatagramSocket datagramSocket = new DatagramSocket();
String data = "sending data";
byte[] byteArr = data.getBytes("UTF-8");
DatagramPacket packet = new DatagramPacket(byteArr, byteArr.length, new InetSocketAddress("localhost", 5001));
datagramSocket.send(packet);
DatagramSocket datagramSocket = new DatagramSocket(5001);
DatagramPacket datagramPacket = new DatagramPakcet(new byte[100], 100);
datagramSocket.receive(datagramPacket);
datagramSocket.close();