날아라쩡글이의 블로그입니다.

I/O 본문

중앙 HTA (2106기) story/java API story

I/O

날아라쩡글이 2021. 10. 14. 21:49
반응형

I/O는 java.io package에 포함되어 있는 클래스 이다. 

  • App에서 리소스를 읽어오거나 App에서 데이터를 목적지로 출력하는 작업을 수행하는 클래스이다. 
  • 내 App이 기준점으로 자원을 읽어오면 Input File을 출력하면 OutPut 으로 방향에 따라서 읽어오는 Stream와 내보내는 Stream이 존재한다. 
  • 클래스의 종류의 경우 한번에 읽고 쓰는 데이터에 따라서 구별이 가능하다. 
  • ByteStream(바이트스트림)
    • 한번에 한 1bite씩 읽고, 쓸 수 있는 스트림
    • 바이너리데이타를 다룸 
    • 010101형태로 읽는 스트림
      • InputStream, OutputStream
      • FileInputStream, FileOutputStream
      • BufferedInputStream, BufferedOutputStream
      • DataInputStream, DataOutputStream
      • ObjectInputStream,ObjectOutputStream
      • printStream
  • CharactStream(캐릭터스트림)
    • 한번에 한글자씩 읽고 쓸수 있는 스트림이다. 
      • Reader, writer
      • FileReader, FileWriter
      • BufferedReader, BufferedWriter
      • printWriter
  • 방향에 따라서 구별된다. 
    • 읽기 InputStream, InputReader
    • 쓰기 OutputStream, OutputReader
  • 위치에 따라서 구별된다. 
    • 1차 Stream, 말단 Stream
      • 직접 리소스와 연결되는 Stream
      • FileInputStream, FileOutputStream
      • FileReader, FileWriter
    • 브릿지 Stream
      • byteStream과 CharactStream을 연결하는 Stream
        • InputStreamReader
        • OutputStreamWriter
        • Input과 Output, Reader와 Writer가 함께 공존한다. 
    • 2차 Stream
      • 직접 리소스와 연결할 수 없는 Stream
      • 1차 Stream혹은 브릿지Stream과 연결해서 사용하는 Stream
      • 보통 2차 Stream은 자신과 연결된 Stream의 읽거나 쓰는 능력을 향상시킨다. 
      • 다른 Stream과 Writer, Reader와 연결해야한다. 
        • BufferedInputStream, BufferedOutputStream
        • BufferWriter,BufferReader
        • DataInputStream, DataOutputStream
        • ObjectInputStream,ObjectOutputStream
    • 출력전용Stream 
      • 출력하는 기능만 있는 Stream
        • printStream, printWriter
  • 텍스트 데이터 
    • 메모장에서 열어서 볼 수 있는 데이터
    • Java에서 복사, 분석을 할 수 있다. 
    • ByteStream에서 다룬다. 
  • 바이너리 데이터 
    • 메모장에서 열어서 볼 수 없는 데이터
    • 열게 되면 이상한 숫자로 나오는 데이터이다. 
    • 그림, 영상, 압축파일, 각종 한글, 워드, 엑셀, 파워포인트등의 파일
    • 전용프로그램을 통해서만 데이터를 보고 편집할 수 있다. 
    • 우리는 복사로 옮기기만 한다. 첨부파일 업로드 하는 방식이다. 
  • 우리가 확인하는 데이터는 Text Data밖에 없다. 다른 것은 전용프로그램을 통해서만 Data 확인이 가능하기 때문이다. 

Stream이란 

  • 데이터를 운반하는데 사용되는 연결통로이다. 
  • 연결되는 통로로써 1차Stream과 연결되어 소스와 직접 연결하여 사용한다. 
    • 파일명을 입력하는 곳에 생성자, URL, 파일 경로를 입력할 수 있다. 
    • 그러나 속도가 느리기 때문에 
  • 2차 Stream을 이용하여 1차Stream의 성능을 높여주는 Stream을 연결하여 사용할 수 있다. 
  • 수도 파이프에 호스를 달면 물은 나오지만 샤워기처럼이 아닌 콸콸나오는 것처럼 2차Stream인 샤워기를 이용하여 물을 원하는데로 사용랄 수 있다. 
  • 2차 Stream은 1차 Stream과 연결하여 성능을 높여줄 수 있다. 

