string java utf8编码_Java的String不能处理中文utf-8编码

Sequence File 文件格式支持文件分割,因此适合map-reduce做业。最近有一个项目,把kafka的protobuf数据写到hdfs,方便下游的离线做业作数据分析。java

在kafka中,protobuf序列化成了byte数组(message就是byte数组)。这个时候在linkedin的camus(linkedin开源的一个把kafka数据写到hdfs 的工具)中配置做业把kafka message以sequence file的格式写到hdfs。Sequence file的key是org.apache.hadoop.io.LongWritable,value是org.apache.hadoop.io.Text。apache

很顺利,咱们把数据写到了hdfs,而后我本身写一个pig udf去解析protobuf的数据。Pig自己有一个udf去读取sequencefile:org.apache.pig.piggybank.storage.SequenceFileLoader。由于存放的是Text,因此pig读取的时候就转成了chararray。而后我就遇到了以下的错误:数组

bad record, bad formatcom.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.工具

后来咱们花费了很长时间,甚至查看了protobuf的二进制,作了人工翻译,发现hdfs上的protobuf byte数组中多出了一些非法字符,这些字符不是utf-8的字符(由于咱们的protobuf中存放的是中文数据,utf-8编码)。怎么来的呢?oop

原来,咱们的protobuf中除了string字段外,还有一个int字段,这个字段是一个counter,记录着当前message的编号,是连续变化的。Protobuf在序列化的时候,这个字段作了简单的压缩,以二进制的形式存放在byte array中。而后,当camus把byte array数据转换成Text的时候(或者是pig把sequencefile数据转换成String的时候,还不知道具体是哪一个环节出的错),String内部默认定义存放的是utf-8的字符串,因此这个时候byte array中int字段并不符合utf-8编码(其实并非全部的都不是utf-8有效值,确实存在一部分int字段的值,是有效的utf-8编码),因而String对这些值作了转换,获得一些奇怪的utf-8编码值。这样,当咱们用protobuf parse这个String的byte array(这个byte array来自转换后的String的getBytes()返回的结果)时,就会遇到结构被破坏的错误。google

怎么办?编码

最后咱们找到了支持byte array的一个类:org.apache.hadoop.io.BytesWritable。这样,咱们就解决了这个问题。spa

后来,我本身作了实验,发现java中byte array转成String,再用getBytes()转回byte array,并不能彻底获得以前的byte array(有时候能够,有时候不能够,取决于byte array具体的值),二者并不等价。在中文字符处理的时候,这就会是个问题。翻译

之后对于中文处理,仍是要使用byte array,不要使用String或者Text。orm

Sequence File 文件格式支持文件分割,因此适合map-reduce做业。最近有一个项目,把kafka的protobuf数据写到hdfs,方便下游的离线做业作数据分析。java 在kafka中,protobuf序列化成了byte数组(message就是byte数组)。这个时候在linkedin的camus(linkedin开源的一个把kafka数据写到hdfs 的工具)中配置做业把kafka message以sequence file的格式写到hdfs。Sequence file的key是org.apache.hadoop.io.LongWritable,value是org.apache.hadoop.io.Text。apache 很顺利,咱们把数据写到了hdfs,而后我本身写一个pig udf去解析protobuf的数据。Pig自己有一个udf去读取sequencefile:org.apache.pig.piggybank.storage.SequenceFileLoader。由于存放的是Text,因此pig读取的时候就转成了chararray。而后我就遇到了以下的错误:数组 bad record, bad formatcom.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.工具 后来咱们花费了很长时间,甚至查看了protobuf的二进制,作了人工翻译,发现hdfs上的protobuf byte数组中多出了一些非法字符,这些字符不是utf-8的字符(由于咱们的protobuf中存放的是中文数据,utf-8编码)。怎么来的呢?oop 原来,咱们的protobuf中除了string字段外,还有一个int字段,这个字段是一个counter,记录着当前message的编号,是连续变化的。Protobuf在序列化的时候,这个字段作了简单的压缩,以二进制的形式存放在byte array中。而后,当camus把byte array数据转换成Text的时候(或者是pig把sequencefile数据转换成String的时候,还不知道具体是哪一个环节出的错),String内部默认定义存放的是utf-8的字符串,因此这个时候byte array中int字段并不符合utf-8编码(其实并非全部的都不是utf-8有效值,确实存在一部分int字段的值,是有效的utf-8编码),因而String对这些值作了转换,获得一些奇怪的utf-8编码值。这样,当咱们用protobuf parse这个String的byte array(这个byte array来自转换后的String的getBytes()返回的结果)时,就会遇到结构被破坏的错误。google 怎么办?编码 最后咱们找到了支持byte array的一个类:org.apache.hadoop.io.BytesWritable。这样,咱们就解决了这个问题。spa 后来,我本身作了实验,发现java中byte array转成String,再用getBytes()转回byte array,并不能彻底获得以前的byte array(有时候能够,有时候不能够,取决于byte array具体的值),二者并不等价。在中文字符处理的时候,这就会是个问题。翻译 之后对于中文处理,仍是要使用byte array,不要使用String或者Text。orm
经验分享 程序员 微信小程序 职场和发展