patternjavaMinor
Reading and writing Serializable objects using NIO
Viewed 0 times
nioreadingobjectswritingserializableusingand
Problem
I have created the following class to read Serializable object from file and write to a file.
```
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.channels.FileLock;
/**
* Class FileSerializeStreamer is used to read and write Serialise object to
* file.
*
* @author TapasB
*/
public class FileSerializeStreamer {
/**
* Constructor FileSerializeStreamer
*
* @author TapasB
*/
public FileSerializeStreamer() {
}
/**
* Method readSerializable reads the Serialised object from file and
* returns. If the file is null or doesn't exist then it returns null
* without throwing any error.
*
* @author TapasB
* @param file
* - the instance of the file to read from.
* @param clazz
* - the class type of the object.
* @return the instance of the object.
*/
public T readSerializable(File file, Class clazz) {
if (file == null || !file.exists()) {
return null;
}
RandomAccessFile serFile = null;
FileChannel fileChannel = null;
byte[] bytes = null;
try {
serFile = new RandomAccessFile(file, "rw");
fileChannel = serFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate((int) serFile.length());
FileLock fileLock = fileChannel.lock();
fileChannel.read(buffer);
fileLock.release();
bytes = buffer.array();
buffer.clear();
} catch (Exception cause) {
cause.printStackTrace();
} finally {
closeStream(fileChannel);
closeStream(serFile);
```
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.channels.FileLock;
/**
* Class FileSerializeStreamer is used to read and write Serialise object to
* file.
*
* @author TapasB
*/
public class FileSerializeStreamer {
/**
* Constructor FileSerializeStreamer
*
* @author TapasB
*/
public FileSerializeStreamer() {
}
/**
* Method readSerializable reads the Serialised object from file and
* returns. If the file is null or doesn't exist then it returns null
* without throwing any error.
*
* @author TapasB
* @param file
* - the instance of the file to read from.
* @param clazz
* - the class type of the object.
* @return the instance of the object.
*/
public T readSerializable(File file, Class clazz) {
if (file == null || !file.exists()) {
return null;
}
RandomAccessFile serFile = null;
FileChannel fileChannel = null;
byte[] bytes = null;
try {
serFile = new RandomAccessFile(file, "rw");
fileChannel = serFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate((int) serFile.length());
FileLock fileLock = fileChannel.lock();
fileChannel.read(buffer);
fileLock.release();
bytes = buffer.array();
buffer.clear();
} catch (Exception cause) {
cause.printStackTrace();
} finally {
closeStream(fileChannel);
closeStream(serFile);
Solution
Why? Why use NIO? You are reading the data in to a buffer, completely, then you are performing the deserialization from that. What advantages of NIO are you using?
Even using your system, though, you should be using try-with-resources, and you should use the
But, given your use case, I would simply do:
If you really require the file locking, then do it all in one process anyway, and don't use the intermediate byte[] array:
Note, all the comments on the reading side, also apply to the writing side too. You can convert your serialization to match the same concepts as well.
Even using your system, though, you should be using try-with-resources, and you should use the
FileChannel.open(...) mechanism for it...try (FileChannel channel = FileChannel.open(file.getPath())) {
... do something with the channel
} catch (IOException ...) {
....
return null;
}But, given your use case, I would simply do:
try {
byte[] data = Files.readAllBytes(file.getPath());
try (ObjectINputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) {
return clazz.cast(ois.readObject());
} catch (....) {
... deserialization problem
}
} catch (....) {
... IO Problem
}If you really require the file locking, then do it all in one process anyway, and don't use the intermediate byte[] array:
try (FileChannel channel = FileChannel.open(file.getPath())) {
FileLock lock = channel.lock();
try (ObjectInputStream ois = new ObjectInputStream(Channels.newInputStream(channel))) {
return clazz.cast(ois.readObject());
} finally {
lock.release();
}
try (ObjectINputStream
}Note, all the comments on the reading side, also apply to the writing side too. You can convert your serialization to match the same concepts as well.
Code Snippets
try (FileChannel channel = FileChannel.open(file.getPath())) {
... do something with the channel
} catch (IOException ...) {
....
return null;
}try {
byte[] data = Files.readAllBytes(file.getPath());
try (ObjectINputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) {
return clazz.cast(ois.readObject());
} catch (....) {
... deserialization problem
}
} catch (....) {
... IO Problem
}try (FileChannel channel = FileChannel.open(file.getPath())) {
FileLock lock = channel.lock();
try (ObjectInputStream ois = new ObjectInputStream(Channels.newInputStream(channel))) {
return clazz.cast(ois.readObject());
} finally {
lock.release();
}
try (ObjectINputStream
}Context
StackExchange Code Review Q#76877, answer score: 3
Revisions (0)
No revisions yet.