java 如何将对象二进制(反)序列化为/形成字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13568248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to binary (de)serialize object into/form string?
提问by LunaVulpo
I need serialize objects into String and deserialize.
我需要将对象序列化为 String 并反序列化。
I readed sugestion on stackoverflow and make this code:
我在stackoverflow上阅读了sugestion并制作了这段代码:
class Data implements Serializable {
int x = 5;
int y = 3;
}
public class Test {
public static void main(String[] args) {
Data data = new Data();
String out;
try {
// zapis
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(data);
out = new String(baos.toByteArray());
System.out.println(out);
// odczyt.==========================================
ByteArrayInputStream bais = new ByteArrayInputStream(out.getBytes());
ObjectInputStream ois = new ObjectInputStream(bais);
Data d = (Data) ois.readObject();
System.out.println("d.x = " + d.x);
System.out.println("d.y = " + d.y);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
but I get error:
但我收到错误:
java.io.StreamCorruptedException: invalid stream header: EFBFBDEF
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:801)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:298)
at p.Test.main(Test.java:37)
Why? I expected: d.x = 5 d.y = 3
为什么?我预期:dx = 5 dy = 3
how to do in good way? Ah. I don't want to write this object in file. I have to have it in string format.
怎么做才好?啊。我不想在文件中写入这个对象。我必须以字符串格式使用它。
采纳答案by Aleksander Blomsk?ld
UseByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
instead of
ByteArrayInputStream bais = new ByteArrayInputStream(out.getBytes());
, since the String conversion corrupts the data (because of the encoding).
使用ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
代替
ByteArrayInputStream bais = new ByteArrayInputStream(out.getBytes());
,因为字符串转换会破坏数据(由于编码)。
If you really need to store the result in a String, you need a safe way to store arbitrary bytes in a String. One way of doing that is to us Base64-encoding.
如果您确实需要将结果存储在字符串中,则需要一种安全的方法将任意字节存储在字符串中。一种方法是对我们进行 Base64 编码。
A totally different approach would have been to not use the standard Java serialization for this class, but create your own Data to/from String converter.
一种完全不同的方法是不对此类使用标准的 Java 序列化,而是创建您自己的数据到/从字符串转换器。
回答by ngrislain
It is not entirely true to say that conversion to string corrupts the data. Conversion to "UTF-8" does because it is not bijective (some characters are 2 bytes but not all 2 bytes sequences are allowed as character sequences), while "ISO-8859-1" is bijective (1 character of a String is a byte and vice-versa).
说转换为字符串会损坏数据并不完全正确。转换为“UTF-8”是因为它不是双射的(某些字符是 2 个字节,但并非所有 2 个字节的序列都允许作为字符序列),而“ISO-8859-1”是双射的(字符串的 1 个字符是字节,反之亦然)。
Base64 encoding is not very space-efficient compared to this.
与此相比,Base64 编码不是很节省空间。
This is why I would recommend:
这就是为什么我会推荐:
/**
* Serialize any object
* @param obj
* @return
*/
public static String serialize(Object obj) {
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(obj);
so.flush();
// This encoding induces a bijection between byte[] and String (unlike UTF-8)
return bo.toString("ISO-8859-1");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Deserialize any object
* @param str
* @param cls
* @return
*/
public static <T> T deserialize(String str, Class<T> cls) {
// deserialize the object
try {
// This encoding induces a bijection between byte[] and String (unlike UTF-8)
byte b[] = str.getBytes("ISO-8859-1");
ByteArrayInputStream bi = new ByteArrayInputStream(b);
ObjectInputStream si = new ObjectInputStream(bi);
return cls.cast(si.readObject());
} catch (Exception e) {
e.printStackTrace();
}
}