Why this strange behaviour of ObjectOutputStream and ObjectInputStream throwing EOFException? - java

I wrote a custom serializing/de-serializing logic for persisting some of the data as Java default serialization turned out to be both time and memory expensive. For this purpose I wrote readObject(ObjectInput in) and writeObject(ObjectOutput out) methods for the class(es) that needs persisting. However I noticed that if I do not use any out.writeObject(obj) in writeObject(ObjectOutput out) method then it always throws EOFException.
Consider the following example:
Data.java
public class Data implements BaseData {
private String messageUID;
private String rawData;
private String data;
private Long type;
private Boolean processed = false;
private String processedMessage;
private String processedDetaildMessage;
// getter setter
public void readObject(ObjectInput in) throws IOException, ClassNotFoundException {
messageUID = in.readUTF();
rawData = in.readUTF();
data = in.readUTF();
type = in.readLong();
processed = in.readBoolean();
if (processed) {
processedMessage = in.readUTF();
processedDetaildMessage = in.readUTF();
}
}
public void writeObject(ObjectOutput out) throws IOException {
out.writeUTF(messageUID);
out.writeUTF(rawData);
out.writeUTF(data);
out.writeLong(type);
out.writeBoolean(processed);
if (processed) {
out.writeUTF(processedMessage);
String tempDetailsMessage[] = processedDetaildMessage.split(" more");
out.writeUTF(tempDetailsMessage[tempDetailsMessage.length - 1]);
}
}
However whenever I use above code the out stream is always missing some information at the end (from processedDetaildMessage field) and I get EOFException while reading it form in, stacktrace below (Data.java line 216 is processedDetaildMessage = in.readUTF());
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.readByte(ObjectInputStream.java:2766)
at java.io.ObjectInputStream$BlockDataInputStream.readUTFChar(ObjectInputStream.java:3158)
at java.io.ObjectInputStream$BlockDataInputStream.readUTFBody(ObjectInputStream.java:3055)
at java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:2864)
at java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1072)
at com.smartstream.common.Data.readObject(Data.java:216)
at com.smartstream.common.PerformanceTest.getObjectFromBytes(PerformanceTest.java:168)
at com.smartstream.common.PerformanceTest.access$0(PerformanceTest.java:160)
at com.smartstream.common.PerformanceTest$1.mapRow(PerformanceTest.java:119)
at com.smartstream.common.PerformanceTest$1.mapRow(PerformanceTest.java:1)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:92)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:60)
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:651)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:639)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:668)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:676)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:731)
at com.smartstream.common.PerformanceTest.readFromDb(PerformanceTest.java:109)
at com.smartstream.common.PerformanceTest.main(PerformanceTest.java:66)
so I though I would put some extra byte/s of information at the end after writing all required fields and will not read them so that I don't reach end of file while reading. I tried all of these out.writeByte(-1), out.writeInt(-1), out.writeLong(2342343l), out.writeUTF("END_OF_STREAM") but those make no difference. finally I did this out.writeObject(new String("END_OF_STREAM")) and it works fine. Can someone please explain as to why outputstream misses some information if none of the information is written using writeObject() method. Below is how I read and write to/from streams;
private byte[] getObjectAsBytes(Data data) {
byte[] byteArray = null;
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
// Use this for java default serialization
// oos.writeObject(data);
data.writeObject(oos);
byteArray = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.flush();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return byteArray;
}
private Data getObjectFromBytes(byte[] byteArray) {
Data data = new Data();
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
bais = new ByteArrayInputStream(byteArray);
ois = new ObjectInputStream(bais);
// Use this for java default serialization
// data = (Data) ois.readObject();
data.readObject(ois);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return data;
}
If anyone is interested below is what is written in the streams;
persisted data with original code (throws EOFException and missing information) (don't confuse the stacktrace with original issue this stacktrace is persisted as field processedDetailedMessage)
¬í---z-------3507319347632941385----FEEDER-----1437052314954 ---This is a random string---N---þ%J---!this is message of processed dataÛ
Caused by: java.sql.SQLException: ORA-01691: unable to extend lob segment TLM_DBO.SYS_LOB0000076335C00008$$ by 8192 in tablespace WIN_SL_TABLE
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1008)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
at oracle.jdbc.driver.OraclePre
persisted data after writing extra string at the end using writeObject method
¬í---z-------3507319347632941385----FEEDER-----1437052314954 ---This is a random string---N---þ%J---!this is message of processed dataÛ
Caused by: java.sql.SQLException: ORA-01691: unable to extend lob segment TLM_DBO.SYS_LOB0000076335C00008$$ by 8192 in tablespace WIN_SL_TABLE
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1008)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
at oracle.jdbc.driver.OraclePrz-----NeparedStatement.execute(OraclePreparedStatement.java:3550)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1374)
at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.pmiExecute(WSJdbcPreparedStatement.java:975)
at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.execute(WSJdbcPreparedStatement.java:642)
at com.smartstream.control.engine.config.dao.jdbc.ProcessExecutionAuditDetailDao$1.doInPreparedStatement(ProcessExecutionAuditDetailDao.java:115)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586)
... 23t
END_OF_STREAM
PS ---- represents unreadable bytes

