수업 정리

18일차 수업 정리(IO - Input, Output)

Vita500cc 2020. 5. 1. 21:53

**Input & Output(IO)
    => MainMemory와 주변 장치(파일, 키보드와 같은 입출력 장치, 네트워크 등)들 간의 통신
1. java.io.File 클래스
    => 파일에 대한 정보를 리턴해주는 클래스
  1) 경로(위치 설정)
    => 절대경로 : root로 부터의 경로, 불변의 경로
        -> 윈도우즈 - c:\디렉토리명...\파일명
        -> 그외의 운영체제 - /디렉토리명.../파일명
        -> 웹 - http://요청경로
        -> 윈도우즈만 디렉토리 구분 기호가 \이고, 나머지 경우는 전부 / 윈도우즈 경로 표시시 \\로 표현해야 함
    => 상대경로 : 현재 위치로 부터의 경로, 현재 위치에 따라 변함
        -> ./ : 현재 디렉토리
        -> ../ : 상위 디렉토리
        (현재 디렉토리는 생략해도 되는 경우가 대부분이고, Mac의 경우는 터미널에서 에러가 남
  2) 파일 객체 
    => 생성 : File(String pathname), File(String parent, String child)
         (파일의 경로를 가지고 생성)
  3) 중요한 메소드
    => boolean exists() :  파일의 존재 여부를 리턴
    => boolean delete() : 파일을 삭제하고 삭제 성공 여부를 리턴
    => long lastModified() : 최후 수정 시간을 정수로 리턴
    => long length() : 파일의 크기를 리턴
    => String[ ] list() : 디렉토리의 경우 내부에 존재하는 파일의 목록을 문자열로 리턴
  4) 서버로 부터 데이터를 다운로드 받는 애플리케이션 생성
    => 서버에 접속할 때 마다 데이터를 다운로드 받는 것은 자원의 낭비
    => 처음에 접속 할 때 데이터를 다운로드 받아서 파일로 저장해두고 사용
    => 다음에 접속 했을 때는 데이터의 변경 발생시 다운로드, 그렇지 않으면 이전 데이터를 계속 사용

2. java.nio.file.Path
    => File 클래스에 기능을 추가한 새로 등장한 API
    => File 클래스는 symbolic link(바로가기)를 생성 할 수 없음
    => File 클래스는 디렉토리 밑의 파일의 생성/갱신/삭제를 감시할 수 없음

3. 입출력 Stream
    => 데이터를 주고 받는 연결 통로
    => 파일이나 네트워크등과 통신하기 위해서는 스트림이 필요
  1) 입출력에 따른 분류
    => InputStream : 입력을 받기 위한 스트림(외부에서 읽어오기 위한 스트림)
    => OutputStream : 출력을 하기 위한 스트림(내부의 데이터를 전송하기 위한 스트림
  2) 전송 단위에 따른 분류
    => byteStream : 바이트단위로 전송하는 스트림, 문자가 아닌(그림등) 데이터의 전송에 사용, 타 기종간 통신에 이용
    => CharacterStream : 문자단위 전송
    => ObjectStream : 인스턴스 단위로 전송
    => 자바 소켓서버와 iOS가 채팅을 하는 경우 기본적으로는 ByteStream을 이용해야 합니다.

** ByteStream
    => 데이터를 Byte 단위로 주고 받는 스트림
