스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O
Stream
Stream이란 데이터가 이동하는 통로이다.
1. Input, Output
2. Reader & Writer - 문자 스트림
InputStream & OutputStream - 바이트 스트림 (입출력 단위가 1byte)
3. nodeStream(기반 스트림) - 리소스에 직접적으로 연결되는 스트림
filterStream(보조 스트림) - 다른 스트림을 거쳐서 리소스와 연결되는 스트림
<그 외의 바이트 기반 스트림>
ByteArrayInputStream, ByteArrayOutputStream - 메모리(byte 배열)
PipedInputStream, PipedOutputStream - 프로세스(프로세스 간의 통신)
AudioInputStream, AudioOutputStream - 오디오 장치
Buffer 기반 스트림과 보조 스트림
보조 스트림은 직접적으로 리소스와 연결되지는 않지만, 다른 스트림에 연결되어 성능 향상을 돕는다.
BufferedReader br = null;
BufferedWriter bw = null;
// Scanner 클래스가 추가되기 전에는 이렇게 받아야 했음
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new FileWriter("output.txt"));
while((str = br.readLine()) != null) {
str += "\n";
bw.write(str);
}
// System.in이라는 InputStream이 InputStreamReader에
// 연결되고 이것이 마지막으로 BufferedReader와 연결
// BufferedReader(or InputStream_을 사용하면 read() 메소드를 호출했을 때 입력 소스로부터
// 데이터를 읽어서 버퍼에 저장
// 버퍼로부터 읽으면 외부의 입력소스를 바로 읽는 것보다 작업이 훨씬 빨라짐
// BufferedWriter도 유사하게 write() 메소드를 호출했을 때 출력이 버퍼에 저장된 후, 버퍼가 가득 차면
// 모든 내용을 출력 소스에 출력
// 버퍼에 남은 데이터가 있을 수 있으므로 flush()나 close()를 통해 남은 데이터를 출력 후 종료
Channel
채널의 특징
- Socket과 연결 되어, 입출력 역할을 수행한다.
- 입력과 출력을 동시에 수행한다.
- Selector와 연결되어 있고, 하나에 Selector에는 다수의 채널이 존재할 수 있다.
- Blocking된 스레드를 깨우거나, 다시 Blocking할 수 있다.
Selector
JAVA NIO는 하나의 스레드에 여러개의 연결이 있기 때문에 Selector를 이용해 어느 연결과 I/O를 실시할지 정한다.
public static Selector open() throws IOException
// 새로운 Selector 생성
public final SelectionKey register(Selector sel, int ops) throws ClosedChannelException
// Selector에는 서로 다른 채널들이 등록되어야 하며 채널에 할당하기 위해 SelectionKey를 사용
// 그 다음 프로그램에서 Selector 객체에 작업을 수행할 준비가 된 채널 키의 세트를요청
// SelectionKey는 채널에서 포인터로 제공, Selector에 채널을 등록하게 되면 (register) SelectionKey를 반환
// Selector에 채널을 할당하기 위해서는 Selector가 아닌 채널에서 register() 메소드 호출
// int ops values
SelectionKey.OP_ACCEPT -> public fianl boolean isAcceptable()
SelectionKey.OP_CONNECT -> public fianl boolean isConnectable()
SelectionKey.OP_READ -> public fianl boolean isReadable()
SelectionKey.OP_WRITE -> public fianl boolean isWritable()
SocketChannel 클래스
Socket의 수정이 필요할 경우 해당 클래스를 수정
public static SocketChannel open(SocketAddress remote) throws IOException
// 만약 파라미터 없이 open() 메소드 사용 시, open으로 channel의 실행만 실시하고 connect() 메소드를 통해 연결
public static SocketChannel connect(SocketAddress remote) throws IOException
public static SocketChannel read(SocketAddress remote) throws IOException
// ByteBuffer를 파라미터로 사용해 읽기
public abstract write(SocketAddress remote) throws IOException
// ByteBuffer를 파라미터로 사용해 읽기
public void close() throws IOException
// 포트와 리소스 해제를 위해 채널을 닫음
ServerSocketChannel
들어오는 연결을 수용하기 위해 만들어짐. Selector에서 채널이 선택되면 연결의 알림을 받는 목적으로 사용되는 accept() 메소드만 사용
public static ServerSocketChannel open() throws IOException
// open() 메소드를 통해 서버소켓으 만들 수 있다.
// SocketChannel의 open()과 달리 객체만 만들고 실제로 연결을 제공해주지는 않는다.
public abstract SocketChannel accept() throws IOException
// accept() 메소드를 통해 들어오는연결을 대기할 수 있다.
InputStream과 OutputStream
InputStream
바이트 기반 입력 스트림의 최상위 클래스로 추상 클래스
모든 바이트 기반 입력 스트림은 이 클래스를 상속받아서 만들어짐
InputStream 클래스에는 바이트 기반 입력 스트림이 기본적으로 가져야 할 메소드들이 정의 되어 있음
메소드 | 설명 |
int available() | 현재 읽을 수 있는 바이트 수를 반환한다 |
void close() | 현재 열려있는 InputStream을 닫는다 |
void mark(int readlimit) | InputStream에서 현재의 위치를 표시해준다 |
boolean markSupported() | 해당 InputStream에서 mark()로 지정된 지점이 있는 지에 대한 여부를 확인한다 |
abstarct int read() | InputStream에서 한 바이트를 읽어서 int값으로 반환한다 |
int ready(byte[] b) | byte[] b 만큼의 데이터를 읽어서 b에 저장하고 읽은 바이트 수를 반환한다 |
int read(byte[] b, int off, int len) | len만큼 읽어서 byte[] b의 off위치에 저장하고 읽은 바이트 수를 반환한다 |
void reset() | mark()를 마지막으로 호출한 위치로 이동 |
long skip(long n) | InputStream에서 n바이트만큼 데이터를 스킵하고 바이트 수를 반환한다 |
OutputStream
바이트 기반 출력 스틀미의 최상위 클래스로 추상 클래스
모든 바이트 기반 출력 스트림 클래스는 이 클래스를 상속받아서 만들어짐
OutputStream 클래스에는 모든 바이트 기반 출력 스트림이 기본적으로 가져야할 메소드가 정의되어 있음
메소드 | 설명 |
void close() | OutputStream을 닫는다 |
void flush() | 버퍼에 남아있는 출력 스트림을 출력한다 |
void write(byte[] b) | 버퍼의 내용을 출력한다 |
void write(byte[] b, int off, int len) | b 배열 안에 있는 시작 off부터 len만큼 출력한다 |
abstarct void write(int b) | 정수 b의 하위 1바이트를 출력한다 |
Byte와 Character 스트림
Byte Stream
Byte Stream은 1 byte를 Input/Output 할 수 있는 스트림이다.
동영상 이미지 음악 파일을 처리하기에 적합하다.
Byte Input Stream
자바는 객체를 생성하고 생성된 객체와 Byte Stream과 연결함으로서 파일을 연다
Byte Output Stream
장치와 연결딘 두 개의 Output Stream은 System.out, System.err를 생성한다.
Character Stream
자바 스트림 클래스 중에서 처리할 데이터가 문자인 경우에 사용한다
문자 스트림은 16bit 유니코드 문자를 주고 받는다
public class CharacterStreamStudy {
public static void main(String[] args) {
try{
FileReader input = new FileReader("a.txt");
FileWriter output = new FileWriter("b.txt");
int a;
while((a=input.read()) != -1){
output.write(a);
}
input.close();
output.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
표준 스트림 (System.in, System.out, System.err)
표준 입출력(Standard I/O)
콘솔을 통한 데이터의 입력과 콘솔로의 출력을 의미
System.out : 표준 출력
System.in : 표준 입력
System.err : System.out과같은 역할 + 입출력을 콘솔 이외 다른 대상으로 변경하는 것이 가능(표준 에러)
Scanner
메소드 | 설명 |
next() | 문자열 입력(공백, 엔터 전까지 입력) |
nextLine() | 문자열 입력(엔터 전까지 입력) |
next.charAt(0) | 문자 입력 |
nextInt() | 정수 입력 |
nextDouble() | 실수 입력 |
Scanner와 BufferedReader 차이
BufferedReader | Scanner | |
BufferSize | 8192 | 1024 |
Synchronized | O | X |
문자열 파싱 | 단순히 읽어 들임 | 문자열 파싱 가능 |
Exception | IOException 던짐 | IOException 숨김 |
파일 읽고 쓰기
파일 쓰기(File Write)
import java.io.*;
//파일 쓰고 읽기 테스트
public class FileMake {
public static void main(String[] args) {
/***********************FILE WRITE***********************/
try( //요기서 객체를 생성하면 try종료 후 자동으로 close처리됨
//true : 기존 파일에 이어서 작성 (default는 false임)
FileWriter fw = new FileWriter( "coding532.txt" ,true);
BufferedWriter bw = new BufferedWriter( fw );
)
{
bw.write("손흥민"); //버퍼에 데이터 입력
bw.newLine(); //버퍼에 개행 삽입
bw.write("이강인");
bw.newLine();
bw.flush(); //버퍼의 내용을 파일에 쓰기
}catch ( IOException e ) {
System.out.println(e);
}
File f = new File("coding532.txt");
// 파일 존재 여부 판단
if (f.isFile()) {
System.out.println("coding532.txt 파일이 있습니다.");
}
}
}
파일 읽기(File Read)
import java.io.*;
//파일 쓰고 읽기 테스트
public class FileMake {
public static void main(String[] args) {
/***********************FILE WRITE***********************/
try( //요기서 객체를 생성하면 try종료 후 자동으로 close처리됨
//true : 기존 파일에 이어서 작성 (default는 false임)
FileWriter fw = new FileWriter( "coding532.txt" ,true);
BufferedWriter bw = new BufferedWriter( fw );
)
{
bw.write("손흥민"); //버퍼에 데이터 입력
bw.newLine(); //버퍼에 개행 삽입
bw.write("이강인");
bw.newLine();
bw.flush(); //버퍼의 내용을 파일에 쓰기
}catch ( IOException e ) {
System.out.println(e);
}
File f = new File("coding532.txt");
// 파일 존재 여부 판단
if (f.isFile()) {
System.out.println("coding532.txt 파일이 있습니다.");
}
/***********************FILE READ***********************/
try(
FileReader rw = new FileReader("coding532.txt");
BufferedReader br = new BufferedReader( rw );
){
//읽을 라인이 없을 경우 br은 null을 리턴한다.
String readLine = null ;
while( ( readLine = br.readLine()) != null ){
System.out.println(readLine);
}
}catch ( IOException e ) {
System.out.println(e);
}
}
}
ref {
https://velog.io/@bahar-j/자바의-입출력IO와-스트림
https://adrian0220.tistory.com/150
https://develop-im.tistory.com/54
https://velog.io/@rabbit/Byte-Character-스트림
}
'Programming > Java' 카테고리의 다른 글
[JAVA] 람다식 (0) | 2022.04.18 |
---|---|
[JAVA] 제네릭 (0) | 2022.04.11 |
[JAVA] Annotation (0) | 2022.03.28 |
[JAVA] ENUM (0) | 2022.03.21 |
[JAVA]멀티쓰레드 프로그래밍 (0) | 2022.03.14 |
댓글