ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [자바] 입출력
    자바 2022. 7. 26. 17:17
    728x90

    1. 입출력

    I/O - 입출력
    스트림 - 데이터를 운반하는데 사용되는 연결 통로 ( 단방향, FIFO)

     

    실행중인 프로그램에 입력을 하는 방법

    import java.util.Scanner;
    
    public class ScannerDemo {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int i = sc.nextInt();
            System.out.println(i*1000);
            sc.close();
        }
    }
    
    // 사용자가 계속해서 입력하는 입력값을 사용하는 방법 ( 입력되면 출력하고 입렫되면 출력하는 반복 )
    import java.util.Scanner;
    
    public class ScannerDemo {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            while(sc.hasNextInt()) {
                System.out.println(sc.nextInt()*1000);
            }
            sc.close();
        }
    }
    // while문에서 false가 되는 조건이 올시 종료된다.
    
    // 파일안의 데이터를 입력값으로 넣는 방법
    import java.util.Scanner;
    
    public class ScannerDemo {
        public static void main(String[] args) {
            try {
                 File file = new file("out.txt");
                 Scanner sc = new Scanner(file);
    
                while(sc.hasNextInt()) {
                    System.out.println(sc.nextInt()*1000);
                }
                sc.close();
            } catch(FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
            sc.close();
        }
    }

     

     

    바이트기반 스트림 - InputStream, OutputStream

    바이트단위로 데이터를 전송한다

    입 출력 스트림 종류

    java.io 패키지를 통해서 많은 종류의 입출력관련 클래스들을 제공한다

    읽기, 쓰기 수행하는 메소드

    read, write()는 반드시 구현해야 하는 추상메소드다.

     

    보조 스트림

    실제 데이터를 주고 받는 스트림이 아니기 때문에 데이터룰 입출력할 수 있는 기능은 없지만, 스트림의 기능을 향상시키거나 새로운 기능을 추가할 수 있다
    // 기반스트림 생성
    FileInputStream fis = new FileInputStream(".txt");
    
    // 보조스트림 생성
    BufferedInputStream bis = new BufferedInputStream(fis);
    bis.read(); // 보조스트림인 BufferedInputStream으로부터 데이터를 읽는다

     

    보조스트림 자체로는 아무것도 못한다.

     

    문자기반 스트림 - Reader, Writer

    문자데이터를 입출력할 때는 바이트기반 스트림 대신 문자기반 스트림 사용하기

    InputStream -> Reader
    OutputStream -> Writer

    바이트기반 스트림 vs 문자기반 스트림
    바이트 기반 보조스트림 vs 문자기반 보조스트림

     

    2. 바이트 기반 스트림 

    문자기반 스트림은 byte 대신에 char(2바이트) 배열을 사용한다는 차이점이 있다

    1. InputStream, OutputStream

    스트림을 사용해서 모든 작업을 마치고 난 후에는 close() 을 꼭 호출하기

    하지만, ByteArrayInputStream과 같이 메모리를 사용하는 스트림이나, System.in, System.out 같은 표준 입출력 스트림은 자동적으로 닫히니 닫아주지 않아도 된다

     

    2. ByteArrayInputStream, ByteArrayOutputStream

    메모리, 즉 바이트배열에 데이터를 입출력 하는데 사용되는 스트림이다.

    다른 곳에 입출력하기 전에 데이터를 임시로 바이트배열에 담아서 변환 등의 작업을 하는데 사용된다

     

    스트림의 종류가 달라도 읽고 쓰는 방법은 동일하다

    byte[] inSrc = {0,1,2,3,4};
    byte[] outSrc = null;
    
    ByteArrayInputStream input = null;
    ByteArrayInputStream output = null;
    
    input = new ByteArrayInputStream(inSrc);
    output = new ByteArrayInputStream();
    
    int data = 0;
    
    // first way
    while((data = input.read()) != -1 ) {
        output.write(data);
    }
    // data = input.read() -> read()를 호출한 반환값을 변수 data에 저장
    // data != -1-> data에 저장된 값이 -1이 아닌지 비교
    
    // upgrade 1 way -> 배열을 이용한 이불력은 작업의 효율을 증가시키므로 입출력 대상에 따라 알맞는 크기의 배열 사용하기
    input.read(temp, 0, temp.length); // 읽어온 데이터를 배열 temp에 담는다
    output.write(temp,5,5); // temp[5]부터 5개의 데이터를 write한다
    
    // upgrade again 1 way
    // read(), write()는 IOException을 발생시킬 수 있기에 try-catch를 사용한다
    // available()은 블락킹 없이 읽어 올 수 있는 바이트의 수를 반환한다
    try {
        while(input.available() > 0 ) {
            int len = input.read(temp); // 읽어 온 데이터 개수 반환
            output.write(temp, 0 , len); // 읽어온만큼만 write
        }
    } catch(IOException e) {}
    
    outSrc = output.toByteArray(); // 스트림의 내용을 byte배열로 반환한다.

     

    3. FileInputStream, FileOutputStream

    파일에 입출력을 하기 위한 스트림이다.

    텍스트 파일을 다루는 경우에는 FileReader/FileWriter 을 쓰는 것이 좋다

     

    2. 바이트 기반의 보조스트림

    1. FilterInputStream, FilterOutputStream

    InputStream/OutputStream 의 자손이면서 모든 보조스트림의 조상이다.
    Protected FilterInputStream(InputStream in)
    public FilterOutputStream(OutputStream out)

    상속을 통해 원하는 작업을 수행하도록 읽고 쓰는 메소드를 오버라이딩을 해야한다.

     

    protected 이기 떄문에 인스턴스 생성해 사용하지 못하므로, 상속을 통해 오버라이딩 해야한다

     

    2. BufferedInputStream, BufferedOutputStream

    스트림의 입출력 효율을 높이기 위헤 버퍼를 사용한 보조스트림이다

     

    BufferedInputStream

    - 버퍼크기는 입력소스로부터 한번에 가져올 수 있는 데이터의 크기로 지정하기

    ( 버퍼를 사용해 한번에 여러 바이트를 입출력하는 것이 효율적이므로 )

    - 자신의 내부 버퍼에 저장

    - 외부의 입력소스로 부터 읽는 것보다는 내부의 버퍼로 읽는것이 훨씬 효율적

     

    BufferedOutputStream

    - write 메서드로  BufferedOutputStream 버퍼에 저장된다

    - 버퍼가 가득 차면, 그때 버퍼의 모든 내용을 출력소스에 출력

    - 버퍼가 가득 찼을때만 출력을 하기에 마지막 출력부분이 BufferedOutputStream 버퍼에 남아있는 채로 프로그램 종료될 수 있음을 주의 ( BufferedOutputStream의 close()를 호출해서 남아 있는 모든 내용 출력하기 )

     

    보조 스트림을 사용하는 경우에는 기반스트림에 close() 호출할 필요 없이 보조스트림의 close()를 호출하기만 허면 된다

     

    3. DataInputStream, DataOutputStream

    DataInput 인터페이스, DataOutput 인터페이스 를 구현하여, byte단위가 아닌 8가지 기본 자료형의 단위를 읽고 쓸수있다.

    출력한 데이터를 다시 읽어 올 때는 출력했을때의 순서를 염두하기

     

    try {
        FileInputStream fis = new FileInputStream(".txt");
        DataInputStream dis = new DataInputStream(fis);
        
        System.out.println(dis.readInt());
        System.out.println(dis.readFloat());
        System.out.println(dis.readBoolean());
        dis.close();
    }catch( IOException e ) {
        e.printStackTrace();
    }

    readInt() 와 같이 읽어 올 데이터의 타입에 맞는 메서드를 사용하기만 하면 된다.

    readInt()는 IOException가 가능하기에 try-catch문 써주기

     

    while문에서 작업하면 finally 블럭에서 스트림 닫기

     

    4. SequenceInputStream

    여러 개의 입력스트림을 연속적으로 연결해서 하나의 스트림으로부터 데이터를 읽는 것과 같이 처리할 수 있도록 도와주기 
    큰 파일을 여러개의 작을 파일로 나누었다가 하나의 파일로 합치는 작업수행시 좋다
    사용방법 1
    Vector files = bew Vector();
    files.add(new FileInputStream("file.001"));
    files.add(new FileInputStream("file.002"));
    SequenceInputStream in = new SequenceInputStream(files.elements());
    
    사용방법 2
    FileInputStream file1 = new FileInputStream("file.001");
    FileInputStream file2 = new FileInputStream("file.002");
    SequenceInputStream in = new SequenceInputStream(file1, file2);

    Vector에 저장된 순서대로 입력되므로 순서에 주의하기

     

    5. PrintStream

    PrintStream 보다 PrintWriter이 더 좋으니까 이거 쓰기

    print, println, printf 와 같은 메서드를 오버로딩하여 제공

     

    printf에서 사용될 수 있는 옵션은 JAVA API문서 - Formatter클래스 참고하기

    정수 출력애 서용 가능한 옵션

    4. 문자 기반 스트림 

    1. PipedReader , PipedWriter

    쓰레드 간에 데이터를 주고받을 때 사용된다. 하나의 스트림으로 연결해서 데이터를 주고 받는다

    한쪽 스레드에서 connect()를 호출해서 입력스트림과 출력스트림을 연결한다.

    입출력을 마친 후에는 어느 한쪽 스트림만 닫아도 나머지 스트림은 자동으로 닫힌다.

     

    2. StringReader , StringWriter

    입출력 대상이 메모리인 스트림이다. 
    StringWriter에 출력되는 데이터는 내부의 StringBuffer에 저장된다
    StringBuffer getBuffer() - StringWriter에 출력한 데이터가 저장된 StringBuffer를 반환한다
    String toString() - StringWriter에 출력된 (StringBuffer에 저장된 ) 문자열을 반환한다

     

    4. 문자 기반 보조스트림 

    1. BufferedReader, BufferedWriter

    버퍼를 이용해 입출력의 효율을 높일 수 있도록 해주는 역할을 한다
    readLine() - 사용하는 데이터를 라인단위로 읽을 수 있다.
    newLine() - 줄바꿈해준다

     

    2. InputStreamReader, OutputStreamWriter

    바이트기반 스트림을 문자기반 스트림으로 연결시켜주는 역할 ( 바이트 기반 스트림의 데이터를 지정된 인코딩의 문자데이터로 변환 )

     

    5. 표준 입출력과 File

    1. 표준 입출력

    System.in - 콘솔로부터 데이터를 입력받는데 사용
    System.out - 콘솔로 데이터를 출력하는데 사용
    System.err - 콘솔로 데이터를 출력하는데 사용

    표준 입출력

    in, out, err는 System클래스에 선언된 클래스변수(static변수) 이지만, 버퍼를 이용하는 BufferedInputStream, BufferedOutputStream의 인스턴스를 사용한다

     

    2. RandomAccessFile

    자바에서는 입,출력이 각각 별도로 작업을 하는데 RandomeAccessFile에서만 파일에 대한 입출력 모두가 가능하다

    randomAccessFile 상속계층도

    3. file

    - 이미 있는 파일 참조
    File f = new File("경로");

    - 새로운 파일 생성
    File f = new File("경로");
    f.createNewFile()

     

    6. 직렬화

    직렬화 - 객체를 데이터 스트림으로 만드는것을 의미한다
    객체에 저장된 데이터를 스트림에 쓰기 위해 연속적인 데이터로 변화 
    역직렬화 - 스트림으로 부터 데이터를 읽어서 객체를 만드는 것

    객체의 직렬, 역직렬화

     

    객체 - 클래스에 정의된 인스턴스변수의 집합. 객체에는 클래스변수나 메서드가 포함되지 않는다. 객체는 오직 인스턴스변수들로만 구성되어 있다 ( 메서드는 포함이 아니다!! )

    객체를 저장한다 = 객체의 모든 인스턴스 변수의 값을 저장한다

     

    1. ObjectInputStream, ObjectOutputStream

    직렬화 ( 스트림에 객체를 출력 ) ObjectOutputStream 사용
    역직렬화 ( 스트림으로 부터 객체를 입력 ) ObjectInputStream 사용

     

    보조스트림으로 스트림을 지정해줘야한다

    ObjectInputStream(InputStream in)
    ObjectOutputStream(OutputStream out)

     

    파일에 객체를 저장(직렬화)하고 싶다면 하는 방법

    FileOutputStream fos = new FileOutputStream(".txt");
    ObjectOutputStream out = new ObjectOutputStream(fos);
    
    out.writeObject(new UserInfo());

     

    ObjectOutputStream의 writeObject(Object obj)를 사용해서 객체를 출력하면, 객체가 파일에 직렬화되어 저장된다

    역직렬화는 직렬화와 달리 입력스트림을 사용하고 writeObject(Object obj) 대신에 readObject()를 사용해서 저장된 데이터를 읽기만 하면 객체로 역직렬화가 된다 ( writeObject는 반환타입이 Object이기에 객체 원래의 타입으로 형변환 필수 )

     

    2. 직렬화가 가능한 클래스 만들기 - Serializable, transient

    직렬화가 가능한 클래스를 만드는 방법은 java.io.Serializable 인터페이스를 구현하도록 하면 된다
    public class UserInfo {
        String name;
        String password;
        int age;
    }
    
    public class UserInfo {
        implements java.io.Serializable {
            String name;
            String password;
            int age; 
        }
    }

     

    Serializable을 구현한 클래스를 상속받는다면, Serializable을 구현하지  않아도 된다

    public class SuperUserInfo implements Serializable {
        String name;
        String password;
    }
    
    public class UserInfo extends SuperUserInfo {
        int age;
    }

     

    클래스의 최고조상인 Object는 Serializable을 구현하지 않았기 때문에 직렬화 불가능하다.

    만일 Object가 Serializable을 구현했다면 모든 클래스가 직렬화 가능 

     

    보안상 직렬화되면 안되는 값 혹은 직렬화 대상에서 제외해야 하는 경우가 있다.

    그때는 제어자 transient 를 붙인다

     

    직렬화가 안되게끔하고 역직렬화를 하면 값은 null이 된다.

     

    또한 역직렬화를 할때는 직렬화할때의 순서와 일치해야 한다.

    따라서 직렬화는 개별적으로 하는 것보다는 ArrayList와 같은 컬렉션에 저장해서 직렬화 하는 것이 좋다.

    '자바' 카테고리의 다른 글

    [자바] 클래스 멤버와 인스턴스 멤버  (0) 2022.08.04
    [자바] 메소드  (0) 2022.08.04
    [자바] 스트림  (0) 2022.07.25
    [자바] 람다  (0) 2022.07.25
    [자바] 쓰레드  (0) 2022.07.23
Designed by Tistory.