I am trying to convert a ArrayList object to a byte string so it can be sent via sockets. When I run this code it converts to a string properly but when I try to convert it back I get the exception "java.io.StreamCorruptedException: invalid stream header: EFBFBDEF". Other answers I looked at on here didn't really help as I am using the matching ObjectOutputStream and ObjectInputStream. Sorry if there is a simple fix as I am new to working with stream objects.
try {
ArrayList<String> text = new ArrayList<>();
text.add("Hello World!");
String byteString = Utils.StringUtils.convertToByteString(text);
ArrayList<String> convertedSet = (ArrayList<String>) Utils.StringUtils.convertFromByteString(byteString);
VCS.getServiceManager().addConsoleLog(convertedSet.get(0));
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
public static String convertToByteString(Object object) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)) {
out.writeObject(object);
final byte[] byteArray = bos.toByteArray();
return new String(byteArray);
}
}
public static Object convertFromByteString(String byteString) throws IOException, ClassNotFoundException {
final byte[] bytes = byteString.getBytes();
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInput in = new ObjectInputStream(bis)) {
return in.readObject();
}
}
I figured it out. I had to use Base64 encoding. The conversion methods have to be changed to the following:
public static String convertToByteString(Object object) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)) {
out.writeObject(object);
final byte[] byteArray = bos.toByteArray();
return Base64.getEncoder().encodeToString(byteArray);
}
}
public static Object convertFromByteString(String byteString) throws IOException, ClassNotFoundException {
final byte[] bytes = Base64.getDecoder().decode(byteString);
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInput in = new ObjectInputStream(bis)) {
return in.readObject();
}
}
String is not a container for binary data. You need to pass around the original byte array, or hex- or base64-encode it.
Better still, serialize directly to the socket and get rid of this altogether.
Related
public class JavaApplication {
public static void main(String[] args) throws IOException{
URL u = new URL("https://www.javatpoint.com/java-string-valueof");
byte[]bytes= u.openStream().readAllBytes();
ObjectOutputStream output= new ObjectOutputStream(
new FileOutputStream("binary.dat"));
output.write(bytes);
output.close();
//Scanning the URL works just not the try and catch block
try{
ObjectInputStream input = new ObjectInputStream(new FileInputStream
("binary.dat"));
byte[]byte1= (byte[])input.readObject();
String any;
for(int i=0; i<byte1.length; i++){
any=String.valueOf(byte1[i]);
System.out.println(any);
}
input.close();
}
catch(Exception e){
System.out.println(e);}
}
}
I used a new byte array to read the object from file, use String.valueOf() to obtain the String value of the byte, then a for-loop to iterate the String. What am I doing wrong?
As the first commenter said, your main problem was not using writeObject. The only other problem is the way you turn the bytes into text. Your code will result in the 'ascii' code of the character being printed instead of the character itself. In fact you can simplify the output code as follows:
import java.io.*;
import java.net.*;
public class JavaApplication {
public static void main(String[] args) throws IOException {
URL u = new URL("https://www.javatpoint.com/java-string-valueof");
byte[] bytes = u.openStream().readAllBytes();
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("binary.dat"));
output.writeObject(bytes);
output.close();
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream("binary.dat"));
byte[] byte1 = (byte[]) input.readObject();
System.out.println(new String(byte1));
input.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
To solve your problem, I prefer you :
Add implementation of URLConnection for avoidance from Http Status 403 / Forbidden. Reference
use ByteArrayOutputStream to write the byte and save it into file using ObjectOutputStream
if you read with readObject() you must write with writeObject()
public class JavaApplication {
public static void main(String[] args) throws IOException, ClassNotFoundException {
URL u = new URL("https://www.javatpoint.com/java-string-valueof");
URLConnection uc = u.openConnection();
uc.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
try {
is = uc.getInputStream();
byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
int n;
while ((n = is.read(byteChunk)) > 0) {
baos.write(byteChunk, 0, n);
}
} catch (IOException e) {
System.err.printf("Failed while reading bytes from %s: %s", u.toExternalForm(), e.getMessage());
} finally {
if (is != null) {
is.close();
}
}
byte[] bytes = baos.toByteArray();
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("binary.dat"));
output.writeObject(bytes);
output.close();
//Scanning the URL works just not the try and catch block
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream("binary.dat"));
byte[] byte1 = (byte[]) input.readObject();
String any;
for (int i = 0; i < byte1.length; i++) {
any = String.valueOf(byte1[i]);
System.out.println(any);
}
input.close();
} catch (IOException e) {
System.out.println(e);
}
}
}
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 want to compute md5 of any Serilizable object, which is done by following function.
public static String getMd5Hash(Serializable object) {
try {
return getChecksum(object, "MD5");
} catch (Exception e) {
throw new RmsException("Exception while generating md5 hash", e);
}
}
public static String getMd5Hash(Serializable object) {
try {
return getChecksum(object, "MD5");
} catch (Exception e) {
throw new RuntimeException("Exception while generating md5 hash", e);
}
}
private static String getChecksum(Serializable object, String algorithm)
throws IOException, NoSuchAlgorithmException {
try (
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)
) {
oos.writeObject(object);
MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] theDigest = md.digest(baos.toByteArray());
return DatatypeConverter.printHexBinary(theDigest);
}
}
Test
#Test
public void getMd5Hash() {
String actual = CryptoUtils.getMd5Hash("water");
Assert.assertEquals("9460370bb0ca1c98a779b1bcc6861c2c", actual);
}
OP
Expected :9460370bb0ca1c98a779b1bcc6861c2c (actual md5 for string water)
Actual :37F7DBD142DABF05ACAA6759C4D9E96C (Why the diff?)
The ObjectOutputStream adds a header, so the Serializable you are passing does not actually represent "water" when you get the byte array. Print out baos.toString() to verify. You can either extend ObjectOutputStream and override the writeStreamHeader method, or call md.digest with the substring of the data, ie md.digest(baos.substring(7).getBytes()) (or something thereabouts). Once the actual data digested is "water", the hash will be correct.
As Terje says,
ObjectOutPutStream adds a header, you can verify that using
public static String getChecksum(Serializable object, String algorithm)
throws IOException, NoSuchAlgorithmException {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(object);
oos.flush();
MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(object.toString().getBytes());
byte[] theDigest = md.digest();
System.out.println("Without Object output stream="+DatatypeConverter.printHexBinary(theDigest));
md.reset();
System.out.println("object="+object+ " Written to ByteArray is="+baos.toString());
md.update(baos.toByteArray());
theDigest = md.digest();
return DatatypeConverter.printHexBinary(theDigest);
}
}
public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
System.out.println(getChecksum("water", "MD5"));
}
Instead of creating all ByteArrayOutputStream and ObjectOutputStream, you can simple use
md.update(object.toString().getBytes());
To write byte array to MessageDigest.
Thanks
I am trying to send vector object from UDP server to UDP client in Java.
Sending and Receiving string as an object after serializing has been achieved , but I am unable to send or receive vectors. Below is server ide code.
public class UDPReceive {
public UDPReceive() throws IOException {
try {
int port = Integer.parseInt("1233");
int allReceived=0;
String[] custData=new String[3];
DatagramSocket dsocket = new DatagramSocket(port);
byte[] buffer = new byte[2048];
for(;;) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
dsocket.receive(packet);
String msg = new String(buffer, 0, packet.getLength());
String msg2 = new String(packet.getData());
custData[allReceived]=msg;
allReceived++;
if(allReceived == 3){
System.out.println("All Data Received");
for(int i=0;i<3;i++){
System.out.println(custData[i]);
}
Vector rawData=getTransactions(custData[0],custData[1],custData[2]);
System.out.println("Vectot size "+ rawData.size());
byte[] sendData = new byte[1024];
sendData=(object[])rawData.toArray();
allReceived=0;
}/*if ends here */
}
}
catch (Exception e) {
System.err.println(e);
}
}
Here I want to send back "rawData" variable to client and receive it, and covert it to vector in client side. I tried using byte[] as well, but it didn't work
I suggest you serialize the Vector as an ObjectOutputStream and use ObjectInputStream to get the original Vector.
public static byte[] objectToBytes(Object o) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
return baos.toByteArray();
}
to reverse
public static <T> T bytesToObject(byte[] bytes) throws IOException, ClassNotFoundException {
return (T) new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject();
}
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();
}
}
}