将 ByteArray 转换为 String 到 ByteArray

convert ByteArray to String to ByteArray

I want to convert ByteArray to string and then convert the string to ByteArray,But while converting values changed. someone help to solve this problem.

person.proto:

syntax = "proto3";
  message Person{
    string name = 1;
    int32 age = 2;
  }

After sbt compile it gives case class Person (created by google protobuf while compiling)

我的主类:

val newPerson = Person(
      name = "John Cena",
      age = 44                        //output
    )
    println(newPerson.toByteArray)    //[B@50da041d
    val l = newPerson.toByteArray.toString  
    println(l)                        //[B@7709e969
    val l1 = l.getBytes
    println(l1)                      //[B@f44b405

why the values changed?? how to convert correctly??

[B@... 是 JVM 字节数组的 .toString returns 的格式,只是 [B(意思是“字节数组”)和 hex-string 这类似于数组所在的内存地址(我故意不称它为指针,但它很相似; hex-string 到内存地址的精确映射是 JVM-dependent 并且可以受正在使用的垃圾收集器等因素的影响)。重要的是,两个具有相同字节的不同数组将具有不同的 .toString。请注意,在某些地方(例如 REPL),Scala 会打印类似 Array(-127, 0, 0, 1) 的内容而不是调用 .toString:这可能会引起混淆。

似乎 toByteArray 每次调用时都会发出一个新数组。所以第一次调用newPerson.toByteArray的时候,会在50da041d对应的位置得到一个数组。第二次调用它时,您会在 7709e969 对应的位置得到一个具有相同内容的字节数组,并将字符串 [B@7709e969 保存到变量 l 中。然后,当您对该字符串调用 getBytes(将其保存在 l1 中)时,您会得到一个字节数组,它是字符串“[B@7709e969”在对应于 [=26= 的位置的编码].

所以在对应于 50da041d7709e969 的位置,你有两个不同的字节数组,它们恰好包含相同的元素(这些元素是 [=29= 的原型表示中的字节) ]).在对应于 f44b405 的位置,您有一个字节数组,其中字节编码(在某些字符集中,可能是 UTF-16?)[B@7709e969.

因为原型并不是真正的字符串,所以没有通用的方法来获取有用的字符串(取决于您所处理的有用的定义)。您可以尝试将 toByteArray 中的字节数组解释为具有给定字符编码的字符串,但不能保证任何给定的原型在任意字符编码中都有效。

纯 8 位的编码,如 ISO-8859-1 保证至少可以从字节数组中解码,但可能有 non-printable 或控制字符,因此不太可能有用:

val iso88591Representation = new String(newPerson.toByteArray, java.nio.charset.StandardCharsets.ISO_8859_1)

或者,您可能想要一种类似于 Scala REPL 将如何(有时)呈现它的表示:

"Array(" + newPerson.toByteArray.mkString(", ") + ")"