브릿지 Stream이란,

  • Reader는 문자로만 읽고, Writer의 경우는 문자로 작성한다. 
  • InputStream은 Byte단위로 읽고, OutputStream으로 Byte단위로 보낸다. 
  • 그렇기 때문에 서로 연결을 해줄 수 없어서 가운데에 브릿지Stream을 연결하여, 
  • Byte에서 한글자로 읽고, 보내는 역활을 진행한다. 
  • 1차 ->브릿지 -> 2차 이런 순으로 데이터를 보낼 수 있다. 

FileWriter

  • 모든 I/O의 경우 예외처리가 기본이다. IOException
  • throws처리해도 되고, try catch문으로 진행해도 된다. 
  • 파일에 텍스트를 기록, 출력한다. 
  • text만 입력되기 때문에 줄바꿈문자는 따로 입력해줘야한다. 
  • write가 중복정의 되어있고, String이 반환타입이다. 
  • 꼭 close를 해주어야한다. 

PrintWriter <입력하면 바로 이 객체를 사용하자!!!!>

  • 텍스트를 출력하는 객체이다. 
  • write(String text) 
    • 보통의 출력 객체는 이 메소드만 가지고 있다. 
  • println(String text) 등의 메소드를 가지고 있다. 
    • 중복정의된 println(값) 메소드를 가지고 있다. 
    • println 메소드는 줄 바꿈 문자를 자동으로 추가한다. 
    • CSV 데이터를 기록할 때 유용하다. 
    • 업무용 시스템을 만들기 때문에 무의미한 데이터는 입력하지 않는다. 
    • 유용한 데이터는 특별한 형식으로 기록되어 있다. 
    • 제일 유용하다. 
    • writer에서는 FileWriter와 printWriter만 기억하면 된다. 

BufferedReader<읽기하면 바로 이 객체를 사용하자!!!!>

  • Reader에서 제일 기억해야 하는 객체 
  • 텍스트를 읽어오는 객체이다. 
  • 텍스트를 한 줄씩 읽어오는 String readLine()메소드를 제공한다. 
  • 텍스트를 한 줄씩 읽어오는 객체는 이 객체 하나 뿐이다. 
  • 한 줄을 읽고 그 줄에서 읽어올 데이터가 없으면 null을 반환한다. 
  • readLine() 줄바꿈 문자 앞까지 읽어서 반환한다. 
  • readLine()은 더 이상 읽어 올 데이터가 없으면 (Stream끝에 도달하면) null을 반환한다. 
    • 우리가 가져오는 text data는 CSV의 형태를 가지고 있다. 
    • 정형적인 데이터의 형식을 가지고 오지, 불 규칙한 데이터에서 읽어오는 경우는 존재하지 않는다. 
    • 정형데이터 
      • 규칙에 맞춰져 있어서 읽을 수 있다. 
      • CSV가 대표적이다. 
      • 한 줄씩 의미를 갖고 있어서, 한 줄씩 읽어내는 기능이 중요하다. 
      • BufferedReader밖에 없다. 
    • 반정형데이터 
      • 일정한 형식을 가지고 있지만 약간의 손을 거쳐야지 데이터를 읽을 수 있다. 
      • 데이터 분석하는 경우도 로그 Data로 반정형 데이터를 가지고 있어서 , 약간의 손을 거쳐야지 데이터를 읽을 수 있다. 
    • 비정형데이터 
      • 일반 text를 의미한다. 
  • BufferedReader는 위에 작성되어있듯이 2차 Stream으로 1차 Stream 혹은 브릿지 Stream이 있어야한다. 
  • 파일 내용을 읽어오는 FileReader객체를 생성한다. 
    • FileReader의 읽기 메소드는 1글자씩만 읽어온다. 
    • Stream의 text Data를 한 줄을 읽어오는 BufferedReader객체를 생성한다. 
  • BufferedReader가 읽어올 텍스트를 전달하는 FileReader객체를 BufferedReader한테 생성자 인자로 전달한다. 
  • 파일의 텍스트 데이터를 읽어오는 FileReader를 BufferedReader에게 전달한다. 
  • Stream에서 한줄씩 읽어서 text에 대입한다. 
    • text = reader.readLine();
    • text에 대입된 값이 null 아니면 true이다. 
    • 즉, while문 블록내의 수행문이 실행된다. 
    • while((text = reader.readLine()) != null) 반복문으로 돌리고, 
    • String[] values = text.split(",");으로 나눠서 
    • 각 배열에 하나씩 입력한다. 
    • index상으로 1번부터는 숫자기 때문에 return type은 int로 Integer.ParseInt(values[1].trim());으로 전환한다. 
    • 그리고 출력해주면된다. 
  • 마지막에는 닫는 메소드를 입력해주어야한다. 
  • try~catch문으로 예외를 잡아줘야한다. 

