BACK/JAVA

[JAVA] byte단위 입출력- InputStream/OutputStream

연듀 2022. 10. 23. 17:18

 

 

자바의 입출력은 크게 byte 단위의 입출력과 char 단위의 입출력으로 나눌 수 있다.

우선 byte단위의 입출력인 InputStream과 OutputStream 추상클래스에 대해 포스팅하고 다음 포스팅에서 char 단위의 입출력을 포스팅한다.

 

InputStream

 

입력으로 InputStream 추상 클래스가 사용된다.

InputStream을 상속해 추상 메서드를 구현한 자식 클래스에는 FileInputStream, BufferedInputStream, DataInputStream이 있다.

 

 

FileInputStream으로 InputStream 객체 생성하기

// 입력 파일 생성
File inFile = new File("src/files/FileInput-Stream1.txt");

// FileInputStream으로 InputStream 객체 생성
InputStream is = new FileInputStream(inFile);
int data;
while((data = is.read())!= -1){
    System.out.println("읽은 데이터: "+(char)data + " 남은 바이트 수: " + is.available());
}
// InputStream 자원 반납
is.close();
읽은 데이터: h남은 바이트 수: 4
읽은 데이터: e남은 바이트 수: 3
읽은 데이터: l남은 바이트 수: 2
읽은 데이터: l남은 바이트 수: 1
읽은 데이터: o남은 바이트 수: 0

 

FileInputStream의 read() 메서드를 이용해 데이터 읽기

import java.io.*;

public class Main{
    public static void main(String[] args) throws IOException {
        // 입력 파일 생성
        File inFile = new File("src/files/FileInput-Stream1.txt");
        // FileInputStream으로 InputStream 객체 생성
        InputStream is1 = new FileInputStream(inFile);

        byte[] byteArray1 = new byte[9];
        int count1;

        // 1-byte 단위 읽기
        while((count1 = is1.read(byteArray1))!= -1){
            for(int i=0; i<count1; i++){
                System.out.print((char)byteArray1[i]);
            }
            System.out.println(": count1 = "+count1);
        }
        is1.close();
        System.out.println();

        // n-byte 단위 읽기
        InputStream is2 = new FileInputStream(inFile);
        byte[] byteArray2 = new byte[9]; // 최소 offset + length
        int offset = 3;
        int length = 6;
        int count2 = is2.read(byteArray2, offset, length); // 앞에서 length만큼 읽어 byte[] offset 위치에서부터 입력
        for(int i=0; i<offset+count2; i++){
            System.out.print((char)byteArray2[i]);
        }
        is2.close();
    }
}
FileInput: count1 = 9
Stream Te: count1 = 9
st: count1 = 2

   FileIn

 

 

콘솔로 InputStream 사용하기

import java.io.IOException;
import java.io.InputStream;

public class Main{
    public static void main(String[] args) throws IOException {
        InputStream is = System.in;
        int data;
        while((data=is.read())!='r'){
            System.out.println((char)data);
        }
        System.out.println(data);
        System.out.println(is.read()); // 버퍼를 비워주기 위해 입력 버퍼에 남아 있는 '\n\을 read() 메서드를 이용해 꺼냄
    }
}

 

 

콘솔로 입력을 하는데는 InputStream 타입의 System.in 객체를 이용한다. 

 

 

 

 

 


 

OutputStream

 

출력으로는 OutStream추상 클래스가 사용된다.

OutputStream을 상속해 추상 메서드를 구현한 자식 클래스에는 FileOutputStream, BufferedOutputStream, DataOutputStream, PrintStream이 있다.

 

 

FileOutputStream의 write() 메서드를 이용한 데이터 쓰기

import java.io.*;

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

        // 입력 파일 생성
        File outFile = new File("src/files/FileOutputStream1.txt");

        OutputStream os1 = new FileOutputStream(outFile); // FileOutputStream으로 OutputStream 객체 생성하기

        // 1-byte 단위쓰기
        os1.write('J');
        os1.write('A');
        os1.write('V');
        os1.write('A');
        os1.write('\r'); // 윈도우 콘솔에서 엔터를 입력하면 2byte(\r\n)가 입력됨
        os1.write('\n');
        // FileOutputStream 객체는 내부적으로 메모리 버퍼를 사용하지 않아 flush() 생략 가능
        os1.flush(); // 실제 출력
        os1.close(); // FileOutputStream의 자원 반납

        // n-byte 단위 쓰기
        OutputStream os2 = new FileOutputStream(outFile, true); // true면 내용 이어쓰기
        byte[] byteArray = "Better the last smile than the first laughter".getBytes();
        os2.write(byteArray, 7, 8); // 첫번째 매개변수만 있을 경우 처음부터 끝까지 데이터 쓰기
        os2.write('\n');
        os2.flush();
        os2.close();
    }
}
JAVA
the last

 

 

