2

I have this Java code:

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class DemoApp {

    public static void main(String args[]) {

        try (DataInputStream dis = new DataInputStream(new FileInputStream("abc.txt"))) {

            int k = dis.readInt();
            System.out.println(k);
        }

        catch (FileNotFoundException fnfe) {

            System.out.printf("ERROR: %s", fnfe); 
        }

        catch (IOException ioe) {

            System.out.printf("ERROR: %s", ioe);
        }
    }

}

When the abc.txt file contains the number 987 I have this ERROR: java.io.EOFException if the abc.txt contains the number 1234 when I run the program I have this result: 825373492. I just want to understand how exactly is working this readInt() method from DataInputStream and why I have this error for some numbers. Thank you!

elvis
  • 956
  • 9
  • 33
  • 56

2 Answers2

2

DataInputStream is designed to read bytes from a binary stream (bytes) and your text file contains a textual representation of a integer value.
So it cannot work.

You can find the information in the DataInputStream.readInt() javadoc :

See the general contract of the readInt method of DataInput.

Where DataInput().readInt() states

The DataInput interface provides for reading bytes from a binary stream and reconstructing from them data in any of the Java primitive types. ...

The value returned is:

(((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff))

987 is read as 57, 56, 55 bytes. It misses a byte to be an int as int are represented on 4 bytes.
Whereas The EOFException thrown during readInt() invocation as this input stream reached the end before reading four bytes.
By adding an additional digit in your text file, you have 4 bytes to read. So it "works" : the 4 bytes can be read but 1234 is read as 49, 50, 51, 52 bytes that produces the 825373492 int according to the DataInput.readInt() specification.

To read int value from a text file you can use a Scanner such as :

try (Scanner sc = new Scanner(new File("abc.txt"))) {
        int i = sc.nextInt();
        System.out.println(i);
}
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • Thank you for your reply. I know there are other methods to read from a text file, but I want to understand this DataInputStream because I know it is a way of serialization for primitive data types, and I'm trying to lean about serialization – elvis Apr 09 '18 at 16:54
  • You are welcome. I understand your point but `DataxxxStream` are data stream or more simply bytes stream while your file represents numbers in textual form. So stream designed to read text (Scanner or BufferedReader for example) match much better. – davidxxx Apr 09 '18 at 18:45
1

abc.txt contains the characters 1234, whose ASCII representations are the hexadecimal numbers 0x31, 0x32, 0x33 and 0x34. If you write those out you will notice that the hexadecimal number 0x31323334 has the decimal value 825373492.

The solution is to read a byte at a time (not an Integer at a time), and subtract 0x30 from the byte to find the digit it represents. For each digit, you have to shift the previous result left by a factor of ten (to move tens to hundreds, and so on) and then add the current digit to it, for each byte you read from the file.

Alternatively, read the characters as a String, and pass it to the Integer.parseInt method, which will do the fiddly character-to-digit conversion for you. To read the characters as a String, you may want to use BufferedReader d = new BufferedReader(new InputStreamReader(in)).

Or a Scanner, as davidxxx suggests.

Breandán Dalton
  • 1,619
  • 15
  • 24