0

I wrote up this class based on some examples I found online for Data Streams and I'm getting an EOFException at the end of each run. When I looked it up it said the end of the stream had been reached unexpectedly. It does appear to work on the console (at least it spits out the correct sequence of numbers). The text file is just gibberish though when I inspect the contents after running.

public class DataStreamExample {

    public static void main(String args[]) {
        int choice = 0;
        int[] numbers = { 25, 4, 19, 70, 12, 28, 39, 30 };

        System.out.println("This program will provide an example on how the Data Stream works.");
        System.out.println("Note: Data Streams only work with primative data types.");
        System.out.println();
        System.out.println();


        try {
            System.out.println("1. For write Data operation");
            System.out.println("2. For read Data operation");  
            System.out.println("Enter the number for the operation of your choice: ");

            BufferedReader buffRead = new BufferedReader(new InputStreamReader(System.in));
            choice = Integer.parseInt(buffRead.readLine());
            switch(choice){
                case 1:  
                    FileOutputStream fileOut = new FileOutputStream("Example.txt");
                    BufferedOutputStream buffOut = new BufferedOutputStream(fileOut);
                    DataOutputStream dOutput =new DataOutputStream (buffOut);
                    for (int i = 0; i < numbers.length; i ++) {
                        dOutput.writeInt(numbers[i]);
                    }
                    System.out.print("writing data ");  
                    dOutput.close();

                case 2:
                    FileInputStream fileIn = new FileInputStream("Example.txt");
                    BufferedInputStream buffIn = new BufferedInputStream(fileIn);
                    DataInputStream dInput = new DataInputStream (buffIn);
                    while (true){
                        System.out.print(dInput.readInt());
                    }

                default:
                    System.out.println("Invalid choice");  
            }
        } 
        catch (Exception e) {
            System.err.println("Error in read/write data to a file: " + e);
        }

    }
}

Does anyone have any advice or observations that can help clean this up so I don't get gibberish in the file and so it doesn't catch the exception? How should I be ending the operation and closing the stream?

Jon Lin
  • 142,182
  • 29
  • 220
  • 220
user1588867
  • 67
  • 1
  • 3
  • 8

3 Answers3

1

For your input operation, you are reading forever while(true), so the only way that loop will complete is by throwing EOFException. if you don't want the operation to complete that way, you will have to know how many ints you are reading before you start (and use that to limit the loop).

the reason the file looks like gibberish is because you are writing the values as binary. if you want to read the ints in the file, you would have to write them as text.

also, you should put break; statements at the end of each case.

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • Would you recommend a count at the beginning of the case or would it be better to put it before the input entirely when the array is assigned? – user1588867 Jan 22 '13 at 05:08
0

Some things:

  1. When you enter 1 to "write Data operation", you don't have a break; in your case statement, thus when you try to write the data, the integers gets written into the file, then the second case gets executed and you try to read from it. Not sure if this is your intention. But you can add a break to keep that from happening:

            case 1:  
                FileOutputStream fileOut = new FileOutputStream("Example.txt");
                BufferedOutputStream buffOut = new BufferedOutputStream(fileOut);
                DataOutputStream dOutput =new DataOutputStream (buffOut);
                for (int i = 0; i < numbers.length; i ++) {
                    dOutput.writeInt(numbers[i]);
                }
                System.out.print("writing data ");  
                dOutput.close();
                break;
    
  2. When you try to read from your data file, you loop indefinitely:

                while (true){
                    System.out.print(dInput.readInt());
                }
    

    That means it'll keep attempting to read serialized integers until the end of the file is reached. And when the end of the file has been reached, the stream throws an EOFException`. You can try changing your loop to this to prevent the exception:

                while (dInput.available()>0){
                   System.out.print(dInput.readInt());
                }
                break;
    
  3. When you print the integers, they're going to be all jumbled up.

  4. The text file is gibberish because it's not text. When you use a DataOutputStream the objects (or primitives) that you write into the stream gets processed so that the data is portable.

Jon Lin
  • 142,182
  • 29
  • 220
  • 220
  • 1
    InputStream.available() is a terrible method which should never be used. – jtahlborn Jan 22 '13 at 04:43
  • @Jon Lin Thanks this is really helpful. I wound up putting a print statement in the loop to indicate the numbers being written to the file and it works great. (That is, in addition to your recommendations) – user1588867 Jan 22 '13 at 05:07
  • Specifically, available() > 0 is *entirely incorrect* as a test for EOS, as it says in the Javadoc. – user207421 Jan 22 '13 at 06:04
0

Well, instead of using

while (true){
    System.out.print(dInput.readInt());
 }

you should use

while(dInput.available()>0){
    System.out.print(dInput.readInt());
}

Because when you use while(true), it's alway read from Stream, include when stream reach EOF (End Of File)
After all, you should close all your stream using close() method

Cong Nguyen
  • 168
  • 1
  • 8
  • 1
    InputStream.available() is a terrible method which should never be used. – jtahlborn Jan 22 '13 at 04:43
  • @jtahlborn could you explain in more detail? – Cong Nguyen Jan 22 '13 at 04:48
  • 1
    it's unreliable at best. e.g. i believe the `available()` method for GZIPInputStream returns 1 until the stream is closed, then returns 0. ultimately, there is really never a good reason to use the method. – jtahlborn Jan 22 '13 at 04:56
  • If you use available() method to calculate exactly the number of bytes remaining, you are correct. But the method is used to "estimate" of the number of bytes remaining, not for exactly how many bytes remaining. So I think there's no reason why i shouldn't use the method – Cong Nguyen Jan 22 '13 at 05:15
  • 1
    No. available() *does not return* the number of bytes available, *or* an estimate. It can return zero when there remain gigabytes to be read. It has nothing to do with the EOS condition whatsoever. See the Javadoc. -1 – user207421 Jan 22 '13 at 06:05