Your persisted data is incomplete because you are creating your byte array before flushing the ObjectOutputStream. In getObjectAsBytes(Data) move byteArray = bos.toByteArray(); after the finally block to make it work. Alternatively, the method could be written more succinctly as follows (requires Java 7+):
private byte[] getObjectAsBytes(Data data) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
data.writeObject(oos);
} catch (IOException e) {
e.printStackTrace();
}
return bos.toByteArray();
}
I tested both ways in my own program and they both prevent the EOFException from being thrown.
As far as why having a writeObject was working, that's because the underlying writeObject implementation toggles block data mode at the beginning and ending of the method, and changing the block data mode performs a drain which writes all data to the underlying OutputStream, which for a ByteArrayOutputStream is effectively the same as a flush.

This issue is caused because of the different implementations of writeObject method and some other non-generic write* methods i.e. writeUTF. The writeObject method toggles to data block mode at the start and at the end of the method which results all the data being written to underlying OutputStream, this has same affect as calling flush on outputStream. This means that you cannot create another byteArray before flushing the remaining data to the stream. It would be best if you stick with writeObject method for now; ie
public void writeObject(ObjectOutput out) throws IOException {
out.writeUTF(messageUID);
out.writeUTF(rawData);
out.writeUTF(data);
out.writeLong(type);
out.writeBoolean(processed);
if (processed) {
out.writeUTF(processedMessage);
String tempDetailsMessage[] = processedDetaildMessage.split(" more");
out.writeObject(tempDetailsMessage[tempDetailsMessage.length - 1]);
}
}

Related

ObjectInputStream doesn't have available bytes after being constructed with a ByteArrayInputStream