1. InputStream & Output Stream
  1) InputStream
    => Byte 단위로 입력받기 위한 스트림을 위한 추상클래스
    => 공통으로 사용할 메소드를 선언한 클래스

    => int available() : 읽을 수 있는 바이트 수 리턴
    => void close() : 스트림을 닫는 메소드
    => int read() : 하나의 바이트를 읽어서 정수로 리턴, 읽은 데이터가 없으면 -1을 리턴
    => int read(byte[ ] b) : 데이터를 읽어서 b에 저장하고 읽은 바이트 수를 리턴, 읽은 데이터가 없으면 -1을 리턴
    => int read(byte[]b, int off, int len) : 데이터를 읽어서 b에 저장, off부터 len만큼만 저장후 읽은 바이트 수를 리턴, 

                                                  읽은 데이터가 없으면 -1을 리턴
    => long skip(long n) : n만큼 넘어가는 메소드

  2) OutputStream
    => 바이트 단위로 데이터를 전송하기 위한 스트림의 추상 클래스
    => 다른 클래스에서 공통으로 사용할 메소드를 선언만 한 클래스

    => void close() : 스트림을 닫는 메소드
    => void write(int b) : b 1개를 전송
    => void write(byte[] b) : b배열을 전송
    => void write(byte[] b, int off, int len) : b배열에서 off부터 len만큼 전송
    => void flush() : 버퍼의 내용을 전부 전송

    => 데이터 전송시, 버퍼에 모아서 한꺼번에 전송. wirte로 데이터 전송시 버퍼의 크기를 넘어서면 전송을 하지만 그렇

       지 않으면 전송하지 않는 경우가 발생하는데 이때는 flush를 이용하여 내용을 전부 전송해주어야 함

2. FileInputStream & FileOutputStream
    => 파일에 바이트 단위로 기록하고 읽어오는 클래스
    => 파일 경로를 생성자에 입력해서 인스턴스를 생성
    => 생성시 파일의 경로가 없을 수 있어 FileNotFoundException 예외처리가 필요
    => 기록을 하는 클래스의 생성자는 읽기를 하는 클래스의 생성자보다 1개 정도 더 많음
        -> 기록시 전부 지우고 기록 or 이어서 기록 여부 설정(default는 전부 지우고 기록)

3. BufferedInputStream & PrintStream
    => 버퍼를 이용해서 입출력 효율을 높이기 위한 스트림
    => 버퍼를 이용하지 않으면 입출력 메소드를 호출시마다 운영체제의 native method를 호출하여 효율 저하
    => 버퍼를 모아서 한꺼번에 처리하는 방식을 권장
    => 인스턴스 생성시 다른 스트림 인스턴스를 받아 생성

** Character Stream
    => 문자 단위로 데이터를 주고 받는 스트림
    => 파일 전송 등에는 사용할 수 없고 오로지 문자 전송에만 사용하는 스트림
1. Reader
    => 문자 단위 전송에 사용하는 메소드를 소유한 추상 클래스

    => void close()
    => int  read()
    => int  read(char[] buf)
    => int  read(char[] buf, int off, int len)
    => long skip(long n)

2. Writer
    => 문자 단위 쓰기에 사용되는 메소드를 소유한 추상 클래스
    => void close()
    => void write(String str)
    => void write(String str, int off, int len)
    => void flush()

3. FileReader & FileWriter
    => 파일에 문자 단위로 읽고 쓰기 위한 스트림
    => 이 클래스의 인스턴스를 이용해서 읽고 쓰기를 하면 Native Method를 자주 호출해서 입출력 효율 저하

4. BufferReader & PrintWrite
  1) BufferedReader
    => 버퍼를 이용해서 문자 단위로 읽는 클래스(String readLine()메소드가 추가되어 있음)
        - 한줄의 문자열을 읽어서 문자열로 리턴하는 메소드로 읽은 데이터가 없으면 null 리턴
  2) PrintWriter
    => 버퍼를 이용해서 문자 단위로 쓰는 클래스
    => print와 println 메소드가 있음

5. 데이터 표현
  1) 하나의 값 - Scala Data
    => boolean, byte, short, char, int, long, float, double
         String, Data(날짜) : 분할이 가능한 데이터
  2) 하나의 행을 위한 자료형
    => Map (별도의 클래스를 만들고 인스턴스를 생성)
  3) 하나의 열을 위한 자료형
    => Array(배열), ArrayList, LinkedList
  4) 테이블 구조
    => Map 또는 별도 클래스의 Array, ArrayList, LinkedList

