Error "java.io.StreamCorruptedException: invalid stream header: 5B424037" - java

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.

Related

Java invalid stream header: 4C6F6361

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);

How to retrieve object from key value database into Map, then convert back to object in Java

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 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
}
}

java insert Blob as ByteArrayOutputStream get ClassCastException

I've to save a pdf file represented as a ByteArrayOutputStream into a Blob SQL field of a table, here's my code:
public boolean savePDF(int version, ByteArrayOutputStream baos) throws Exception{
boolean completed = false;
ConnectionManager conn = new ConnectionManager();
try {
PreparedStatement statement = conn.getConnection().prepareStatement(INSERT_PDF);
statement.setLong(1, version);
statement.setBlob(2, (Blob)baos);
statement.execute();
conn.commit();
completed = true;
} catch (SQLException e) {
conn.rollbackQuietly();
e.printStackTrace();
throw e;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally{
conn.close();
}
return completed;
}
But I get a java.lang.ClassCastException:
java.io.ByteArrayOutputStream cannot be cast to java.sql.Blob
How can I manage that? Thanks
There is a setBlob that takes an InputStream, so
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
statement.setBlob(2, bais);
You can't cast ByteArrayOutputStream to Blob. Try creating the Blob instance as below:
SerialBlob blob = new SerialBlob(baos.toByteArray());
and then
statement.setBlob(2, blob);

Serialise/Deserialise List<String>

I was to save an arraylist of strings into 1 column in the local database. I am having some problems doing this. Can somebody tell me where I am going wrong...
private String serializeArray(List<String> array) {
try {
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bytesOut);
oos.writeObject(array);
oos.flush();
oos.close();
return Base64.encodeToString(bytesOut.toByteArray(), Base64.NO_WRAP);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private ArrayList<String> deserializeArray(String string) {
Log.d("USERDAO", string);
try {
ByteArrayInputStream bytesIn = new ByteArrayInputStream(Base64.decode(string, Base64.NO_WRAP));
ObjectInputStream ois = new ObjectInputStream(bytesIn);
return (ArrayList<String>) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
I am getting a null pointer exception when returning the Arraylist on deserialise array. The serialiseArray method does return a string however I am not sure if it is correct.
When I run this in eclipse I get java.lang.ClassCastException at this line:
return (ArrayList<String>) ois.readObject();
the readObject() method is trying to return an Arrays$ArrayList (whatever that is) and your cast is causing it to break. If you change the cast and the return type of your deserialise to be List you'll find it all works.

Categories

Resources