I'm constructing a class that is handling a Binary De/Serialization. The method open() receives an InputStream and a OutputStream. Those are created by another open() method that receives a path as argument. The InputStream is actually a ByteArrayInputStream.
I already did some tests to prove that the InputStream is arriving at the open() method with content - and it actually is. But when I try to set a ObjectInputStream using it, it doesn't work. No exceptions are thrown, but when I try to read bytes from it, it always gives me -1.
BinaryStrategy class
public class BinaryStrategy implements SerializableStrategy{
public BinaryStrategy(){
try{
open("products.ser");
}catch(IOException ioe){
}
}
#Override
public void open(InputStream input, OutputStream output) throws IOException {
try{
this.ois = new ObjectInputStream(input);
}catch(Exception ioe){
System.out.println(ioe);
}
this.oos = new ObjectOutputStream(output);
}
#Override
public void writeObject(fpt.com.Product obj) throws IOException {
oos.writeObject(obj);
oos.flush();
}
#Override
public Product readObject() throws IOException {
Product read = new Product();
try{
read.readExternal(ois);
}catch(IOException | ClassNotFoundException exc){
System.out.println(exc);
}
return read;
}
}
interface SerializableStrategy (just the default method)
default void open(Path path) throws IOException {
if (path != null) {
ByteArrayInputStream in = null;
if (Files.exists(path)) {
byte[] data = Files.readAllBytes(path);
in = new ByteArrayInputStream(data);
}
OutputStream out = Files.newOutputStream(path);
open(in, out);
}
Product class
public class Product implements java.io.Externalizable {
#Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeLong(getId());
out.writeObject(getName());
out.writeObject(getPrice());
out.writeObject(getQuantity());
}
#Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.setId((Long)in.readLong());
this.setName((String) in.readObject());
this.setPrice((Double) in.readObject());
this.setQuantity((Integer) in.readObject());
}
I had to personalize it because the attributes are SimplePropertys
At public void open(InputStream input, OutputStream output) I tried to do some stuff as follow to test:
public void open(InputStream input, OutputStream output) throws IOException {
try{
System.out.println(input.available() + " " + input.read() + " " + input.read());
//is gives me: 181 172 237
//181 is the exact size of the file I have, so i think that the Output is ok
//172 237 - just some chars that are in the file
//I know that for now on it is going to give me an excepetion because
// of the position of the index that is reading. I did it just to test
this.ois = new ObjectInputStream(input);
}catch(Exception ioe){
System.out.println(ioe);
}
this.oos = new ObjectOutputStream(output);
}
And then the other test:
public void open(InputStream input, OutputStream output) throws IOException {
try{
this.ois = new ObjectInputStream(input);
System.out.println(ois.available() + " " + ois.read());
//here is where I am receiving -1 and 0 available bytes!
//so something is going wrong right here.
//i tried to just go on and try to read the object,
//but I got a EOFException, in other words, -1.
}catch(Exception ioe){
System.out.println(ioe);
}
this.oos = new ObjectOutputStream(output);
}
Please check if the file represented by the path has a java object written to it.
From the ObjectInputStream API doc https://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html
An ObjectInputStream deserializes primitive data and objects previously written using an ObjectOutputStream.
ObjectInputStream is used to recover those objects previously serialized.
If you are doing a this.ois.readObject(), and you are getting a -1, there are chances that the file does not contain an object in it.
Update: readObject returns an object and not an int. If you are using the read methods in ois, and you are getting a -1, then the file is empty.
Also, there are chances that your file contains -1 as its content ;)
ObjectInputStream, internally uses a BlockDataInputStream perform its read operations. This reads a block of data and not just a byte as we expect, when you call a read. It reads a byte only if it falls as a "block"
The output is not what I was expecting either.
But, if you look at the code of ObjectInputStream.read(), it makes sense.
So, in your case it makes sense to use only readObject to restore your objects' state.
Heres your code again...
class SimpleJava {
public static void open(InputStream input, OutputStream output) throws IOException {
try {
ObjectInputStream ois = new ObjectInputStream(input);
System.out.println(ois.available());// 0
System.out.println(ois.available() + " " + ois.read() + " " + ois.read());// 0 -1 -1
// Reads the object even if the available returned 0
// and ois.read() returned -1
System.out.println("object:" + ois.readObject());// object:abcd
}
catch (Exception ioe) {
ioe.printStackTrace();
}
}
static void open(Path path) throws IOException {
if (path != null) {
ByteArrayInputStream in = null;
if (Files.exists(path)) {
byte[] data = Files.readAllBytes(path);
in = new ByteArrayInputStream(data);
}
OutputStream out = Files.newOutputStream(path);
open(in, out);
}
}
public static void main(String[] args) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("/home/pradhan/temp.object")));
oos.writeObject("abcd");//writes a string object for us to read later
oos.close();
//
open(FileSystems.getDefault().getPath("/home/user/temp.object"));
}
}
Heres the output...
0
0 -1 -1
object:abcd
The problem was that I was reading the ObjectInputStream the wrong way. It was like:
read.readExternal(ois);
but the correct way is:
read = (Product)ois.readObject();
And beacause of the Exceptions I was getting for doing so, I thought that the problem was with the construction of ObjectInputStream when using ByteArrayInputStream.
What a big mistake! :D
Thanks to everybody that tried to help.

Java ObjectOutputStream's Method flush()

