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

byte array length varies before and after transformation

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

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

我四处搜索,找到了这个 post 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

我省略了 "message" 因为它太长了。

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

我说的是10个中的8个,因为也有派生和原始长度相同的情况,见下文

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

我想不出确切的规则。

有人知道吗?

或者是否有更好的方法将字节数组与字符串相互转换?

干杯

the simplest way I can think of is to convert the byte array into string.

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

更好(即更健壮)的方法是使用 Base64 编码。阅读 javadoc Base64 class 及其依赖的编码和解码器 classes。


如果您坚持尝试使用 new String(byte[]) 等方法将任意字节的首位字符转换回来:

  • 请确保您选择的字符编码的字节 -> 字符 -> 字节转换序列无损。 (LATIN-1 可以)

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

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

I have a need to send and receive large byte array over internet(http restful service).

the simplest way I can think of is to convert the byte array into string.

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

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

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

    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"中提取,忠实地还原了原来的"message"

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[]) and "String.getBytes()转换前后的“2字节变化”我还是一头雾水”...

干杯