텍스트 데이터의 읽고, 쓰기 

  • 텍스트 데이터를 출력하기 
    • App에서 생성된 텍스트 데이터를 출력하기 
    • PrintWriter의 println()을 사용한다.
    • 리소스가 파일인 경우 printWriter writer = new printwriter("c:/temp/doc/example2.txt");를 출력한다. 
  • 텍스트 데이터 읽기 
    • App에서 분석할 텍스트 데이터를 읽기 
    • BufferedReader의 readline()을 사용한다. 
    • 리소스가 파일인 경우 
      • FileReader fileReader = new fileReader("c:/temp/doc/example2.txt");을 작성한다. 
      • BufferedReader reader = new BufferedReader(fileReader);을 입력한다. 
  • text 파일은 다운로드하거나 첨부파일 업로드 하는 것은 위에 해당되지 않는다.
  • text파일을 전송하는 것 (업로드, 다운로드 하는 것)은 위에 해당되지 않는다. 

객체가 들어오는 것은 CSV파일 자동처리 라이브러리가 있다. 지금까지 파일을 기록하고 파일을 읽어봤다. 

리소스가 File이었다.

리소스데이타가 파일이 아닌 URL인 경우를 확인해보자 

  • 파일의 경우 FileReader을 2차 Stream인 BufferedReader와 연결해주면 완료가 되었다. 
  • 리소스의 경로 , 주소만 있다면 전부 다 가져올 수 있다. 
  • String path= "";로 주소를 설정해준다. 
    • 쿠키가 있어야한다. 
    • 프로토콜, 호스트번호, 경로, 포트번호가 들어가 있는 경로를 입력한다. 
    • 이것을 분석해서 갖고 있는 객체가 URL이다. 
  • Java.net의 URL
    • URL url = new URL(path);
    • String객체 참조변수를 생성자에 입력한다. 
    • 자원이 있는 주소로, URL 주소가 가르키는 리소스를 1byte씩 읽어오는 스트림 객체를 획득했다. 
  • InputStream inputStream = url.openStream(); 
    • File, Jpeg, pnp를 얻을 수 있다. 
  • InputStreamReader isr = new InputStreamReader(inputStream);
    • byteStream과 연결되는 Reader개체를 생성한다. 
  • BufferedReader reader = new BufferedReader(isr);
    • 한 라인씩 읽어오는 BufferedReader와 InputStreamReader객체를 연결한다.

이 3가지를 합쳐서 한번에 작성할 수 있다. 

BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));

  • 이렇게 한꺼번에 적어서 완성할 수 있다. 
  • 한 줄씩 읽어올 수 있다. 
  • 데이터에 대한 컬럼명 획득하기 
    • 한 줄을 버리고 싶다면 reader.readLine();으로 버릴 수 있다. 
    • 단 방향이기 때문에 이미 지나간 것을 다시 읽을 수 없다. 
    • 그렇기 때문에 while문으로 돌리기전에 사용하면 두번째 줄 이후로 출력이 된다. 
    • String text = null; 
      • reader.readLine(); 한 줄씩 출력되는 내용을 입력할 String을 설정하였다. 
    • while((text = reader.readLine()) != null) 
      • //while문은 reader.readLine()이 null값이 아니면 반복한다. 
    • String[]values = text.split(",");
      • //text상 ,표시가 있으면 잘라서 String 배열에 넣는다. 
  • int amount = Interger.parseInt(values[5]) 
    • 거래 금액이 있는 index를 amount에 입력한다. 
    • totalAmount += amount; 해서 totalAmount에 더한다. 
  • 그리고 데이터를 읽고 원하는 정보를 획득할 수 있다. 
  • 예외의 경우 try(이 곳에 입력하면) close();메소드를 따로 호출하지 않아도 된다.

