Java serialize and immediately deserialize gives error [duplicate] - java

This question already has answers here:
How to binary (de)serialize object into/form string?
(2 answers)
Closed 5 years ago.
Object before = "";
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(os);
oo.writeObject(before);
oo.close();
String serialized = os.toString("UTF-8");
ByteArrayInputStream is = new ByteArrayInputStream(serialized.getBytes("UTF-8"));
try(ObjectInputStream io = new ObjectInputStream(is)) {
Object after = io.readObject();
System.err.println("Object deserialization successful.");
} catch (Exception e) {
System.err.println("Object deserialization error.");
System.err.println("Type being serialized: " + before.getClass());
System.err.println("Serialization as bytes: " + Arrays.toString(serialized.getBytes("UTF-8")));
e.printStackTrace();
}
So I've got a bit of code I'm working with that's supposed to serialize an object to a java.lang.String and deserialize it later. I'm using object streams to do the object writing/reading and byte array streams to do the string handling. But when I try to construct an ObjectInputStream around the serialized object, I get a StreamCorruptedException, claiming there's an "invalid stream header".
The code sample above is the most basic piece of code I could find that reproduces my issue (and it's pretty simple!). As far as I can tell, I'm doing everything perfectly symmetrically:
Make an ObjectOutputStream around a ByteArrayOutputStream
Write a (simple!) object to the OOS
Get a UTF-8 String from the BAOS
Make an ObjectInputStream around a ByteArrayInputStream around that String's UTF-8 bytes
Read an object from the OIS
But at step 4, during ObjectInputStream's constructor the program crashes with a StreamCorruptedException. I'm extremely confused by that, given that the bytes were literally just produced by an ObjectOutputStream!

Don't convert the byte[] to and from a String, that is going to interpret special (wide) characters. Instead, just use the bytes from the ByteArrayOutputStream directly. Like,
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());

Related

How can I create a truststore from a base64 encoded String?

I have a String that is encoded in base64, I need to take this string, decode it and create a truststore file, but when I do that, the final file is not valid. Here is my code:
public static void buildFile() {
String exampleofencoded = "asdfasdfasdfadfa";
File file = new File("folder/file.jks");
try (FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
DataOutputStream dos = new DataOutputStream(bos))
{
Base64.Decoder decoder = Base64.getDecoder();
String decodedString =new String(decoder.decode(exampleofencoded).getBytes());
dos.writeBytes(decodedString);
}
catch (IOException e) {
System.out.println("Error creating file");
}
catch(NullPointerException e) {
System.out.println(e.getMessage();
}
}
The problem is two-fold.
You're converting a byte[] array to String, which is a lossy operation for actual binary data for most character sets (except maybe iso-8859-1).
You're using DataOutputStream, which is not a generic output stream, but intended for a specific serialization format of primitive types. And specifically its writeBytes method comes with an important caveat ("Each character in the string is written out, in sequence, by discarding its high eight bits."), which is one more reason why only using iso-8859-1 will likely work.
Instead, write the byte array directly to the file
public static void buildFile() {
String exampleofencoded = "asdfasdfasdfadfa";
File file = new File("folder/file.jks");
try (FileOutputStream fos = Files.newOutputStream(file.toPath()) {
Base64.Decoder decoder = Base64.getDecoder();
byte[] decodedbytes = decoder.decode(exampleofencoded);
fos.write(decodedbytes);
} catch (IOException e) {
System.out.println("Error creating file");
}
}
As an aside, you shouldn't catch NullPointerException in your code, it is almost always a problem that can be prevented by careful programming and/or validation of inputs. I would usually also advise against catch the IOException here and only printing it. It is probably better to propagate that exception as well, and let the caller handle it.

How can we make an object serializable in java manually without implementing Serializable interface? [duplicate]

This question already has answers here:
Java: How to make this Serializable?
(3 answers)
Closed 5 years ago.
Serialization is defined as the converting and object to the byte array. Here, I am able to convert
the object to the byte array but still while storing the byte array(of given object) to the file, i am getting exception of object is not serializable. could anyone please explain me on it. Thanks!
The way i am using to convert the object to byte array is:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(**yourObject**);
out.flush();
byte[] yourBytes = bos.toByteArray();
...
} finally {
try {
bos.close();
} catch (IOException ex) {
// ignore close exception
}
}
In order to make an object serializable you have to make it implement the Serializable interface

Turning an InputStream into BigInteger [duplicate]

This question already has answers here:
How can I quickly load a large txt file into BigInteger?
(3 answers)
Closed 5 years ago.
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// Load file with 17 million digit long number
BufferedReader Br = new BufferedReader (new FileReader("test2.txt"));
String Line = Br.readLine();
try {
// create a new file with an ObjectOutputStream
FileOutputStream out = new FileOutputStream("test.txt");
ObjectOutputStream oout = new ObjectOutputStream(out);
// write the number into a new file
oout.writeObject(Line);
// close the stream
oout.close();
// create an ObjectInputStream for the new file
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.txt"));
// convert new file into a BigInteger
BigInteger Big = (BigInteger) ois.readObject();
} catch (Exception ex) {
ex.printStackTrace();
}
}
This is a program I made for learning how to use Input/OutputStream. Everything works except that I get an error when trying to turn my file into a BigInteger.
java.lang.String cannot be cast to java.math.BigInteger
at ReadOutPutStream.main
I'm new to this so I'm probably making a simple error, what am I doing wrong?
You wrote a string to the file with
oout.writeObject(Line);
Therefore when you read an object from the stream it will also be a String. You can't cast a String to a BigInteger so you get an exception. I know form your earlier question that you want to serialize the BigInteger to save time when deserializing from the filesystem, so to fix your specific problem you should write a BigInteger to the stream instead of a string:
oout.writeObject(new BigInteger(Line));

