byte[]与String转换引起的protobuf反序列化抛异常问题
2017-03-23 15:42
1156 查看
使用protobuf时,将string写入ssdb然后再读出来反序列化protobuf message的时候报错:
代码如下:
很诡异,只是把数据写入再读出来怎么会抛
加个日志定位,把写入前后的字符串长度打印出来:
执行结果:
纳尼,前后的长度居然不一样!!!!
通过各种折腾发现是string和byte转换的问题,因为protobuf序列化后是二进制的数据流,不能转换成string类型,String类型是带编码的,如UTF-8
所以一个保存二进制数据的byte[]转为string,再转回byte[]就会和原来不一样。
参考:
- http://stackoverflow.com/questions/16270994/difference-between-string-length-and-string-getbytes-length
- http://blog.csdn.net/hjxgood/article/details/20057989
com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either than the input has been truncated or that an embedded message misreported its own length. at com.google.protobuf.InvalidProtocolBufferException.truncatedMessage(InvalidProtocolBufferException.java:70) at com.google.protobuf.CodedInputStream.readRawBytes(CodedInputStream.java:789) at com.google.protobuf.CodedInputStream.readBytes(CodedInputStream.java:329) at com.google.protobuf.UnknownFieldSet$Builder.mergeFieldFrom(UnknownFieldSet.java:484) at com.google.protobuf.UnknownFieldSet$Builder.mergeFrom(UnknownFieldSet.java:461) at com.google.protobuf.UnknownFieldSet$Builder.mergeFrom(UnknownFieldSet.java:579) at com.google.protobuf.UnknownFieldSet$Builder.mergeFrom(UnknownFieldSet.java:280) at com.google.protobuf.CodedInputStream.readGroup(CodedInputStream.java:240) at com.google.protobuf.UnknownFieldSet$Builder.mergeFieldFrom(UnknownFieldSet.java:488) at com.google.protobuf.GeneratedMessage.parseUnknownField(GeneratedMessage.java:193)
代码如下:
Msg.Builder msg1 = Msg.newBuilder(); //set value msg1.setId(11); byte[] data = msg1.build().toByteArray(); //写入ssdb ssdb.set(key,data); //立刻get出来 String str = ssdb.get(key); Msg.Builder msg2 = Msg.newBuilder(); try { msg2.mergeFrom(str.getBytes()); } catch (InvalidProtocolBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); return; } logger.info("msg===={}",msg2);
很诡异,只是把数据写入再读出来怎么会抛
InvalidProtocolBufferException异常。。。。
加个日志定位,把写入前后的字符串长度打印出来:
Msg.Builder msg1 = Msg.newBuilder(); //set value msg1.setId(11); byte[] data = msg1.build().toByteArray(); //写入前的字符串长度 System.out.println("==============before length="+data.length); //写入ssdb ssdb.set(key,data); //立刻get出来 String str = ssdb.get(key); //读出来的字符串长度 System.out.println("==============after length="+str.length()); Msg.Builder msg2 = Msg.newBuilder(); try { msg2.mergeFrom(str.getBytes()); } catch (InvalidProtocolBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); return; } logger.info("msg===={}",msg2);
执行结果:
==============before length=9977 ==============after length=9963
纳尼,前后的长度居然不一样!!!!
通过各种折腾发现是string和byte转换的问题,因为protobuf序列化后是二进制的数据流,不能转换成string类型,String类型是带编码的,如UTF-8
所以一个保存二进制数据的byte[]转为string,再转回byte[]就会和原来不一样。
解决办法1:使用iso8859-1编码
public static void testByte2String() { byte bytes[] = new byte[] { 50, 0, -1, 28, -24 }; String string = new String(bytes); byte[] ret = string.getBytes(); String isoString; byte[] isoret = null; try { isoString = new String(bytes, "ISO-8859-1"); isoret = isoString.getBytes("ISO-8859-1"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } System.out.println(System.getProperty("file.encoding")); System.out.println(ret); System.out.println(isoret); }
解决办法2:使用base64编码传输
对于二进制数据最好的办法是采用base64编码成可打印字符串进行传输参考:
- http://stackoverflow.com/questions/16270994/difference-between-string-length-and-string-getbytes-length
- http://blog.csdn.net/hjxgood/article/details/20057989
相关文章推荐
- C#中有关string和byte[]转换的问题
- String与Byte数组转换----EOFException问题
- C#中有关string和byte[]转换的问题
- byte[]、String转换中文编码问题
- java中byte[]转换成String类型的问题
- WCF中因序列化问题引起的异常和错误。
- delphi pchar char byte string转换问题
- delphi pchar char byte string转换问题
- String和byte[]互相转换的问题
- java中byte[]转换成String类型的问题
- C# char和byte 以及string之间的转换问题
- C#中有关string和byte[]转换的问题
- JAVA里面关于byte数组和String之间的转换问题
- C#中有关string和byte[]转换的问题
- VB 字节数组和字符串的转换问题 (StringByte)
- 问题1:java中没有实现这种“byte a = 0xB2 --> String b = “B2””转换的简单实现需要自己实现。 答:自己编写的转换函数,思路将byte的高低4位分开,分别转换为对应的字符然后合成返回的字符串。 java 代码 1.
- JAVA里面关于byte数组和String之间的转换问题
- protobuf Message的序列化和反序列化string类型
- JAVA里面关于byte数组和String之间的转换问题
- VB 字节数组和字符串的转换问题 (String<>Byte)