실제 read와 write로 데이터를 획득하기 

  • VO class를 완성한다. getter을 입력한다. 
  • 입력 하기
  • ScoreWriter을 입력한다. 
  • main메소드를 입력한다. 
  • List<Score> scoreList = new ArrayList<>();
  • List객체에 저장된 학생성적 정보를 Score.txt파일로 저장할 예정이다. 
    • try (PrintWriter writer = new PrintWriter(경로 입력)) {
    • StringBuilder sb = new StringBuilder();
    • 향상된 for문으로 List를 돌린다. 
    • StringBuilder에 저장한다. 
    • sb.append(Score.getName());
    • writer.println(sb.toString());
    • StringBuilder의 toString()메소드를 호출하여 writer.println()을 이용하여 경로입력한 곳에 저장한다. 
    • sb.setLength(0);
      • String배열에 들어있는 데이터를 0으로 만들어 버렸다. 
      • 데이터를 지워버리는 역활을 수행한다. 
      • save버튼을 만들어서 입력할 수 있다. 
      • 파일에 데이터를 영속화할 수 있다. 
  • 읽어 오기 
    • try (BufferedReader reader = new BufferedReader(new FileReader(경로를 입력한다. ));{
      • 읽어올 데이터가 여러개의 정보이다. 
      • 행하나가 객체 하나에 대응된다. 
      • 여러개를 담을 ArrayList가 필요하다. 
        • HashSet은 같은 정보는 못 담으니까 순차적으로 쌓는 ArrayList에 담아준다. 
    • List<Score> scores = new ArrayList<>();
      • Score.txt파일에서 읽어온 성적정보를 저장하는 ArrayList객체
    • String text = null; 
    • while((text = reader.readLine()) != null) {
      • text -> "홍길동,100,100,100" 으로 읽을 수 있다. 
    • String[] values = text.split(",");
      • values -> ["홍길동","100","100","100"]으로 저장된다. 
    • 각자 배열의 값을 분석하여 입력한다. 
    • Score score = new Score (name, kor, eng, math); 
      • Score객체를 생성해서 분석된 성적정보를 입력한다. 
      • scores.add(score); 
      • 성적 정보가 저장된 Score객체를 ArrayList객체에 저장한다. 
    • 데이터 조작/ 분석하기 
      • 학생들의 전체 평균 점수 계산하기 
      • int totalAverage = 0; 
        • 변수의 초기화 
      • 향상된 for문으로 totalAverage + = score.gerAverage(); 진행하고 
      • totalAverage/scores.size();로 평균점수에서 size를 나눠서 전체 평균으로 작성할 수 있다. 

 

읽는 법

  1. 파일 
    • FileReader 
    • FileInputStram
  2. 메모리 
    • StringReader 
    • ByteArrayInputStream
  3. 네트워크 
    • Socket
    • getInputStream()
  4. 인터넷
    • InputStream 
    • InputStreamReader
    • BufferedReader

text -> 객체  객체 -> text 왜 변환하는 걸까?

  • 간단하게 넘어갔지만, 직렬화에 좋다는 이야기가 있다. 그건 다음시간에 다뤄볼 예정이다. 

CharactStream(캐릭터스트림)

  • InputStream (추상 클래스 )
    • abstract int read();
    • int read(Byte[] byf) {.....}
    • close(){....}
      • 구현클래스 
      • FileInputStream
      • BufferInpurStream
      • ByteArrayInputStream
      • DataInputStream
        • 구현 
        • readInt()
        • readLong()
        • readBoolean()
        • readUTF()
      • pipedInputStream
      • FilterInputStream
      • printStream 
        • print()
        • println()
  • OutputStream (추상 클래스 )
    • abstract void write(int value); 
    • void write(byte[] buf, int offSet int len) {...}
    • void flush(){...}
    • void close(){...}
      • 구현클래스 
      • FileOutputStream
      • BufferOutputStream
      • ByteArrayOutputStream
      • DataOutputStream
        • 구현 
        • writeInt(int value)
        • writeLong
        • writeDouvle
        • writeUTF(String value)
      • pipedOutputStream
      • FilterOutputStream
  • Reader(추상 클래스 )
    • abstract int read();
    • int read(char[] buf)
    • void close(){...}
      • 구현클래스 
      • FileReader
      • StringReader
      • BufferedReader
        • readLine()
      • InputStreamReader
  • writer(추상 클래스 )
    • abstract void write(int value)
    • void write(char[] buf, int offSet, int len)
    • void write(String text) {...}
    • void close(){...}
      • 구현클래스 
      • FileWriter
      • StringWriter
      • BufferedWriter
      • OutputStreamWriter
      • printWriter
        • print()
        • println()

InputStream, OutputStream은 바이너리 데이터일 때 사용함.

  • 그림파일, 영상파일, PPT, 데이터들, 흔하게 만나는 데이터 
  • 응용 프로그램으로 파일을 생성하는것은 거의 사용하지 않는다. 
  • 내 파일을 어딘가에 전송하거나, 클라우드 다운, 올릴 때

FileInputStream , FileOutputStream은 파일을 옮기는 작업을 할 때 많이 사용한다.

  • Copy는 전송, 업로드, 다운로드 전부 copy이다. 복사하는  방식이다.

FileCopy하기 

 

  • File을 copy하면, 같은 유니코드로 복사지만, 파일을 표시하는 매직넘버에 따라서 형태가 달라진다. 
  • 복사를 받는 반환타입은 int의 값으로 3Byte는 0으로 출력 1Byte에만 값을 담는다. 
  • 바이너리 데이터는 Input/ outPut으로 업로드와 다운로드작업을 빈번히 사용한다. 
  • 입출력시 BufferedInputStream을 사용하는 것이 좋다. 
  • 일반 InputStream의 경우 1Byte를 옮기게되는데, 그렇다면 1층~ 10층까지 택배 100개를 옮기면 100번 왔다갔다하는 것과 동일하게 속도가 엄청 느리기 때문이다. 
  • 2차 스트림인 Buffered를 사용하면 속도가 엄청 빨라지는데, 1번에 8KB씩 옮기기 때문이다. 

복사 객체 만들기 

  • FileInputStream in = new FileInputStream("경로"); 
    • 원본파일을 1byte씩 읽어오는 Stream을 생성했다. 
  • FileOutputStream out = new FileOutputStream("복사될 경로");
    • 복사본 파일을 생성하고 1byte씩 출력하는 Stream객체를 생성
  • 파일이 얼마나 큰값인지는 모르지만 파일의 맨끝은 -1로 저장된다. 
  • int value = 0;
    • 1byte씩 읽은 값을 저장하는 변수 
  • while((value = in.read)) != -1){
    • 1byte씩 읽어서 value에 저장하고, value에 저장된 값이 -1이 나올때까지 수행문 반복한다. 
    • out.write(value);
      • value에 저장된 값을 복사본파일에 꺼내서 저장한다 . 
  • in.close()
  • out.close()
    • copy code는 이게 끝이다. 

링크된 파일사진을 다운받기 

  • URl url = new URL("링크 주소");
  • InputStream in =url.openStream();
    • 반환타입이 inputStream으로 연결되어 있다. 
  • FileOutputStream out = new FileOutputStream("다운받을 경로. 유형");
    • 복사본 파일로 1byte씩 출력하는 스트림객체를 생성
    • 다른 컴퓨터로 보낼 수 있다. 그때는 FileOutputStream객체를 사용안함. 
  • int value = 0;
  • while(((value = in.read()) != -1) {
  • out.write(value);
  • }
  • in.close();
  • out.close();
  • 자원의 누수를 막는 close();를 꼭 설정해줘야한다. 

BufferedInputStream 과 BufferedOutputStram을 이용하여 읽기, 쓰기 속도를 향상 시키자 

  • long beginUnixTime = System.currenTimeMillis();
    • 시작과 끝의 유닉스 타임을 비교하기 위해 유닉스타임 코드를 작성함 
  • FileInputStream fis = new FileInputStream("복사할 파일 경로 입력");
  • FileOutputStream fos = new FileOutputStream("복사해놓을 파일 경로 입력");
  • BufferedInputStream in = new BufferedInputStream(fis);
  • BufferedOutputStream out = new BufferedOutpuutStream(fos);
    • InputStream과 OutputStream으로 읽기 쓰기 속도를 향상시키는 2차stream이다. 
  • int value = 0;
  •  while((value = in.read()) != -1) {
  • out.write(value);
  • }
  • fis.close();
  • fos.close()
  • long endUnixTime = System.currenTimeMilis();
  • 소요시간 : endUnixTime - beginUnixTime
반응형
Comments