** Serializable(직렬화)
    => 데이터를 전송(파일 입출력, 네트워크 입출력) 할때 인스턴스 단위로 전송할 수 있도록 해주는 것 or 인터페이스
    => 데이터는 하나로 묶어서 읽기, 쓰기를 해야하는데 이전까지의 스트림은 바이트나 문자 단위로만 작업
1. ObjectInputStream & ObjectOutputStream
    => Serializable 인터페이스를 implements한 인스턴스를 입출력하기 위한 스트림
  1) ObjectInputStream
    => 인스턴스 단위로 읽어오기 위한 클래스
    => 생성자(ObjectInputStream(), ObjectInputStream(InputStream input) : 다른 InputStream을 매개변수로 받음
         new ObjectInputStream(new FileInputStream(파일경로))
    => 파일경로 : new File("파일경로") "파일경로"
    => 주요 메소드
        - void close() : 스트림을 닫는 메소드(열면 반드시 닫아야 함)
        - Object readObject() : 인스턴스 1개를 읽어서 Object타입으로 리턴
          (사용시 원래 자료형으로 강제 형변환, 데이터는 묶어서 1개로 표현해야 함)
  2) ObjectOutputStream
    => 인스턴스 단위로 기록하기 위한 스트림
    => 생성자(ObjectOutputStream(), ObjectOutputStream(OutputStream out) : 다른 OutputStream을 매개변수로 받음
         new ObjectInputStream(new FileOutputStream(파일 경로, boolean append))
2. Serializable 인터페이스
    => 자바에서 인스턴스 단위로 입출력할 수 있도록 해주는 인터페이스
    => implement 하면 그걸로 끝! 메소드를 구현할 필요 없음
    => 안드로이드에서 Activity 사이의 데이터 전송에도 이 인터페이스가 이용

** log.txt
    => 한줄은 열가지의 데이터를 공백으로 구분하여 가지고 있음
        (첫번째는 접속한 클라이언트의 IP, 열번째는 접속한 클라이언트의 traffic)

** String의 주요 메소드
    => int length() : 문자열의 길이를 리턴
    => char charAt(int idx) : idx 번째에 해당하는 문자 리턴

    => String toUpperCase() : 대문자로 리턴
    => String toLowerCase() : 소문자로 리턴

    => String split(String 구분문자열) : 구분 문자열을 가지고 분할하여 String 배열로 리턴
    
    => String subString(int start) : start부터 끝까지 문자열을 분할하여 리턴
    => String subString(int start, int end) : start부터 end까지 문자열을 분할하여 리턴

    => indexOf(String str) : str을 앞에서부터 찾아서 가장 먼저 찾은 인덱스를 리턴
    => lastIndexOf(String str) : str을 앞에서부터 찾아서 가장 나중에 찾은 인덱스를 리턴

    => String trim() : 좌우 공백을 제거하여 리턴

    => byte getBytes() : 바이트 배열을 리턴

** 문자열을 숫자로 만들기
    => Integer.parseInt(String str), Double.parseDouble(String str)

** 텍스트 파일을 읽어내는 스트림
    => BufferedReader(new InputStreamReader(new FileInputStream(String 파일경로)))
  1) 줄단위로 읽어서 문자열로 리턴하는 메소드 : String readLine()(읽은 데이터가 없으면 null)

 

연습문제
1. log.txt 파일에서 서버에 접속한 IP를 중복없이 출력
2. log.txt 파일에서 서버에 접속한 traffic(줄에서 10번째 데이터)의 합계를 출력
3. log.txt 파일에서 서버에서 접속해서 사용한 traffic의 합계를 ip별로 출력

Tip
파일을 읽고 쓰는 부분, 데이터 베이스를 읽고 쓰는 부분, 네트워크 접속하는 부분은 반드시 예외처리가 필요