JAVA/Basic

[스터디할래? Java 13]I/O

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다. 

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >> https://www.notion.so/I-O-af9b3036338c43a8bf9fa6a521cda242

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

I/O Input & Ouput 입출력
java.io  // 데코레이션 패턴으로 만들어짐 : 
컴퓨터 내부 또는 외부장치와 프로그램간 데이터 주고받기. 
ex) 키보드 데이터 입력, System.out.println()
데코레이션패턴 객체의 타입, 메소드 그대로 유지하면서 새로운 책임을 추가할때 사용. 
탈부착가능한 책임. 
하기 코드 참고.
ex)
BufferedInputStream 담아 보내면 모아서 보내서 시스템 콜 횟수가 줄어서 성능이익
Stream 스트림이란 데이터를 운반하는데 사용되는 연결 통로. 
단방향 통신만 가능. 
먼저 보낸데이터 먼저, 중간에 건넘뜀없이 연속적
바이트 단위로 데이터 전송
AutoCloseable(1.7) <-Closeable(1.5) <- InputStream (1.0) <- FileInputStream (1.0)
                                               <- OutputStream (1.0) <- FileOutputStream (1.0)
InputStream/OutputStream 상속받은 클래스 종류

- FileInputStream / FileOutputStream : 파일
- ByteArrayInputStream / ByteArrayOutputStream
                                              : 메모리(Byte배열) > 메모리만써서 close필요없음
- PipedInputStream / PipedOutputStream : 프로세스간 통신
- AudioInputStream / AudioOutputStream :오디오 장치 

소스작성 흐름
1. FileInputStream : HDD에 존재하는 파일과 연결
2. InputStreamReader : 8bit Stream 16bit stream 연결, char변경(encoding)
3. BufferedReader : 스트림으로 연결된곳에서 줄단위로 읽음. readLine()
InputStream  InputStream 의 추상메서드 read()  --> reader

public abstract class InputStream implements Closeable {
    public abstract int read()  
* byte단위 전송, int값을 가져옴- 4byte중 1byte 이용 범위가 0~255 와 -1 이기때문.

    public int read(byte b[]) 
    public int read(byte b[], int off, int len) 
    public long skip(long n)               // 주어진길이만큼 건너뜀
    public int available()                    //스트림으로부터읽을수 있는 데이터 크기 반환
    public void close()                       // 닫고 사용하던자원반환
    public synchronized void mark(int readlimit) //현재 위치 표시. reset에의해 다시돌아감
    public synchronized void reset()     //스트림위치를 마지막 mark호출된위치 되돌림
    public boolean markSupported()    // mark reset 기능 제공하는지 확인

OutputStream  OutSteream 의 추상메서드 write()  --> writer

public abstract class OutputStream implements Closeable, Flushable {
    
