EOFException - how to handle? - java

I'm a beginner java programmer following the java tutorials.
I am using a simple Java Program from the Java tutorials's Data Streams Page, and at runtime, it keeps on showing EOFException. I was wondering if this was normal, as the reader has to come to the end of the file eventually.
import java.io.*;
public class DataStreams {
static final String dataFile = "F://Java//DataStreams//invoicedata.txt";
static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 };
static final int[] units = { 12, 8, 13, 29, 50 };
static final String[] descs = {
"Java T-shirt",
"Java Mug",
"Duke Juggling Dolls",
"Java Pin",
"Java Key Chain"
};
public static void main(String args[]) {
try {
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile)));
for (int i = 0; i < prices.length; i ++) {
out.writeDouble(prices[i]);
out.writeInt(units[i]);
out.writeUTF(descs[i]);
}
out.close();
} catch(IOException e){
e.printStackTrace(); // used to be System.err.println();
}
double price;
int unit;
String desc;
double total = 0.0;
try {
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(dataFile)));
while (true) {
price = in.readDouble();
unit = in.readInt();
desc = in.readUTF();
System.out.format("You ordered %d" + " units of %s at $%.2f%n",
unit, desc, price);
total += unit * price;
}
} catch(IOException e) {
e.printStackTrace();
}
System.out.format("Your total is %f.%n" , total);
}
}
It compiles fine, but the output is:
You ordered 12 units of Java T-shirt at $19.99
You ordered 8 units of Java Mug at $9.99
You ordered 13 units of Duke Juggling Dolls at $15.99
You ordered 29 units of Java Pin at $3.99
You ordered 50 units of Java Key Chain at $4.99
java.io.EOFException
at java.io.DataInputStream.readFully(Unknown Source)
at java.io.DataInputStream.readLong(Unknown Source)
at java.io.DataInputStream.readDouble(Unknown Source)
at DataStreams.main(DataStreams.java:39)
Your total is 892.880000.
From the Java tutorials's Data Streams Page, it says:
Notice that DataStreams detects an end-of-file condition by catching EOFException, instead of testing for an invalid return value. All implementations of DataInput methods use EOFException instead of return values.
So, does this mean that catching EOFException is normal, so just catching it and not handling it is fine, meaning that the end of file is reached?
If it means I should handle it, please advise me on how to do it.
EDIT
From the suggestions, I've fixed it by using in.available() > 0 for the while loop condition.
Or, I could do nothing to handle the exception, because it's fine.

While reading from the file, your are not terminating your loop. So its read all the values and correctly throws EOFException on the next iteration of the read at line below:
price = in.readDouble();
If you read the documentation, it says:
Throws:
EOFException - if this input stream reaches the end before reading eight bytes.
IOException - the stream has been closed and the contained input stream does not support reading after close, or another I/O error occurs.
Put a proper termination condition in your while loop to resolve the issue e.g. below:
while(in.available() > 0) <--- if there are still bytes to read

The best way to handle this would be to terminate your infinite loop with a proper condition.
But since you asked for the exception handling:
Try to use two catches. Your EOFException is expected, so there seems to be no problem when it occures. Any other exception should be handled.
...
} catch (EOFException e) {
// ... this is fine
} catch(IOException e) {
// handle exception which is not expected
e.printStackTrace();
}

You can use while(in.available() != 0) instead of while(true).

Alternatively, you could write out the number of elements first (as a header) using:
out.writeInt(prices.length);
When you read the file, you first read the header (element count):
int elementCount = in.readInt();
for (int i = 0; i < elementCount; i++) {
// read elements
}

You may come across code that reads from an InputStream and uses the snippet
while(in.available()>0) to check for the end of the stream, rather than checking for an
EOFException (end of the file).
The problem with this technique, and the Javadoc does echo this, is that it only tells you the number of blocks that can be read without blocking the next caller. In other words, it can return 0 even if there are more bytes to be read. Therefore, the InputStream available() method should never be used to check for the end of the stream.
You must use while (true) and
catch(EOFException e) {
//This isn't problem
} catch (Other e) {
//This is problem
}

