字节数组长度在变换前后变化

时间:2016-07-08 10:59:39

标签: java arrays string bytearray data-conversion

我需要通过互联网发送和接收大字节数组(http restful service)。

我能想到的最简单的方法是将字节数组转换为字符串。

我搜索了一下,发现了这篇文章Java Byte Array to String to Byte Array

我有以下代码来验证转换的准确性。

    System.out.println("message");
    System.out.println (message);

    String message = "Die Strahlengriffelgewächse stammen...";

    byte[] pack = Fbs.packExce(message);    
    System.out.println ("pack");
    System.out.println (pack);
    System.out.println ("packlenght:" + pack.length);

    String toString = new String(pack);
    System.out.println ("toString");
    System.out.println (toString);

    byte[] toBytes = toString.getBytes();
    System.out.println ("toBytes");
    System.out.println (toBytes);
    System.out.println ("toByteslength:" +toBytes.length);

“Fbs.packExce()”是一种获取大块字符串并生成大字节数组的方法。

我改变了消息的长度,检查并打印出字节数组的长度,然后转换为字符串并转换回来。

我得到了以下结果:

...
pack
[B@5680a178
packlenght:748
...
toBytes
[B@5fdef03a
toByteslength:750

----------------------

...
pack
[B@5680a178
packlenght:1016
...
toBytes
[B@5fdef03a
toByteslength:1018

我已经省略了“消息”,因为它太长了。

10次中的8次,我可以看到派生的字节数组(新的,称“toBytes”)比原始字节数组(“pack”)长 2个字节

我说的是10个中的8个,因为在衍生版和原版之间的长度相同的情况下,见下文

...
pack
[B@5680a178
packlenght:824
toString
...
toBytes
[B@5fdef03a
toByteslength:824       
...

我无法弄清楚确切的规则。

有没有人有任何想法?

还是有更好的方法将字节数组转换为字符串吗?

欢呼声

3 个答案:

答案 0 :(得分:6)

  

我能想到的最简单的方法是将字节数组转换为字符串。

最简单的方法是错误的方式。对于大多数字符编码,将任意字节序列转换为文本可能是有损的。

更好(即更强大)的方法是使用Base64编码。请阅读Base64类及其相关编码和解码器类的javadoc

如果您坚持尝试使用new String(byte[])等转换任意字节顶部字符并返回:

  • 请确保选择字符编码,其中字节为>字符 - >字节转换顺序不是有损的。 (LATIN-1将起作用)

  • 不要依赖当前执行平台的编码/解码字符集的默认字符编码。

  • 在客户端/服务器系统中,客户端和服务器必须使用相同的编码。

答案 1 :(得分:2)

  

我需要通过互联网发送和接收大字节数组(http   宁静的服务)。

     

我能想到的最简单的方法是将字节数组转换为   字符串。

如果这都是关于使用jaxrs发送/接收字节数组的话,那么每个jaxrs实现都完全能够传输byte[]。见specification,第4.2.4节。

答案 2 :(得分:1)

根据Stephen C的建议,我转向 Base64基本模式:

以下是我目前的完整验证码:

    String message = "Die Strahlengriffelgewächse stammen ... ...
    System.out.println("message");
    System.out.println (message);

    byte[] pack = Fbs.packExce(message);    
    System.out.println ("pack");
    System.out.println (pack);
    System.out.println ("packlenght:" + pack.length);


    String toString = Base64.getEncoder().encodeToString(pack);
    System.out.println ("toString");
    System.out.println (toString);


    byte[] toBytes = Base64.getDecoder().decode(toString);
    System.out.println ("toBytes");
    System.out.println (toBytes);
    System.out.println ("toByteslength:" +toBytes.length);


    String toBytesExtraction = extractExce(toBytes);
    System.out.println ("toBytesExtraction");
    System.out.println (toBytesExtraction);

    String extraction = extractExce(pack);
    System.out.println ("extraction");
    System.out.println (extraction);


public static byte[] packExce(String text){

    FlatBufferBuilder builder = new FlatBufferBuilder(0);

    int textOffset = builder.createString(text);

    Exce.startExce(builder);
    Exce.addText(builder, textOffset);
    int exce = Exce.endExce(builder);

    Bucket.startBucket(builder);
    Bucket.addContentType(builder, Post.Exce);
    Bucket.addContent(builder, exce);       
    int buck = Bucket.endBucket(builder);

    builder.finish(buck);

    return builder.sizedByteArray();
    //ByteBuffer buf = builder.dataBuffer();
    //return buf;
    //return Base64.getMimeEncoder().encodeToString(buf.array());
}
private String extractExce(byte[] bucket ){

    String message = null;

    ByteBuffer buf = ByteBuffer.wrap(bucket);
    Bucket cont = Bucket.getRootAsBucket(buf); 
    System.out.println (cont.contentType());
    if (cont.contentType() == Post.Exce){
        message = ((Exce)cont.content(new Exce())).text();

    }
   return message; 
}

这似乎符合我的目的:

...
pack
[B@5680a178
packlenght:2020
...
toBytes
[B@5fdef03a
toByteslength:2020
'''
----------------------

...
pack
[B@5680a178
packlenght:1872
...

toBytes
[B@5fdef03a
toByteslength:1872
...

分别从“toBytes”和“pack”两次提取,忠实地恢复原来的“消息”

String toBytesExtraction = extractExce(toBytes);
String extraction = extractExce(pack);

事实上,我没有提到的是我原来的实现是 base64 mime 。我的起点是ByteBuffer然后(我的当前是byte [])。

以下是我感兴趣的代码片段。

编码器

...
ByteBuffer buf = builder.dataBuffer();
return Base64.getMimeEncoder().encodeToString(buf.array());

解码器

ByteBuffer buf = ByteBuffer.wrap(Base64.getMimeDecoder().decode(bucket));

我的猜测是问题可能来自base64.mime。

因为我的故障位置的第一步是删除base64.mime,并直接使用ByteBuffer。这是成功的......

好吧,我有点徘徊。

回到主题,我仍然不知道转换为“new String(byte [])和”String.getBytes()“之前和之后的字节数组的”2字节变化“......

欢呼声