    public abstract void write(int b)  주어진값출력소스에 쓴다. 
    public void write(byte b[])
    public void write(byte b[], int off, int len)
    public void flush()  : 스트림의 버퍼에 있는 모든 내용을 출력소스에 쓴다. 
    public void close()  : 입력소스 닫음으로써 사용하던 자원반납

}
보조 스트림 보조 스트림 : 기능향상, 새로운기능 추가.
각각 inputStream, OutputStream 상속
- FilterInputStream / FilterInputStream 
- BufferedInputStream / BufferedOutputStream
- DataInputStream/DataOutputStream
- SequenceInputStream /없음
- LineNumberInputStream/없음
- PushbackInputStream/없음
- 없음/PrintStream
표준입출력 콘솔을 통한 데이터 입력, 출력
System.in   : inputStream
System.out : PrintStream
System.err : printStream
FileReader /FileWriter FileReader(1.1) -> InputStreamReader(1.1)->Reader(1.1)--> Readable(1.5), Closerble(1.5)
Reader : 문자기반 스트림. byte배열대신 char 배열사용. 자동인코딩
4byte 중 2byte 사용해서 문자단위전송. 

FileReader fileReader = new FileReader("파일이름경로");
fileReader.read() ;
fileReader.close();
Byte스트림 vs Character스트림 Byte 스트림 : 8bit :한번에 전달하는양 작지만 속도빠름
InputStream - FileInputStream, ObjectInputStream, DataInpuStream
Char스트림: 16bit : 한번에 전달하는양 많지만 속도 느림. 
Reader : FileReader , InputStreamReader, BufferedReader
PipeReader /pipeWriter 입출력스트림을하나의 스트림으로 연결
직렬화 Serializable , 파일 읽을때쓸때, 웹에서 데이터 보내고 받을때 줄로보냄. 그때 사용. 
transient - 직렬화 제외
serialVersionUID = 버전관리,  
NIO New Input / Output 새로운 입출력(jdk1.4)
java.nio.channels : 파일채널, TCP, UDT 채널
java.nio.channels.spi java.nio.channels 위한 서비스 제공자. 
java.nio.charset 문자셋 인코더 디코더 API
java.nio.charset.spi
java.nio.file 파일 파일시스템 접근위한 서비스
java.nio.file.attribute 속성접근
java.nio.file.spi
java.nio.buffer
...
입출력방식은  IO는 스트림 NIO 는 채널방식  : 스트림은 매번 생성, 채널은 만들필요없음
버퍼 방식은   IO 넌버퍼,   NIO 는 버퍼 : IO는 넌버퍼라서 bufferedInputStream 연결사용
비동기방식   IO 지원안함 , NIO 지원   : 
프로킹/넌블로킹 IO 블로킹방식만 지원 : 동기, NIO 블로킹/넌블로킹 모두 지원
                                          블로킹(대기상태): IO는 인터럽트안되나 NIO는 가능    
                                          넌블로킹(쓰레드가 입출력시 블로킹안됨)
* NIO 전 FileReader 사용했음. FileWriter 사용 추천. 
Buffer 읽고 쓰기가 가능한 메모리 배열(일반)
데이터를 전송하는 상호간 장치에서 OS system core (저속)와 java api호출(고속) 장치간의 속도차이로 인해 저속 장치가 작업을 추리하는 동안 기다리는 현상 줄어짐
 buffer는 사이즈 지정이 가능, 효율관런 고려 가능

package java.nio;
public abstract class Buffer (1.4))
버퍼에 담았다 한번에 모아서 보냄. 입출력 횟수 줄어 성능이점
ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer
할당:
바이트버퍼.allocatedDirect(크기);
- 다이렉트    Direct      : 운영체제 관리 메모리공간 :생성시간 느림, 한번생성재사용, IMDG 참고
바이트버퍼.allocated(크기);
- 넌다이렉트 NonDirect : JVM 관리 힙 메모리 공간. :생성시간은빠름, 큰크기사용힘듬
https://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html
Channel 파일, 소켓, 데이터그램등과 같은 I/O소스로부터 데이터 블록을 버퍼로 쓰거나 읽음. 
- Socket과 연결, 입출력 역할 수행
- 입력과 출력을 동시 수행
- Selector와 연결, 하나Selector에 다수 채널 존재
- Blocking 스레드 깨우거나 다시 Blocking할수 있다. 
기존 IO 에서 쓰레드에 Reader, Writer만 존재해 Reader로 블로킹, Writer로 블로킹풀어줌
NIO 에서 Non-blocking방식, 쓰레드 -버퍼사이 터널을 만들어주는데 이것이 채널하는역할
package java.nio.channels;
public interface Channel extends Closeable {
https://adrian0220.tistory.com/150
selector java NIO에서 하나의 쓰레드에 여러개 연결이 있어
Selector를 이용해 어떤채널과 연결 선택, 
선택된 채널이 스레드와 버퍼 연결 진행하는게 NIO 매커니즘.  
NIO 파일 읽고 쓰기 package study;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class NIOReadeWrite {
    public static void main(String[] args) throws IOException {

        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String contexts = localDateTime.format(formatter) +"  "+ "안녕하세요 \r\n";
        String path = "C:\\Users\\신미성\\Desktop\\test.txt";
        fileWrite(contexts, path);
        fileRead(path);
    }

    public static void fileWrite(String contents, String pathString) {
        Path path = Paths.get(pathString);
        try(FileChannel writeFileChannel
                    = FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE)){
            ByteBuffer byteBuffer =  Charset.defaultCharset().encode(contents);
            writeFileChannel.write(byteBuffer);
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    private static void fileRead(String pathString) throws FileNotFoundException {
        Path path = Paths.get(pathString);
        if (!Files.exists(path))
            throw new FileNotFoundException("경로 없음");
        try(FileChannel readFileChannel = FileChannel.open(path, StandardOpenOption.READ)){
            ByteBuffer byteBuffer = ByteBuffer.allocate((int)Files.size(path));
            readFileChannel.read(byteBuffer);
            byteBuffer.flip();
            System.out.println(Charset.defaultCharset().decode(byteBuffer).toString());
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}


참고는 했으나.. 파일생성은 없었음.  : https://multifrontgarden.tistory.com/194
StandardOpenOption APPEND
CREATE                 없으면생성
CREATE_NEW         파일생성 있으면 에러남
DELETE_ON_CLOSE
DSYNC
READ
SPARSE
SYNC
TRUNCATE_EXISTING
WRITE

https://docs.oracle.com/javase/7/docs/api/java/nio/file/StandardOpenOption.html
IMDG IMDG(In Memory Data Grid)는 메인 메모리에 데이터를 저장
자바가 쓸수있는것보다 더큰메모리 저장가능

component 부품

decorate 꾸미다. 

책추천 : 유닉스의탄생

개발자취업  https://codesquad.kr/page/masters/curriculum.html

 

데코레이션패턴

package study;

public class CoffeDeco {
    public static void main(String[] args) {
        Latte latte = new Latte();
        System.out.println(latte);
    }
}

//component
abstract class Beans{
    protected String name="원두";
    public abstract double cost();
    public String getName() {return name; }
    public String toString(){return getName() +" : " +cost(); }
}
//deco
abstract class AddMilk extends Beans{
    public abstract String addMilk();
}
class Espresso extends Beans{
    Espresso(){name = "에스프레소"; }
    @Override
    public double cost() { return 1000;}
}
class Latte extends AddMilk{
    Latte(){name = "라떼"; }
    @Override
    public double cost() {return 3000;}
    @Override
    public String addMilk() {return "HALF"; }
    @Override
    public String toString() {
        return super.toString()+"(Milk:"+addMilk()+")";
    }
}

//참고사이트 : https://johngrib.github.io/wiki/decorator-pattern/
  • 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O
  • InputStream과 OutputStream
  • Byte와 Character 스트림
  • 표준 스트림 (System.in, System.out, System.err)
  • 파일 읽고 쓰기