Deserializing a list of objects - java

I have file that I need to deserialize with multiple objects of the same type.
public static ArrayList<Dog> readDogs() {
ArrayList<Dogs> dogs = null;
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(filename)));
dogs = new ArrayList<Dog>();
while(true) {
dogs.add((Dog) in.readObject());
}
} catch (EOFException e) {
} catch (Exception e) {
System.err.println(e.toString());
} finally {
try {
in.close();
} catch (IOException e) {
System.err.println(e.toString());
}
}
return dogs;
}
With the current implementation, I rely upon a try clause to catch and ignore an end of file exception, this seems pretty ugly but I'm not sure how else to handle this?

Don't serialize/deserialize each dog. Serialise/deserialize a single List of Dogs.
All List implementations are themselves Serializable, and serializing them will automatically serialize all its elements.

EOFEception represents an exceptional condition that is caused by something outside of your code. If you are not capturing an Error or a RuntimeException which represents some bug that you could fix in your code, then using an Exception is the best way to deal with the problem.
If the problem is not in your code, which is correct, but outside of it (network down, file not found, file corrupted), it is OK and usually recommended to deal with the problems using exceptions.
There are cases where you should validate data before you use it. If there is a large chance of the data being received in an incorrect format (ex: user input), it might be more efficient to validate it first. But in rare cases where you might have a corrupted file among thousands, it's better to catch the exception when it occurs and deal with it.
You could improve your code logging the exceptions, so you can trace them later. You should also consider which class should be responsible for dealing with the exception (if it should catch it and fix the problem, or if it should declare throws and propagate it to the caller.

Use InputStream.available() to test whether data is available in the stream before reading the next dog.

The following code should work:
try {
FileInputStream fin = new FileInputStream(filename);
in = new ObjectInputStream(new BufferedInputStream(fin));
dogs = new ArrayList<Dog>();
while (fin.available() > 0) {
dogs.add((Dog) in.readObject());
}
} catch (EOFException e) {
Note that you should call available() on the FileInputStream object, not the ObjectInputStream object, which doesn't properly support it. Note also that you should still catch and handle EOFException, since it may still be raised in exceptional situations.

Related

Creating a ZipFile, needs to be initialised but initialisation needs exceptions handled

So I need to add a new method to a program, it requires me accessing this zip folder. The first method downloads from a website and returns a File object.
So now in my method, I'm wanting to change this to be a ZipFile object. At the minute I just want to take in the File, create a ZipFile object using that File, then return it.
So everything is fine, but when I create the ZipFile object, it says an unhandled IOException is there. But if I put the try/catch around it I cannot return the ZipFile. So I create it first and then do the try catch but tells me that the ZipFile is not initialised. Any idea on what I'm missing in my thinking here or how I can sort this?
My code looks like;
ZipFile zipTestData;
try {
zipTestData = new ZipFile(testData)
}catch (IOException io)
log.debug(io.toString());
}catch(Exception e) {
log.debug(e.toString());
}
return zipTestData;
You should not 'swallow' an exception. If an exception occurs, you probably should pass it on for the caller to handle. Otherwise, how would the caller know the operation failed?
You may also use the approach you described, if the caller is prepared to handle the result correctly, like so:
ZipFile zipTestData = null;
try {
zipTestData = new ZipFile(testData)
} catch (IOException io)
log.debug(io.toString());
} catch(Exception e) {
log.debug(e.toString());
}
return zipTestData;
This will return null to the caller instead of a ZipFile if the zip cannot be created for whatever reason.
Although, in that specific case, you could just as well write
try {
return new ZipFile(testData)
} catch (IOException io)
log.debug(io.toString());
} catch(Exception e) {
log.debug(e.toString());
}
return null;
The reason for the error you get is that local variables are not initialized by default upon declaration. So when you declare a local variable (ZipFile zipTestData;) it is not assigned any value. Then, if at run time an exception is thrown at new ZipFile(testData), the variable will not get assigned and the return would try to return the value of that unassigned variable. In Java, that's forbidden.
probably you should initialize the
ZipFile zipTestData = null;
Without stacktrace this is what I could figure out

