카테고리 없음

[TIL] 2022년 9월 20일 화요일

2022. 9. 20. 09:18

3.3 DataInputStream과 DataOutputStream

- DataInputStream과 DataOutputStream은 각각 FilterInputStream, FilterOutputStream의 자식 클래스이자 DataInput, DataOutput 인터페이스를 구현

- DataInput과 DataOutput을 구현한 덕분에 이진 스트림에서 바이트를 읽고 이를 Java의 기본자료형으로, Java 기본 자료형에서 이진 스트림의 바이트로 재구성할 수 있음

자료형 메소드 설명
int read​(byte[] b) Reads some number of bytes from the contained input stream and stores them into the buffer array b.
int read​(byte[] b, int off, int len) Reads up to len bytes of data from the contained input stream into an array of bytes.
boolean readBoolean() See the general contract of the readBoolean method of DataInput.
byte readByte() See the general contract of the readByte method of DataInput.
char readChar() See the general contract of the readByte method of DataInput.
double readDouble() See the general contract of the readChar method of DataInput.
float readFloat() See the general contract of the readFloat method of DataInput.
void readFully(byte[] b) See the general contract of the readFully method of DataInput.
void readFully(byte[] b, int off, int len) See the general contract of the readFully method of DataInput.
int readInt() See the general contract of the readInt method of DataInput.
String readLIne() Deprecated.
This method does not properly convert bytes to characters.
long readLong() See the general contract of the readLongmethod of DataInput.
short readShort() See the general contract of the readShortmethod of DataInput.
int readUnsignedByte() See the general contract of the readUnsignedByte method of DataInput
int readUnsignedShort() See the general contract of the readUnsignedShort method of DataInput.
String readUTF() See the general contract of the readUTF method of DataInput.
static String readUTF(DataInput in) Reads from the stream in a representation of a Unicode character string encoded in modified UTF-8 format; this string of characters is then returned as a String.
int skipBytes(int n) See the general contract of the skipBytesmethod of DataInput.

위 메소드 중 read 가 들어가는 메소드는 읽을 값이 없으면 EOFException이 발생한다. NPE처럼 줄여서 부르는 예외이름인 줄 알았는데 찾아보니 EOFException이란 말을 그대로 쓴다. End Of File, End Of Stream의 약자인 듯 하다. 입력받는 중에 기대와 다르게 파일이나 스트림의 끝에 도달했을 때 발생하는 오류이다. 사용할 때 예외처리하기보다 스트림의 끝에 특별한 값을 반환한다고 한다.

자료형 메소드 설명
void flush() Flushes this data output stream.
int size() Returns the current value of the counter written, the number of bytes written to this data output stream so far.
void write(byte[] b, int off, int len) Writes len bytes from the specified byte array starting at offset off to the underlying output stream.
void write(int b) Writes the specified byte (the low eight bits of the argument b) to the underlying output stream.
void writeBoolean(boolean v) Writes a boolean to the underlying output stream as a 1-byte value.
void writeByte(int v) Writes out a byte to the underlying output stream as a 1-byte value.
void writeBytes(String s) Writes out the string to the underlying output stream as a sequence of bytes.
void writeChar(int v) Writes a char to the underlying output stream as a 2-byte value, high byte first.
void writeChars(String s) Writes a string to the underlying output stream as a sequence of characters.
void writeDouble(double v) Converts the double argument to a long using thedoubleToLongBits method in class Double, and then writes that long value to the underlying output stream as an 8-byte quantity, high byte first.
void writeFloat(float v) Converts the float argument to an int using thefloatToIntBits method in class Float, and then writes that int value to the underlying output stream as a 4-byte quantity, high byte first.
void writeInt(int v) Writes an int to the underlying output stream as four bytes, high byte first.
void writeLong(long v) Writes a long to the underlying output stream as eight bytes, high byte first.
void writeShort(int v) Writes a short to the underlying output stream as two bytes, high byte first.
void writeUTF(String str) Writes a string to the underlying output stream usingmodified UTF-8 encoding in a machine-independent manner.
더보기
import java.io.*;
import java.util.Arrays;

public class DataOutputStreamEx {
    public static void main(String[] args) {
        ByteArrayOutputStream bos = null;
        DataOutputStream dos = null;
        byte[] result = null;

        try {
            bos = new ByteArrayOutputStream();
            dos = new DataOutputStream(bos);
            dos.write(10);
            dos.writeFloat(20.0f);
            dos.writeBoolean(true);

            result = bos.toByteArray();
            String[] hex = new String[result.length];

            for(int i=0; i< result.length; i++){
                if(result[i]<0)
                    hex[i] = String.format("%02x", result[i] + 256);
                else
                    hex[i] = String.format("%02x", result[i]);
            }

            System.out.println("10진수 : " + Arrays.toString(result));
            System.out.println("16진수 : " + Arrays.toString(hex));

            dos.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

교재 속 예제 15-9를 실행해봤는데 책과 결과가 달랐다. 책은 [0, 0, 0, 10, 65, -06, 0, 0, 1] /n [00, 00, 00, 0a, 41, a0, 00, 00, 01]이었다. 첫 줄부터 하나씩 비교하다보니 writeInt()라고 썼어야 했는데 write()라고만 썼다. 이 부분을 고치니 바로 해결할 수 있었다. 책을 보니 int와 float이 4byte라 ByteArrayOutputStream에 네 개의 공간을 차지한 듯 하다. 하지만 write()을 할 땐 10이 byte범위인 -128~127사이에 있어서 1byte만 차지한 것 같다. 궁금해서 write()메소드로 127을 출력해보니 127 그대로 출력하고 그 다음 128은 -128로 출력한다. 256은 0, 257은 1, 258은 2가 나왔다. write()로는 부호가 있는 byte범위의 정수만 입력할 수 있다.

 

더보기
import java.io.*;

public class DataOutputStreamEx2 {
    public static void main(String[] args) {
        int sum = 0;
        int score = 0;

        FileInputStream fis = null;
        DataInputStream dis = null;

        try {
            fis = new FileInputStream("score.dat");
            dis = new DataInputStream(fis);

            while (true){
                score = dis.readInt();
                System.out.println(score);
                sum += score;
            }
        }catch (EOFException ee){
            System.out.printf("점수의 총합은 %d입니다.\n", sum);
        }catch (IOException ie){
            ie.printStackTrace();
        }finally {
            try {
                if(dis != null)
                    dis.close();
            }catch (IOException ie){
                ie.printStackTrace();
            }
        }
    }
}
import java.io.*;

public class DataOutputStreamEx2 {
    public static void main(String[] args) {
        int sum = 0;
        int score = 0;
        
        try (FileInputStream fis = new FileInputStream("score.dat");
             DataInputStream dis = new DataInputStream(fis)) {

            while (true){
                score = dis.readInt();
                System.out.println(score);
                sum += score;
            }
        }catch (EOFException ee){
            System.out.printf("점수의 총합은 %d입니다.\n", sum);
        }catch (IOException ie){
            ie.printStackTrace();
        }
    }
}

코드를 보다가 try - with - resource을 복습했다.