콘솔로 OutputStream사용하기

import java.io.*;

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

        OutputStream os1 = System.out;

        // 1-byte 단위쓰기
        os1.write('J');
        os1.write('A');
        os1.write('V');
        os1.write('A');
        os1.write('\r'); // 윈도우 콘솔에서 엔터를 입력하면 2byte(\r\n)가 입력됨
        os1.write('\n');
        // FileOutputStream 객체는 내부적으로 메모리 버퍼를 사용하지 않아 flush() 생략 가능
        os1.flush(); // 실제 출력

        // n-byte 단위 쓰기

        byte[] byteArray = "Better the last smile than the first laughter".getBytes();
        os1.write(byteArray, 7, 8); // 첫번째 매개변수만 있을 경우 처음부터 끝까지 데이터 쓰기
        os1.flush();
    }
}

 

 

 

BufferedInputStream / BufferedOutputStream

 

 

BufferedInputStream과 BufferedOutputStream은 입출력 과정에서 메모리 버퍼를 사용해 속도를 향상시키는 클래스다.

쓰고자하는 데이터를 메모리 버퍼에 기록하고, 한 번씩 모아 파일에 쓴다.

 

 

import java.io.*;
import java.nio.charset.Charset;

public class Main {
    public static void main(String[] args) throws IOException {
        File file = new File("src/files/mycat.jpg");
        File copyfile = new File("src/files/mycat_copy.jpg");

        // 스트림 객체 생성 
        try (InputStream is = new FileInputStream(file);
             BufferedInputStream bis = new BufferedInputStream(is);
             OutputStream os = new FileOutputStream(copyfile);
             BufferedOutputStream bos = new BufferedOutputStream(os);
        ) {
            int data;
            // 파일을 byte 단위로 읽고, 읽은 데이터를 새로운 파일에 저장 
            while ((data = bis.read()) != -1) {
                bos.write(data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

 

 

 

DataInputStream / DataOutputStream

 

InputStream과 OutputStream만으로는 데이터를 오직 byte단위로만 입출력 할 수 있다. 

DataInputStream과  DataOutputStream은 다양한 데이터타입으로 입출력을 지원하는 클래스이다.

import java.io.*;

public class Main{
    public static void main(String[] args) throws IOException {
        File dataFile = new File("src/files/file1.data");

        try(OutputStream os = new FileOutputStream(dataFile);
            BufferedOutputStream bos = new BufferedOutputStream(os);
            DataOutputStream dos = new DataOutputStream(bos);){
            dos.writeInt(12);
            dos.writeDouble(5.3);
            dos.writeChar('A');
            dos.writeUTF("안녕");
            dos.flush();
        }
        try(InputStream is = new FileInputStream(dataFile);
            BufferedInputStream bis = new BufferedInputStream(is);
            DataInputStream dis = new DataInputStream(bis);){
            System.out.println(dis.readInt()); // 12
            System.out.println(dis.readDouble()); // 5.3
            System.out.println(dis.readChar()); // A
            System.out.println(dis.readUTF()); // 안녕
        }
    }
}

 

 

 

 

PrintStream

 

PrintStream은 다양한 타입의 출력에 특화된 클래스로, 자동 flush()기능을 제공한다.

우리가 늘 사용하는 System.out의 객체 타입이 바로 PrintStream이다. 

즉 System.out.println()은 PrintStream 클래스의 인스턴스 메서드인 println()을 호출하는 것이다. 

 

 

import java.io.*;

public class Main{
    public static void main(String[] args) throws IOException {
        File outFile = new File("src/files/Print-Stream1.txt");

        // PrintStream(File)
        try(PrintStream ps = new PrintStream(outFile);){
            ps.println(4.5);
            ps.print(3+" 안녕 "+1234+"\n");
            ps.println();
        }catch(IOException e){}

        // PrintStream ps = System.out
        try(OutputStream os = System.out;
        PrintStream ps = new PrintStream(os)){
            ps.println(4.5);
            ps.print(3+" 안녕 "+1234+"\n");
            ps.println();
        }
    }
}