FileInputStream.available() returns bytes but ObjectInputStream.available() returns 0

I ran into a weird problem which I don't seem to understand.
I'm making a program which reads data from a file. But when I do read data, I immediately receive an EOFException.
So I checked with .available() if the file was empty or not. And I got a weird result. The FileInputStream said that the file was filled (249 bytes), but the ObjectInputStream said that the file is empty (or can't be read).
EOFException at: "int signatureSize = ois.readInt();"
FileInputStream fin = new FileInputStream("input(signedbyLK).ext");
System.out.println("fin available: " + fin.available());
ObjectInputStream ois = new ObjectInputStream(fin);
System.out.println("ois avaiable: " + ois.available());
int signatureSize = ois.readInt();
byte[] sigBytes = (byte[]) ois.readObject();
String text = (String) ois.readObject();
ois.close();
EDIT: I'm adding content to the file like this:
File newFile = new File("input(signedbyLK).ext");
newFile.createNewFile();
System.out.println("Succesfully created new file: " + newFile.getName());
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(newFile));
oos.writeObject(sigBytes.length);
oos.writeObject(sigBytes);
oos.writeObject(readInput());
oos.close();
Here is what the javadoc says
Any attempt to read object data which exceeds the boundaries of the
custom data written by the corresponding writeObject method will cause
an OptionalDataException to be thrown with an eof field value of true.
Non-object reads which exceed the end of the allotted data will
reflect the end of data in the same way that they would indicate the
end of the stream: bytewise reads will return -1 as the byte read or
number of bytes read, and primitive reads will throw EOFExceptions. If
there is no corresponding writeObject method, then the end of default
serialized data marks the end of the allotted data.
Also, you need to read the object input stream in the same order as when you serialized it

collection of objects to bytes format and then vice versa in java

I have a collection of objects which i need to store in byte format and then afterwards i have to convert the data which in bytes back into collection of objects.I need the answer in java.
For eg I have an array of objects(any type) then i have to convert this array to byte array in java and then vice versa.
Please if possible suggest me the collection to use and the methods which support it.
Assuming that Foo implements Serializable, just do
List<Foo> list = createItSomehow();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
try {
oos.writeObject(list);
} finally {
oos.close();
}
byte[] bytes = baos.toByteArray();
// ...
And the other way round:
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
List<Foo> list = null;
try {
list = (List<Foo>) ois.readObject();
} finally {
ois.close();
}
// ...
Instead of ByteArrayOutputStream and ByteArrayInputStream you can of course also supply FileOutputStream and FileInputStream respectively to write/read it to/from file.
See also:
The Java Tutorials - Essential Classes - Basic I/O - Object Streams

Categories