When I try to convert the data of a blob into an object, errors occur. What am I doing wrong?
public static Object readObject(Blob blob) throws Exception {
Object obj = null;
ObjectInputStream objIn = null;
ByteArrayInputStream bIn = null;
try {
Blob b = blob;
bIn = new ByteArrayInputStream(b.getBytes(1, (int) b.length()));
objIn = new ObjectInputStream(bIn);
obj = (Object) objIn.readObject();
} finally {
try {
objIn.close();
bIn.close();
}catch (Exception e){}
}
return obj;
}
Error:
java.io.StreamCorruptedException: invalid stream header: 4C6F6361
Line that throws the error:
objIn = new ObjectInputStream(bIn);
Related
I am storing an object as a value in LevelDB. Both key and value must be in bytes for LevelDB.
I am receiving an object via a socket and casting it to MyObject:
MyObject myObject = (MyObject) (objectInput.readObject());
Then I am serialising my object when storing the value in LevelDB:
myLevelDb().put(bytes((publicKey)), Serializer.serialize(myObject));
The serializer code is as follows:
public static byte[] serialize(Object object) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(object);
out.flush();
byte[] yourBytes = bos.toByteArray();
return yourBytes;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException ex) {
// ignore close exception
}
} return null;
}
Then I am trying to iterate through the LevelDB and store each object into a Map. Here is where I am trying to deserialize the bytes back into MyObject and save them to Map:
private void iterateBytes() {
DBIterator iterator = myLevelDb().iterator();
while (iterator.hasNext()) {
Map.Entry<byte[], byte[]> next = iterator.next();
String keyString = new String(next.getKey());
MyObject myObject = (MyObject) Serializer.deserialize(next.getValue());
Map<String, MyObject> myMap = new HashMap<>();
myMap().put(keyString, myObject);
}
}
However, Java will not let me cast the deserialized bytes back to MyObject after it has been deserialized using the following code:
public static Object deserialize(byte[] bytes) {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInput in = null;
try {
in = new ObjectInputStream(bis);
Object o = in.readObject();
return o;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
// ignore close exception
}
} return null;
}
I don't understand why I cannot convert the object back from a byte[] when I have followed the exact same method of serializing and deserializing. MyObject implements Serializable and the SUID is correct, as it works on API calls between devices. I just cannot add it to a Map as the original object, nor will Java let me cast it.
This is the line where an error is thrown, no matter where I try to cast it back to myObject:
MyObject myObject = (MyObject) Serializer.deserialize(next.getValue());
Error:
class java.lang.String cannot be cast to class myPackage.MyObject (java.lang.String is in module java.base of loader 'bootstrap';
This was solved by casting the generic Object object to MyObject (user defined class object) at serialization and also casting it at deserialization.
Here is the code at serialization:
public static byte[] serialize(MyObject myObject) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(myObject);
out.flush();
byte[] yourBytes = bos.toByteArray();
return yourBytes;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException ex) {
// ignore close exception
}
} return null;
}
And here is the code for deserializaion.
public static MyObject deserializeNodeClient(byte[] bytes) {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInput in = null;
try {
in = new ObjectInputStream(bis);
MyObject myObject = (MyObject) in.readObject();
return myObject;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
// ignore close exception
}
} return null;
}
So although the original OP code works fine is some cases, the original object cannot be derived by using a generic Object object serialization, then casting the output.
How to convert java POJO class into a byte array as I wanted to save the object into a gz file in S3
I get this exception Caused by: java.io.NotSerializableException
public byte[] compressData(User user) throws IOException {
byte[] data;
try(ByteArrayOutputStream byteStream = new ByteArrayOutputStream();) {
try (GZIPOutputStream objectOutputStream = new GZIPOutputStream(byteStream);) {
try (ObjectOutputStream zipStream = new ObjectOutputStream(objectOutputStream);) {
zipStream.writeObject(user);
}
data = byteStream.toByteArray();
} catch (Exception e) {
throw new IOException(e);
}
}
return data;
}
you can use SerializationUtils.java from ApacheCommonslang dependency.
For serialization
byte[] data = SerializationUtils.serialize(**POJO_Object_Name**);
for deserialize:
POJO_Class_Name **POJO_Object_Name** = SerializationUtils.deserialize(data)
private final Type userType = new TypeToken<User>() {}.getType();
private final Gson = new Gson();
compressData(gson.toJson(user,userType));
public static byte[] compressData(String user) throws IOException {
byte[] data;
try(ByteArrayOutputStream byteStream = new ByteArrayOutputStream();){
try(GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);){
zipStream.write(data.getBytes(StandardCharsets.UTF_8));
}
data = byteStream.toByteArray();
} catch(Exception e) {
throw new IOException("Error while compressing the User record ", e);
}
return data;
}
I have a FootballPlayer entity class which implements the Serializable interface. I am saving the objects from this class to a database table using the longblob type.
That is working fine, but when retrieving the objects from the database, I am getting a StreamCorruptedException.
Here is my code:
public FootballPlayer searchFBPlayer(String id){
try {
String sql = "SELECT * FROM player";
ResultSet rs = DBConnection.getData(sql);
// search for player
while (rs.next()) {
ByteArrayInputStream bais = new ByteArrayInputStream(rs.getBytes("fbPlayer"));
//test
if(bais==null) System.out.println("Null BAIS");
else System.out.println("No Null BAIS");
//test
FootballPlayer fbp = (FootballPlayer) toObject(bais);
if(fbp.getPlayerID().equals(id))
return fbp;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
private Object toObject(ByteArrayInputStream arr){
ObjectInputStream ins;
try{
ins = new ObjectInputStream(arr);
return ins.readObject();
}
catch(Exception e){
e.printStackTrace();
}
return null;
}
Code to save:
public int addFootballPlayer(FootballPlayer player){
byte[] data=toByte(player);
String sql="INSERT INTO footballplayer(footballPlayer) VALUES('"+data+"')";
return DBConnection.setData(sql);
}
private byte[] toByte(Object obj){
try{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
oos.close();
bos.close();
byte[] data = bos.toByteArray();
return data;
}catch(Exception e){
e.printStackTrace();
}
return null;
}
Here is my stack trace:
java.io.StreamCorruptedException: invalid stream header: 5B424037
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at com.league.database.DBAccess.toObject(DBAccess.java:67)
at com.league.database.DBAccess.searchPlayer(DBAccess.java:34)
at com.league.main.Test.main(Test.java:20)
I don't have any kind of networking in my code such as sockets. What am I doing wrong, and how can I fix this issue?
The problem is the point where you create the SQL. You should be using a PreparedStatement at this point, and passing the data as an argument: not converting the data to String.
I have this code from DZone(http://www.dzone.com/links/r/java_custom_serialization_example.html) that serialize/deserialize Java object from/to file.
final class Hello implements Serializable
{
int x = 10;
int y = 20;
public int getX()
{
return x;
}
public int getY()
{
return y;
}
}
public class SerializedComTest {
#AfterClass
public static void tearDownAfterClass() throws Exception {
}
#Test
public void testFile() throws IOException, ClassNotFoundException {
Hello h = new Hello();
FileOutputStream bs = new FileOutputStream("hello.txt"); // ("testfile");
ObjectOutputStream out = new ObjectOutputStream(bs);
out.writeObject(h);
out.flush();
out.close();
Hello h2;
FileInputStream fis = new FileInputStream("hello.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
h2 = (Hello) ois.readObject();
assertTrue(10 == h2.getX());
assertTrue(20 == h2.getY());
}
}
How can I transfer serialized object using Java socket? And also how can I store the serialized/deserialized object to/from a byte array.
This is the code for serialization to/from byte array. I got hints from - Java Serializable Object to Byte Array
#Test
public void testByteArray() throws IOException, ClassNotFoundException, InterruptedException {
Hello h = new Hello();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(h);
byte b[] = bos.toByteArray();
out.close();
bos.close();
Hello h2;
ByteArrayInputStream bis = new ByteArrayInputStream(b);
ObjectInput in = new ObjectInputStream(bis);
h2 = (Hello) in.readObject();
assertTrue(10 == h2.getX());
assertTrue(20 == h2.getY());
}
How can I transfer serialized object using Java socket?
Wrap its output stream in an ObjectOutputStream.
And also how can I store the serialized/deserialized object to/from a string.
You don't. Serialized objects are binary, and should be stored in byte arrays. A deserialized object is the object itself, not a string.
You don't need those readObject() and writeObject() methods. They don't do anything that wouldn't happen by default.
Like you wrapped your filestream with the objectstream class, you do the same with sockets. You should not "store" a serialized object to a string.
This is the code that works, and I got the hint from http://cyberasylum.janithw.com/object-serialization-over-networks-in-java/.
#Test(timeout = 2000)
public void testStream() throws IOException, ClassNotFoundException, InterruptedException {
PingerThread pinger = new PingerThread(9092);
pinger.start();
String serverAddress = "localhost";
Socket s;
PrintWriter output;
BufferedReader input;
try {
// Client
s = new Socket(serverAddress, 9092);
}
catch (IOException e)
{
// when error, try again
Thread.sleep(500);
s = new Socket(serverAddress, 9092);
}
// send the object over the network
Hello h = new Hello();
ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
out.writeObject(h);
out.flush();
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
System.out.println("2");
Hello h2;
h2 = (Hello) in.readObject();
assertTrue(10 == h2.getX());
assertTrue(20 == h2.getY());
}
private class PingerThread extends Thread {
public int portNumber;
public PingerThread(int portNumber) {
super();
this.portNumber = portNumber;
}
#Override
public void run() {
try {
ServerSocket listener = new ServerSocket(this.portNumber);
Socket socket = listener.accept();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
Hello h;
while((h = (Hello) in.readObject()) != null) {
System.out.println("1");
//h = (Hello) in.readObject();
System.out.println(h.getX());
System.out.println(h.getY());
out.writeObject(h);
out.flush();
}
System.out.println("OUT");
socket.close();
listener.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
I want my app to store multiple objects locally for later use.
Now, my problem is that I know how to load an object from an ObjectInputStream by taking the entire file(federations.dat). Is there a way for me to load say object WHERE id = N from "federations.dat" ? Or do I have to create separate files for each object?
This is my load method:
public static Object load(Context ctx, String filename) throws FileNotFoundException
{
Object loadedObj = null;
InputStream instream = null;
instream = ctx.openFileInput(filename);
try {
ObjectInputStream ois = new ObjectInputStream(instream);
loadedObj = ois.readObject();
return loadedObj;
} catch (StreamCorruptedException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
Any suggestions come to mind ?
You can use it like this..
ArrayList<Object> arrayList = new ArrayList<Object>();
Object obj = null;
while ((obj = ois.readObject()) != null) {
arrayList.add(obj);
}
You can return an ArrayList on your method.
return arrayList;
Edit:
Full code would be like this..
public static ArrayList<Object> load(Context ctx, String filename)
{
InputStream fis = null;
ObjectInputStream ois = null;
ArrayList<Object> arrayList = new ArrayList<Object>();
Object loadedObj = null;
try {
fis = ctx.openFileInput(filename);
ois = new ObjectInputStream(fis);
while ((loadedObj = ois.readObject()) != null) {
arrayList.add(loadedObj);
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (null != ois) ois.close();
if (null != fis) fis.close();
}
return arrayList;
}
Hope it helps..
An extention to #Jan 's code, fixing the problem of keeping ois open if an exception is thrown, along with some minor issues.
public static ArrayList<Object> load(Context ctx, String filename) throws FileNotFoundException {
InputStream instream = ctx.openFileInput(filename);
ArrayList<Object> objects = new ArrayList<Object>();
try {
ObjectInputStream ois = new ObjectInputStream(instream);
try{
Object loadedObj = null;
while ((loadedObj = ois.readObject()) != null) {
objects.add(loadedObj);
}
return objects;
}finally{
ois.close();
}
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}