You catch IOException which also catches EOFException, because it is inherited. If you look at the example from the tutorial they underlined that you should catch EOFException - and this is what they do. To solve you problem catch EOFException before IOException:
try
{
//...
}
catch(EOFException e) {
//eof - no error in this case
}
catch(IOException e) {
//something went wrong
e.printStackTrace();
}
Beside that I don't like data flow control using exceptions - it is not the intended use of exceptions and thus (in my opinion) really bad style.

Put your code inside the try catch block:
i.e :
try{
if(in.available()!=0){
// ------
}
}catch(EOFException eof){
//
}catch(Exception e){
//
}
}

EOFException being a child of IOException
I prefer it like below ==>
try {
.
.
.
} catch (IOException e) {
if (!(e instanceof EOFException)) {
throw new RuntimeException(e);
}
}

Related

Objects not read completely when reading from a File in Java

I'm saving objects from two array lists to a file and if I restart the application I have called a read method at the startup which will read the data from the file and add them to the array lists
But when reading from the file only the first object is been read and added to the list even when I add several objects to the array list and save to the file when reading only the first object is read
My Method to Read Objects from the File:
void readData() throws IOException{
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("systemData.txt"))) {
doctorList.add((Doctor) in.readObject());
consultations.add((Consultation) in.readObject());
} catch (EOFException ignored){
} catch (IOException | ClassNotFoundException e ) {
e.printStackTrace();
}catch (ClassCastException ignored) {
}
}
My Method to Save Objects to the File:
#Override
public void saveFile() {
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("systemData.txt"))) {
for (Doctor doctor : doctorList) {
out.writeObject(doctor);
System.out.println("Doctor data saved to the file");
}
for (Consultation consultation: consultations){
out.writeObject(consultation);
System.out.println("Consultation data saved to the file");
}
} catch (IOException e) {
e.printStackTrace();
}
}
As #Slaw hints at you need to inform the read method how many many Doctors to read, then the number of Consulations. In short readObject() does not read the collection, only a single item... that's because you wrote item by item.
Think of it like this:
Imagining stuffing 4 apples and 6 oranges into a legwarmer.
When you write/put in, you call writeObject() 4+6 times. When you read you are pulling things out of the leg warmer from the other end (that's why I chose a leg warmer and not a sock!) and you they come out in exactly the order you put them in. But just like a leg warmer/sock you cannot immediately tell what is going to come out as the objects have similar size...
Certainly your code is quite wrote since you invoke readObject() just twice. So you read just one of the Doctors into the doctors collection then what happens? Well, the second readObject() reads a Doctor but your code tries to cast it into a Consultation which will raise a ClassCastException. Your code catches this but then swallows the Exception so you don't know that that happened! (Hence why it is always bad to have empty catch blocks.
With this low level approach, people develop their own protocols to define how to know what is coming out of the leg-warmer, like #Slaw suggests,. In rough code (I didn't check this compiled) it would be:
out.writeObject(doctorList.size());
for (Doctor doctor : doctorList) {
out.writeObject(doctor);
}
out.writeObject(consultations.size());
for (Consultation consultation: consultations){
out.writeObject(consultation);
}
out.flush();
then read
Integer expectedDoctors = (Integer) in.readObject();
for(int i=0; i<expectedDoctors; i++) {
doctorList.add((Doctor) in.readObject());
}
Integer expected Consultations = (Integer) in.readObject();
for(int i=0; i<Consultations; i++) {
consultations.add((Consultation) in.readObject());
}
A simpler approach would be not to write Doctor by Doctor but the whole collection in one go:
out.writeObject(doctorList);
out.writeObject(consultations;
out.flush();
then read
doctorList.addAll((List) in.readObject());
consultations.addAll((List) in.readObject());
Now you don't need the "here comes" counter. Note addAll() and the changed cast.
The other things you must do is call out.flush(); to ensure all the data has been written - essential if you were to wrap the output stream with a Buffer.

Processing all exceptions in multiple streams

I want my program exceptions to be sent to each of the following, preferably simultaneously:
the console which starts it (not necessarily)
a gui
a txt file.
How can I achieve this?
My attempts:
System.setErr(PrintStream err) will forward all exceptions to a new stream. I am not able to state more than
one stream though.
Calling System.setErr(PrintStream err) on a manually written OutputStream:
"You can write your own stream class that forwards to multiple streams and call System.setOut on an instance of that class" – Jeffrey Bosboom
I found a way to do this. It is very nasty though. It "collects" PrintStream's write-bytes, puts them in a puffer (500 ms timeout) and finally shows it to the user (Proceed):
/* ErrorOutput.java */
public static t_ErrBuffer t_activeErrBuffer = new t_ErrBuffer("");
public static void setStdErrToFile(final File file) {
ps = new PrintStream(fos) {
#Override
public void write(byte[] buf, int off, int len) {
byte[] bn = new byte[len];
for (int i = off, j = 0; i < (len + off); i++, j++) {
bn[j] = buf[i];
}
String msg = null;
try {
msg = new String(bn, "UTF-8");
} catch (UnsupportedEncodingException e1) {}
if (msg.matches("[\\w\\W]*[\\w]+[\\w\\W]*")) { // ^= contains at least one word character
if( ! t_activeErrBuffer.isAlive() ) {
t_activeErrBuffer = new t_ErrBuffer(msg);
t_activeErrBuffer.start();
} else {
t_activeErrBuffer.interrupt();
t_activeErrBuffer = new t_ErrBuffer(t_activeErrBuffer.getErrBuffer() + "\n" + msg); // ^= append to buffer and restart.
t_activeErrBuffer.start();
}
}
}
};
System.setErr(ps);
}
/* t_ErrBuffer.java */
public class t_ErrBuffer extends Thread {
private String errBuffer;
public t_ErrBuffer(String buffer) {
this.errBuffer = buffer;
}
protected class Proceed implements Runnable {
public String msg = null;
public Proceed(String msg) {
this.msg = msg;
}
#Override
public void run() {
// todo PRINT ERROR MESSAGE: DO THINGS WITH msg: console, gui, JOptionPane
}
}
#Override
public void run() {
try {
Thread.sleep(500); // collect error lines before output. Needed because PrintStream's "write"-method writes ErrorMessages in multiple pieces (lines)
// each time some new exception line comes in, the thread is stopped, buffer is being appended and thread new started
} catch (InterruptedException e) {
return; // stop
}
// after 500 ms of wait, no new error message line has come in. Print the message out:
Thread t_tmp = new Thread(new Proceed("\n" + this.errBuffer));
t_tmp.start();
return;
}
public String getErrBuffer() {
return this.errBuffer;
}
}
is this what I am expected to do?
Create new exception class which does it for me. Would probably work, but other exceptions than that (IO, FileNotFound, ...) will still be treated the old way
Instead of stating [method name] throws Exception I could enclose all of my code in try/catch-blocks, get the exception and forward it to a method of mine, like this:
/* AnyMethod.java */
// ...
try {
// ... do everything here
} catch (IOException | FileNotFoundException e) { // as many as you like
ErrorOutput.crash(e);
}
// ...
/* ErrorOutput.java */
public static void crash(Exception e) {
FileOutputStream fos_errOutput = new FileOutputStream(new File("ErrorOutput.txt"), true);
// 1st
if (!System.out.equals(fos_errOutput)) {
System.out.println(e.getMessage() + " :"); // to console or the preferred StdOut
e.printStackTrace();
}
// 2nd
JOptionPane.showMessageDialog(Gui.frame, "THE PROGRAM HAS CRASHED!" + "\n\n" + e.getMessage() + "\n\nFor a more detailed report, see ErrorLog.txt"); // gui output
// 3rd
PrintStream ps = new PrintStream(fos_errOutput);
ps.print(new Date().toString() + ":"); // write to file
e.printStackTrace(ps);
ps.close();
// 4th
System.exit(0); // this could also be "throw new Exception" etc., but I don't know why one should do that.
}
this would probably also work, but I'd have to put everything into try/catch-blocks. This cannot be good programming style at all.
Using a logger:
"use log4j and set up a method to write to GUI and also to log to
stdout, and file" – Scary Wombat
Loggers only help me printing my exceptions into desired streams, but they don't help me catching them, right?
But you really should use a logging package for this -- even java.util.logging can do what you need – Jeffrey Bosboom
I have to tell my logging package where and what to log. But this is exactly what I am searching for.
I now can, as user3159253 suggested, use Thread.UncaughtExceptionHandler to catch unhandled exceptions specifically.
What is the right way to handle all thrown exceptions the way I want them to? What else do I have to consider apart from Thread.UncaughtExceptionHandler and System.setErr()(see above)?
First you need get hold of all exception instances thrown from/within your thread (may be try/catch or Thread.UncoughtExceptionHandler or ThreadPoolExecutor.afterExecute(Runnable r, Throwable t)).
Then once you have the exception instance you can simply log it using log4j but configure Log4j appenders to send your exception messages to multiple destinations. You can use File, Console, JDBC, JMS etc types of appenders depending upon your requirement. Also it is best to wrap them with Async appender.
Refer - https://logging.apache.org/log4j/2.x/manual/appenders.html
About pushing the exception message to GUI, it can be implemented in various ways depending upon what tech stack your are using in your application. In our application we are storing the message events (only critical ones) in database which are then picked by event monitoring threads from server and then pushed back to GUI (JQuery, JavaScript) using http://cometd.org/documentation/cometd-java.
Creating an object that extends PrintStream should work. Whenever it receives a line, it can display it and log it as required. Alternatively, all exceptions can be caught and redirected into a method that receives an Exception as a parameter, and the method can take care of logging/displaying the exception, and terminating the program cleanly.

I just write a wrapcommand in java but sometimes it do not print the command output. WHY

I just write a simple commandwrapper in java, this is construction function:
Process process;
Thread in;
Thread out;
public CommandWrapper(Process process) {
this.process = process;
final InputStream inputStream = process.getInputStream();
// final BufferedReader
//final BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
final byte[] buffer = new byte[1024];
out = new Thread() {
// String line;
int lineNumber = 0;
public void run() {
try {
while (true) {
int count = inputStream.read(buffer);
System.out.println(lineNumber + ":"
+ new String(buffer, 0, count - 1));
// line=r.readLine();
// System.out.println(lineNumber+":"+line);
lineNumber++;
}
} catch (Exception e) {
}
}
};
final BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
final OutputStream outputStream = process.getOutputStream();
in = new Thread() {
String line;
public void run() {
try {
//while (true) {
outputStream.write((reader.readLine() + "/n")
.getBytes());
outputStream.flush();
//}
} catch (Exception e) {
}
}
};
}
public void startIn() {
in.start();
}
This is when it invoke:
public static void main(String[] args) {
try {
CommandWrapper command = new CommandWrapper(Runtime.getRuntime()
.exec("wget www.google.com"));
//command.startIn();
command.startOut();
} catch (Exception e) {
e.printStackTrace();
}
}
It works OK when I run simple command like ls -l or other local commander, but when I want to run wget command it is print out nothing as output. I do know why.
From the code you've shown and your description of how you use it, the best guess is that an exception occurs, and you silently swallow it. This happens whenever you have an empty catch-block, like this:
catch (Exception e) {
}
You happen to have one in the run() method of your out thread.
Silently swallowing exceptions is extremely bad practice.
You should never ever ever do this! Depending on your application the appropriate solution varies, but since you're writing a console application you probably want to print the stack trace of the exception. In Java, this is done with e.printStackTrace():
catch (Exception e) {
e.printStackTrace();
}
Another option (which might not be appropriate in this specific case) is to rethrow the exception, possibly after wrapping it in another exception (for example one you've written specifically for your application):
catch (Exception e) {
throw e;
}
// or
catch (Exception e) {
throw new MyOwnException(e);
}
Doing either of these two (printing stack trace or rethrowing) will ensure that no exceptions go unnoticed.
However, no rule without exceptions ;)
There are cases when it is appropriate to have empty catch-clauses. If you know that some operation might throw an exception and you just want to proceed when it happens, an empty catch-clause is a good way to do it. However, the cases where this is appropriated are limited to (at least) the following conditions:
You must know the specific type of the exception. You never want to catch a general exception (i.e. catch (Exception e) since that might be thrown for any reason which you cannot possibly predict. If you use empty catch clauses, always catch specific exception type (such as IOException).
You must know why the exception was thrown. You should only swallow exceptions that you know the origin of. If you swallow any other exceptions, you'll end up like in this situation, where your code doesn't do what you expect and you can't understand why. Swallowed exceptions are extremely difficult to debug, since they are, well, swallowed, and thereby hidden.
You must know that you don't care about the exception. The reason to use empty catch-clauses is mainly (read: only) to handle situations where the code you're using treats something as exceptional, while you do not. By exeptional in this context we mean "something that shouldn't really happen, and if it does, something is seriously wrong."
An example of when empty catch-clauses are appropriate:
Say that you are using someone elses code that opens a file for reading, given the absolute path of the file. Most such routines throw exceptions if the file does not exist - it is the job of the client code (i.e. the code that calls the "open file routine") to ensure that the file exists before trying to open it. Exceptions will also be thrown if, for example, the user running the program does not have permissions to read the file.
Now, you might not really care why the file couldn't be opened, but if it couldn't you just want to keep going - in that case, you swallow all exceptions related to reading the file (in Java, likely an IOException of some sort). Note that you do not swallow all exceptions - only the ones related to opening the file!

Problems with InputStream

Following is a part of the code snippet that I will be using for my project.
public String fetchFromStream()
{
try
{
int charVal;
StringBuffer sb = new StringBuffer();
while((charVal = inputStream.read()) > 0) {
sb.append((char)charVal);
}
return sb.toString();
} catch (Exception e)
{
m_log.error("readUntil(..) : " + e.getMessage());
return null;
} finally {
System.out.println("<<<<<<<<<<<<<<<<<<<<<< Called >>>>>>>>>>>>>>>>>>>>>>>>>>>");
}
}
Initially the while loop start working pretty fine. But after the probable last character is read from the stream I was expecting to get -1 return value. But this is where my problem starts. The code gets hanged, even the finally block is not executed.
I was debugging this code in Eclipse to see what is actually happening during the run-time. I set a pointer (debug) inside the while loop and was constantly monitoring the StringBuffer getting populated with char values one by one. But suddenly while checking the condition inside the while loop, the debugging control is getting lost and this is the point where the code goes to hangup state !! No exception is thrown as well !!
What is happening here ?
Edit::
This is how I'm getting my InputStream. Basically I'm using Apache Commons Net for Telnet.
private TelnetClient getTelnetSession(String hostname, int port)
{
TelnetClient tc = new TelnetClient();
try
{
tc.connect(hostname, port != 0 ? port : 23);
//These are instance variables
inputStream = tc.getInputStream();
outputStream = new PrintStream(tc.getOutputStream());
//More codes...
return tc;
} catch (SocketException se)
{
m_log.error("getTelnetSession(..) : " + se.getMessage());
return null;
} catch (IOException ioe)
{
m_log.error("getTelnetSession(..) : " + ioe.getMessage());
return null;
} catch (Exception e)
{
m_log.error("getTelnetSession(..) : " + e.getMessage());
return null;
}
}
Look at the JavaDocs:
Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.
In simple turns: if your stream ended (e.g. end of file), read() returns -1 immediately. However if the stream is still open but JVM is waiting for data (slow disk, socket connection), read() will block (not really hung).
Where are you getting the stream from? Check out the available() - but please do not call it in a loop exhausting CPU.
Finally: casting int/byte to char will only work for ASCII characters, consider using Reader on top of InputStream.
read the docs
read() will wait until there is more data on the InputStream if the InputStream is not closed.
I suspect you are doing this with sockets? This is the most common area where this comes up.
"Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown"
I have the same issue with the Apache Commons on Android ...
the read() command on the inputstream hangs forever for some reason. And no, it is not just blocking "until data is available" ...
my debugging information shows that there are several 100 chars available() ... yet it just randomly blocks at some read. However, whenever I send something to the telnet server the block is suddenly released and it will continue reading for several chars until it suddenly stops/blocks again at some arbitrary point!
I believe there is some bug within the Apache Commons library! This is really annoying because there isn't a lot that can be done ... no timeout for the read command or anything else ...
EDIT: I was able to get around it ... by setting the TelNetClient.setReaderThread(false) ... obviously there is a bug within the Library that exists as long as a thread handles the input data ... when dispabled it works just fine for me!

Android - Socket time out

I have some strange socket behavior going on. I've set an timeout of 5 seconds using setSoTimeout. This should be plenty of time in my situation. According to online java documentation a SocketTimeoutException should be thrown if it times out. It also says that the socket is still valid. So I want to catch it and then continue. However instead of the inner catch, the outer catch IOException is catching the expception and when I output to the log the details it says it was a SocketTimeoutException. Another perplexing thing is I change the timeout from 5 seconds to say, 15 seconds and log the amount of time it take for every read, the times are always in the milli-second range, never even close to a second. Any ideas are GREATLY appreciated.
ReadThread code snippet
#Override
public void run()
{
try
{
while (true)
{
byte[] sizeBuffer = new byte[BYTES_FOR_MESSAGE_SIZE];
int bytesRead = this.inputStream.read(sizeBuffer);
int length = 0;
for (int i = 0; i < BYTES_FOR_MESSAGE_SIZE; i++)
{
int bitsToShift = 8 * i;
int current = ((sizeBuffer[i] & 0xff) << bitsToShift);
length = length | current;
}
byte[] messageBuffer = new byte[length];
this.socket.setSoTimeout(5000); //5 second timeout
try
{
this.inputStream.read(messageBuffer);
}
catch(java.net.SocketTimeoutException ste)
{
Log.e(this.toString(), "---- SocketTimeoutException caught ----");
Log.e(this.toString(), ste.toString());
}
}
}
catch (IOException ioe)
{
Log.e(this.toString(), "IOException caught in ReadThread");
Log.e(this.toString(), ioe.toString());
ioe.printStackTrace();
}
catch (Exception e)
{
Log.e(this.toString(), "Exception caught in ReadThread");
Log.e(this.toString(), e.toString());
e.printStackTrace();
}
this.interfaceSocket.socketClosed();
}// end run
I agree with Brian. You are probably getting the timeout on the first read, not the second. The timeout once set remains in effect until you change it again.
Your second read call where you read the 'message' seems to assume (a) that it will read the entire message and (b) that it will timeout if the entire message doesn't arrive within 5s. It doesn't work like that. It will timeout if nothing arrives within 5s, or else it will read whatever has arrived, up to message.length. But it could only be one byte.
You should use DataInputStream.readFully() to read the entire message, and you need to completely reconsider your timeout strategy.
The exception is probably caught in the first try catch because of the earlier call to this.inputStream.read(). You have two of these calls: one in the outer try, one in the inner try.
Have you validated if data is being read? If data is being read then you should expect the read operation to return after a few milliseconds. If data is not being read, then the read operation should block there for the time you specify. Maybe this has to do with the order by which you setSoTimeout (perhaps doing it earlier will help).
Good luck,
B-Rad

Categories