I am currently learning networking, specifically client-server classes.
I have done much research and implemented various test programs but I can't figure out why/when one would need to use the flush() method.
How can there be data mistakenly left in the output stream if it is always read in by the input stream? As dictated by the client-server code.
I tried to test my basic echo client server program by omitting the flush() but I could not break it.
When testing the flush() by writing twice from the client side and only reading once for the server's reply all that happened was a backlog (I assume the stream acts like a queue?) in the server's replies.
Then I took the same code and added flush() before and after the second write and it made no difference. It's as if the flush() doesn't actually clear the stream.
So can someone please explain in what scenario with regards to client/server stream interactions would flush() be required?
Server:
public class ServerApp
{
private ServerSocket listener;
private Socket clientCon;
public ServerApp()
{
try
{
listener = new ServerSocket(1234, 10);
} catch (IOException e)
{
e.printStackTrace();
}
}
public void listen()
{
try
{
System.out.println("Server is listening!");
clientCon = listener.accept();
System.out.println("Server: Connection made with Client");
processClient();
} catch (IOException e)
{
e.printStackTrace();
}
}
public void processClient()
{
try(ObjectOutputStream out = new ObjectOutputStream(clientCon.getOutputStream()); ObjectInputStream in = new ObjectInputStream(clientCon.getInputStream()))
{
String msg;
while(!(msg = (String)in.readObject()).equalsIgnoreCase("Shutdown"))
{
out.writeObject("Server: " + msg);
out.flush();
}
out.writeObject("Server is powering down...");
out.close();
in.close();
} catch (IOException | ClassNotFoundException e)
{
e.printStackTrace();
}
}
public static void main (String args[])
{
ServerApp sa = new ServerApp();
sa.listen();
}
}
Client:
public class ClientApp
{
private Socket serverCon;
public ClientApp()
{
try
{
serverCon = new Socket("127.0.0.1", 1234);
} catch (IOException e)
{
e.printStackTrace();
}
}
public void communicate()
{
try (ObjectOutputStream out = new ObjectOutputStream(serverCon.getOutputStream()); ObjectInputStream in = new ObjectInputStream(serverCon.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)))
{
String response = null;
do
{
System.out.println("Enter your message for server: ");
out.writeObject(br.readLine());
out.flush();
out.writeObject("Flush not working");
out.flush();
response = (String) in.readObject();
System.out.println(response);
response = (String) in.readObject();
System.out.println(response);
} while (!response.equalsIgnoreCase("Server is powering down..."));
} catch (IOException | ClassNotFoundException e)
{
e.printStackTrace();
}
}
public static void main(String args[])
{
ClientApp ca = new ClientApp();
ca.communicate();
}
}
The method flush() is used to flush out any internal buffers that may be in use. For example using a BufferedOutputStream the contents are written in chunks to improve performance (it's slower to write each byte as they come).
Depending on usage, you might never have to call flush(). However let's say you send a small String (converted to byte[]) and it fits nicely in the internal buffer. The contents of the buffer won't be sent until the buffer is full or flush() is called.
Now let's say you're writing over the network, and you expect the other side to answer something to your small String. Since it's still in the buffer, the other side won't receive it and it can result in both sides waiting forever.
Object streams are another beast, and I'm a little disappointed that so many beginners are using them. There should be a warning in the class saying "Objects may be more difficult to send/receive than they appear".
ObjectOutputStream delegates the flush() call to its internal BlockDataOutputStream which has 3 buffers sized 1024, 5 and 256 for "blockdata", header data and characters respectively.
Try it with new ObjectOutputStream(new BufferedOutputStream(clientCon.getOutputStream())) and you'll see a difference with and without flush(). It causes flushing of the underlying buffered output stream. Without a buffered stream there is no buffer to flush so it does nothing.

How to put multiple elements into byte[] in java

How can I put multiple elements into byte[]? I have the following 3 elements: 1) String data , 2) String status and 3) HashMap<String,String> headers, which need to be passed to setContent(byte[] data) as byte arrays. The following is the code in which I would like to use the previous 3 parameters as input for statusResult.setContent():
public void onSuccess(ClientResponse clientResponse){
String data=clientResponse.getMessage();
String status=String.valueOf(clientResponse.getStatus());
HashMap<String,String> headers=clientResponse.getHeaders();
// Now StatusResult is a class where we need to pass all this data,having only getters and
// setters for Content,so here in the next line i need to pass data,status and headers as
// a byte[] to setContent.
statusResult.setContent(byte[]);
}
Can somebody help me to resolve this out?
This is serialization in a crude way. I would suggest the following:
Create a class encapsulating the three elements.
Make sure that class implements serializable interface.
Use the following code [taken from this post] to create a byte array as you wished, and read the object back from byte array (which, although you have not specified as requirement, but it needs mention for the sake of completeness)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
//Assuming that bos is the object to be seriaized
out = new ObjectOutputStream(bos);
out.writeObject(yourObject);
byte[] yourBytes = bos.toByteArray();
...
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ex) {
// ignore close exception
}
try {
bos.close();
} catch (IOException ex) {
// ignore close exception
}
}
//Create object from bytes:
ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes);
ObjectInput in = null;
try {
in = new ObjectInputStream(bis);
Object o = in.readObject();
...
} finally {
try {
bis.close();
} catch (IOException ex) {
// ignore close exception
}
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
// ignore close exception
}
}

Should I keep my Streams for multiple operations?

I have the following method to compress a bytearray.
protected byte[] compress(byte[] original)
{
byte[] compressed = null;
try (ByteArrayOutputStream buffer = new ByteArrayOutputStream())
{
try (DeflaterOutputStream stream = new DeflaterOutputStream(buffer, new Deflater()))
{
stream.write(original);
}
compressed = buffer.toByteArray();
}
catch (IOException e)
{
e.printStackTrace();
}
return compressed;
}
Now I am wondering if the performance cost for constantly reinitializing the streams is high and how I could keep the streams in my class.
Are there any downsides to doing that?
Specifically in the context of threads.