Should we ignore IOException while close Buffered stream?

I load a xml content, and save it to the disk. Then I read it, and try to parse.
When I have successfully parsed xml, should I ignore IOException in 7 line?
catch (IOException ignore) {}
Or some problems may occured?
private HashMap <String, VideoDto> loadContent(String url){
try {
BufferedInputStream bStream = httpGateway.loadContents();
cachedContent = xmlParser.parseVideos(bStream);
try {
bStream.close();
} catch (IOException ignore) {}
return cachedContent;
} catch (XMLStreamException e) {
throw new IllegalStateException("I/O error during integration", e);
}
}
public BufferedInputStream loadContents() {
URL source = config.getContentPath();
URL target= config.getLastImportedFile();
try {
ReadableByteChannel rbc = Channels.newChannel(source.openStream());
FileOutputStream fos = new FileOutputStream(target.getFile());
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Wrong url format", e);
} catch (IOException e) {
throw new IllegalArgumentException("I/O error while saving "+target, e);
}
return createBufferStream(config.getLastImportedFile());
}
private BufferedInputStream createBufferStream(URL url){
try {
return new BufferedInputStream(url.openConnection().getInputStream());
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
There are three parts to this question:
Q1: Should one ever ignore (squash) an exception?
I think that the answer is ... "it depends".
If the exception cause is known AND it you can catch it precisely (i.e. without also catching exceptions with different causes) AND the correct thing to do is to ignore it then ... IMO ... Yes it is acceptable.
Otherwise. No.
Q2: What does and IOException mean in this case, and does it matter?
The answer is that it is not at all clear. Under normal circumstances, one would not expect an IOException when closing an input stream, and it is hard to know what it might mean. Intuitively it is probably harmless. On the other hand, if you don't know what might cause something it is hard to say whether or not it matters.
Q3: Should you simply ignore this IOException?
I would say no. But I would handle it like this:
} catch (IOException ex) {
// possibly log the exception here.
throw new AssertionError("Unexpected exception", ex);
}
The rationale is that if something totally unexpected does occur, then it would be a good thing if the developer / maintainer could find out, and figure out how to deal with it.
On the other hand, if you could make an a priori assessment that any IOException here is harmless, then simply logging (or even squashing) it might be sufficient.
Never ignore exceptions, even if nothing goes wrong. This is the seed of bugs.
The desired thing to do, if you don't need any actions to be done, is, print its stack trace.
e.printStackTrace();
You may ignore that at any time, but may help you in the long run.
Use the try syntax that exists since Java 7:
try (BufferedInputStream bStream = httpGateway.loadContents();) {
cachedContent = xmlParser.parseVideos(bStream);
}
With this you don't have to call .close() manually.
You should catch all exceptions that are thrown inside the try block, though.
This means that the stream will (probably) still be open, whether that is a problem in your program only you will know. At the very least you should log the exception, otherwise you might get strange results that are hard to detect.
You might also want to look at the try-with-resources syntax which doesn't pose this dilemma:
try (BufferedInputStream bStream = httpGateway.loadContents()) {
cachedContent = xmlParser.parseVideos(bStream);
}
In Effective Java Joshua Bloch gives this as an example of an exception you might want to log and ignore. He says, however, that in general you want to do more than just logging an exception.

ObjectInputStream read a empty object

I wrote a object using ObjectOutputStream, and read it using ObjectInputStream, and tested it , I get the expected result. But when write the object in other machine, read it in my computer, the read object's members are empty. Could someone help me? thanks
public class TrustNet implements Serializable{
public double[][] trusts;
public double avg = 0;
public TrustNet(int size){
trusts = new double[size][size];
}
public void writeToFile(String fileName){
try(ObjectOutputStream writer = new ObjectOutputStream(new FileOutputStream(fileName))){
writer.writeObject(this);
writer.flush();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static TrustNet readFromFile(String fileName){
try(ObjectInputStream writer = new ObjectInputStream(new FileInputStream(fileName))){
return (TrustNet) writer.readObject();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
return null;
}
}
It took me a day to figure out what's going on. I think I finally have the answer. May be it will help other people having similar problem.
In my case, the problem was due of using ProGuard.
ProGuard minifyed the code, giving new shorts names to fields, like
a, b, c, etc.
When serializing, the names of fields get stored into the stream. When reading the stream, the names must match.
When I minifyed code the last time (for the new Production version of the app), ProGuard gave different names to fields (in my case it
was due of changed ProGuard settings, but may be due of other
reasons too, not sure if ProGuard guarantee the same names every
time).
As result, when I deserialize the object in the new version, because of the names are not match, all the fields set to default values.

How to properly handle important unchecked exceptions

I'm writing a library that wraps around a REST API. The wrapper I'm creating uses GSON to deserialize the json into my object. Basically, something like this...
public Post getPost(url) throws IOException {
String jsonString = httpClient.get(url);
Post p = gson.fromJson(jsonString, Post.class);
// return Post to client and let client do something with it.
}
If I understand correctly, IOException is a checked exception. I'm telling my client: Hey, buddy - you better watch out and recover from this exception. Now my client can wrap the call in a try/catch and determine what to do if there is some network failure.
The GSON fromJson() method throws a JsonSyntaxException. I believe this is unchecked in the Java world, as one of its super classes is RuntimeException, and also because I am not required to add a try/catch or another "throws" like IOException.
Assuming what I have said so far is correct - how exactly should the API and client handle this situation? If the json string is garbage, my client is going to fail miserably due to the JsonSyntaxException because it's unchecked.
// Client
PostService postService = new PostService();
try{
Post p = postService.getPost(urlString);
// do something with post
}catch (IOException){
// handle exception
}
// ok, what about a JsonSyntaxException????
What's the best way to handle these situations?
You are allowed to catch unchecked exceptions. Just add catch(JsonSyntaxException e) to your try-catch block. After you catch the JsonSyntaxException, you can either handle it or rethrow it as a checked exception.
Ex:
try{
//do whatever
}catch(JsonSyntaxException e){
e.printStackTrace();
// throw new Exception(e); //checked exception
}catch(IOException e){
e.printStackTrace();
}

Correct way to close nested streams and writers in Java [duplicate]

This question already has answers here:
Is it necessary to close each nested OutputStream and Writer separately?
(7 answers)
Closed 6 years ago.
Note: This question and most of its answers date to before the release of Java 7. Java 7 provides Automatic Resource Management functionality for doing this easilly. If you are using Java 7 or later you should advance to the answer of Ross Johnson.
What is considered the best, most comprehensive way to close nested streams in Java? For example, consider the setup:
FileOutputStream fos = new FileOutputStream(...)
BufferedOS bos = new BufferedOS(fos);
ObjectOutputStream oos = new ObjectOutputStream(bos);
I understand the close operation needs to be insured (probably by using a finally clause). What I wonder about is, is it necessary to explicitly make sure the nested streams are closed, or is it enough to just make sure to close the outer stream (oos)?
One thing I notice, at least dealing with this specific example, is that the inner streams only seem to throw FileNotFoundExceptions. Which would seem to imply that there's not technically a need to worry about closing them if they fail.
Here's what a colleague wrote:
Technically, if it were implemented right, closing the outermost
stream (oos) should be enough. But the implementation seems flawed.
Example:
BufferedOutputStream inherits close() from FilterOutputStream, which defines it as:
155 public void close() throws IOException {
156 try {
157 flush();
158 } catch (IOException ignored) {
159 }
160 out.close();
161 }
However, if flush() throws a runtime exception for some reason, then
out.close() will never be called. So it seems "safest" (but ugly) to
mostly worry about closing FOS, which is keeping the file open.
What is considered to be the hands-down best, when-you-absolutely-need-to-be-sure, approach to closing nested streams?
And are there any official Java/Sun docs that deal with this in fine detail?
When closing chained streams, you only need to close the outermost stream. Any errors will be propagated up the chain and be caught.
Refer to Java I/O Streams for details.
To address the issue
However, if flush() throws a runtime exception for some reason, then out.close() will never be called.
This isn't right. After you catch and ignore that exception, execution will pick back up after the catch block and the out.close() statement will be executed.
Your colleague makes a good point about the RuntimeException. If you absolutely need the stream to be closed, you can always try to close each one individually, from the outside in, stopping at the first exception.
In the Java 7 era, try-with-resources is certainly the way to go. As mentioned in several previous answers, the close request propagates from the outermost stream to the innermost stream. So a single close is all that is required.
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f))) {
// do something with ois
}
There is however a problem with this pattern. The try-with-resources is not aware of the inner FileInputStream, so if the ObjectInputStream constructor throws an exception, the FileInputStream is never closed (until the garbage collector gets to it). The solution is...
try (FileInputStream fis = new FileInputStream(f); ObjectInputStream ois = new ObjectInputStream(fis)) {
// do something with ois
}
This is not as elegant, but is more robust. Whether this is actually a problem will depend on what exceptions can be thrown during construction of the outer object(s). ObjectInputStream can throw IOException which may well get handled by an application without terminating. Many stream classes only throw unchecked exceptions, which may well result in termination of the application.
It is a good practice to use Apache Commons to handle IO related objects.
In the finally clause use IOUtils
IOUtils.closeQuietly(bWriter);
IOUtils.closeQuietly(oWritter);
Code snippet below.
BufferedWriter bWriter = null;
OutputStreamWriter oWritter = null;
try {
oWritter = new OutputStreamWriter( httpConnection.getOutputStream(), "utf-8" );
bWriter = new BufferedWriter( oWritter );
bWriter.write( xml );
}
finally {
IOUtils.closeQuietly(bWriter);
IOUtils.closeQuietly(oWritter);
}
I usually do the following. First, define a template-method based class to deal with the try/catch mess
import java.io.Closeable;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public abstract class AutoFileCloser {
// the core action code that the implementer wants to run
protected abstract void doWork() throws Throwable;
// track a list of closeable thingies to close when finished
private List<Closeable> closeables_ = new LinkedList<Closeable>();
// give the implementer a way to track things to close
// assumes this is called in order for nested closeables,
// inner-most to outer-most
protected final <T extends Closeable> T autoClose(T closeable) {
closeables_.add(0, closeable);
return closeable;
}
public AutoFileCloser() {
// a variable to track a "meaningful" exception, in case
// a close() throws an exception
Throwable pending = null;
try {
doWork(); // do the real work
} catch (Throwable throwable) {
pending = throwable;
} finally {
// close the watched streams
for (Closeable closeable : closeables_) {
if (closeable != null) {
try {
closeable.close();
} catch (Throwable throwable) {
if (pending == null) {
pending = throwable;
}
}
}
}
// if we had a pending exception, rethrow it
// this is necessary b/c the close can throw an
// exception, which would remove the pending
// status of any exception thrown in the try block
if (pending != null) {
if (pending instanceof RuntimeException) {
throw (RuntimeException) pending;
} else {
throw new RuntimeException(pending);
}
}
}
}
}
Note the "pending" exception -- this takes care of the case where an exception thrown during close would mask an exception we might really care about.
The finally tries to close from the outside of any decorated stream first, so if you had a BufferedWriter wrapping a FileWriter, we try to close the BuffereredWriter first, and if that fails, still try to close the FileWriter itself. (Note that the definition of Closeable calls for close() to ignore the call if the stream is already closed)
You can use the above class as follows:
try {
// ...
new AutoFileCloser() {
#Override protected void doWork() throws Throwable {
// declare variables for the readers and "watch" them
FileReader fileReader =
autoClose(fileReader = new FileReader("somefile"));
BufferedReader bufferedReader =
autoClose(bufferedReader = new BufferedReader(fileReader));
// ... do something with bufferedReader
// if you need more than one reader or writer
FileWriter fileWriter =
autoClose(fileWriter = new FileWriter("someOtherFile"));
BufferedWriter bufferedWriter =
autoClose(bufferedWriter = new BufferedWriter(fileWriter));
// ... do something with bufferedWriter
}
};
// .. other logic, maybe more AutoFileClosers
} catch (RuntimeException e) {
// report or log the exception
}
Using this approach you never have to worry about the try/catch/finally to deal with closing files again.
If this is too heavy for your use, at least think about following the try/catch and the "pending" variable approach it uses.
The colleague raises an interesting point, and there are grounds for arguing either way.
Personally, I would ignore the RuntimeException, because an unchecked exception signifies a bug in the program. If the program is incorrect, fix it. You can't "handle" a bad program at runtime.
This is a surprisingly awkward question. (Even assuming the acquire; try { use; } finally { release; } code is correct.)
If the construction of the decorator fails, then you wont be closing the underlying stream. Therefore you do need to close the underlying stream explicitly, whether in the finally after use or, more diifcult after successfully handing over the resource to the decorator).
If an exception causes execution to fail, do you really want to flush?
Some decorators actually have resources themselves. The current Sun implementation of ZipInputStream for instance has non-Java heap memory allocated.
It has been claimed that (IIRC) two thirds of the resources uses in the Java library are implemented in a clearly incorrect manner.
Whilst BufferedOutputStream closes even on an IOException from flush, BufferedWriter closes correctly.
My advice: Close resources as directly as possible and don't let them taint other code. OTOH, you can spend too much time on this issue - if OutOfMemoryError is thrown it's nice to behave nicely, but other aspects of your program are probably a higher priority and library code is probably broken in this situation anyway. But I'd always write:
final FileOutputStream rawOut = new FileOutputStream(file);
try {
OutputStream out = new BufferedOutputStream(rawOut);
... write stuff out ...
out.flush();
} finally {
rawOut.close();
}
(Look: No catch!)
And perhaps use the Execute Around idiom.
The Java SE 7 try-with-resources doesn't seem to be mentioned. It eliminates needing to explicitly do a close completely, and I quite like the idea.
Unfortunately, for Android development this sweet only becomes available by using Android Studio (I think) and targeting Kitkat and above.
Also you dont have to close all nested streams
check this
http://ckarthik17.blogspot.com/2011/02/closing-nested-streams.html
I use to close streams like this, without nesting try-catch in finally blocks
public class StreamTest {
public static void main(String[] args) {
FileOutputStream fos = null;
BufferedOutputStream bos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream(new File("..."));
bos = new BufferedOutputStream(fos);
oos = new ObjectOutputStream(bos);
}
catch (Exception e) {
}
finally {
Stream.close(oos,bos,fos);
}
}
}
class Stream {
public static void close(AutoCloseable... array) {
for (AutoCloseable c : array) {
try {c.close();}
catch (IOException e) {}
catch (Exception e) {}
}
}
}
Sun's JavaDocs include RuntimeExceptions in their documentation, as shown by InputStream's read(byte[], int, int) method; documented as throwing NullPointerException and IndexOutOfBoundsException.
FilterOutputStream's flush() is only documented as throwing IOException, thus it doesn't actually throw any RuntimeExceptions. Any that could be thrown would most likely be wrapped in an IIOException.
It could still throw an Error, but there's not much you can do about those; Sun recommends that you don't try to catch them.

Categories

Resources