Where and when should I use the close() method to avoid IOException in ObjectInputStream?

I'm trying to read an object from client program over tcp. As you can see in this line I created objectInput:
ObjectInputStream objectInput = new ObjectInputStream(incoming.getInputStream());
And then read my input from the other program. It used to work fine until i made minor changes to clean up the program. Personally Assume I added
objectInput.clsoe();
My question is, After reading the object should I close the objectInputStream or Keep remain without close? Should I close it straight away after using it or at the end of if block or at the end of program? What are the effect of the close? By the way I have read the close documentation.
Here is the error:
java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2280)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2749)
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:779)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:279)
at Server.ClientWorker.run(MyCollectionServer.java:116)
at java.lang.Thread.run(Thread.java:680)
Here is my code:
public static void main(String[] args) {
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(port);
}
catch (IOException e)
{
e.printStackTrace();
}
while(true)
{
ClientWorker w;
try
{
w = new ClientWorker(serverSocket.accept());
Thread t = new Thread(w);
t.start();
}
catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
}
class ClientWorker implements Runnable
{
.....
private Socket incoming;
public ClientWorker(Socket incoming)
{
myList = new ArrayList<PureAlbum>();
loadList();
this.incoming = incoming;
}
.....
public synchronized void run()
{
else if(request.compareTo("AddAlbum")==0)
{
try
{
ObjectInputStream objectInput = new ObjectInputStream(incoming.getInputStream()); //This is the line mentioned in the error
PureAlbum object = (PureAlbum) objectInput.readObject();
if(object instanceof CDAlbum)
{
CDAlbum a = (CDAlbum) object;
myList.add(a);
System.out.println("Artist = " + a.getArtist());
}
else if(object instanceof Client.au.edu.uow.Collection.DVDAlbum)
{
myList.add((DVDAlbum) object);
}
else
{
System.err.println("Warning : The object to add to database is unknown! "+ object.getClass() + "*");
System.exit(0);
}
}
catch (UnknownHostException e)
{
System.err.println("Can not read the host name");
e.printStackTrace();
}
catch (IOException e)
{
System.err.println("Can not read the FILE name"); //This exception has been called
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
Your code fragment is pretty long, so I will try to give you a general answer and it will hopefully help you.
The typical patterns of usage of stream.close() prior to java 7 are:
InputStream in = null;
try {
InputStream in = .....; // create your input stream;
// use input stream
} catch (IOException e) {
// do what you need here
} finally {
if (in != null) {
in.close();
}
}
or simply declare the method as throws IOException and then write:
InputStream in = null;
try {
InputStream in = .....; // create your input stream;
// use input stream
} finally {
if (in != null) {
in.close();
}
}
Pay atention that this example does not contain catch section.
Starting from java 7 we can enjoy the new facilities of the language:
try (
InputStream in = .....; // create your input stream;
) {
// use input stream
}
You even do not have to call close() at all. All resources defined into header of try block that implement interface Closable will be closed automatically.
This line of stack trace shows that the exception is occurring when you are initializing the ObjectInputStream, not when you are closing.
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:279)
The most likely cause is that the remote client did not open an ObjectOutputStream. It might have written some other kind of data, or it might have closed its output stream or simply exited.
You should close the Stream when you have completed your reading or writing.
here in this case , you should close the InputStream when you have read the file completely and you no longer require to read file from stream.
In Short , You should close the Stream when its work is over.
It may be in the end of program or after if loop....depends on your use case.
Hope this will help.
I am doing it this way (different example):
private void readFile() throws Exception {
FileInputStream fis = null;
ObjectInputStream ois = null;
Object aux = null;
try {
fis = new FileInputStream("lib.dat");
ois = new ObjectInputStream(fis);
do {
aux = ois.readObject();
if (aux instanceof MyObject)
this.myObjectInstance.add((MyObject) aux);
} while (true);
} catch (EOFException e) {
ois.close();
}
}
This way I am sending any relevant "Error" Exception upstairs to be handled, and once the EndOfFileException is launched this is specifically captured to close the stream properly.
The object has to be defined outside the Try block to be accessible from the Catch block.
The close() method could as well throw an IOException and this can't be caught by our Try block, this would have to be passed by the generic "throw Exception" of readFile() method.

Categories

Resources