Vas*_*Vel 0 scala protocol-buffers playframework scalapb
我想将 ByteArray 转换为字符串,然后将字符串转换为 ByteArray,但是在转换时值发生了变化。有人帮助解决这个问题。
人.proto:
syntax = "proto3";
message Person{
string name = 1;
int32 age = 2;
}
Run Code Online (Sandbox Code Playgroud)
sbt 编译后,它给出案例类 Person (编译时由 google protobuf 创建)
我的主课:
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
Run Code Online (Sandbox Code Playgroud)
为什么价值观改变了?如何正确转换??
[B@...是 JVM 字节数组返回的格式.toString,只是[B(这意味着“字节数组”)和一个十六进制字符串,类似于数组所在的内存地址(我故意不称其为指针,但它是类似;该十六进制字符串到内存地址的精确映射取决于 JVM,并且可能受到正在使用的垃圾收集器等因素的影响)。重要的是,两个具有相同字节的不同数组将具有不同的.toStrings。请注意,在某些地方(例如 REPL),Scala 会打印类似的内容Array(-127, 0, 0, 1)而不是调用.toString:这可能会导致混乱。
看起来toByteArray每次调用都会发出一个新数组。因此,第一次调用时newPerson.toByteArray,您会在对应的位置获得一个数组50da041d。第二次调用它时,您将在对应的位置获得一个具有相同内容的字节数组,7709e969并将该字符串保存[B@7709e969到变量中l。然后,当您调用getBytes该字符串(将其保存在 中l1)时,您会得到一个字节数组,它是与 对应的位置处的字符串“[B@7709e969”的编码f44b405。
50da041d因此,在和对应的位置处,7709e969您有两个不同的字节数组,它们恰好包含相同的元素(这些元素是 的原型表示中的字节newPerson)。在与您对应的位置f44b405有一个字节数组,其中字节编码(在某些字符集中,可能是 UTF-16?)[B@7709e969。
因为原型并不是真正的字符串,所以没有通用的方法来获取有用的字符串(取决于您正在处理的有用的定义)。您可以尝试将字节数组解释为toByteArray具有给定字符编码的字符串,但不能保证任何给定的原型在任意字符编码中都有效。
纯粹的 8 位编码,例如ISO-8859-1保证至少可以从字节数组中解码,但可能存在不可打印或控制字符,因此它不太有用:
val iso88591Representation = new String(newPerson.toByteArray, java.nio.charset.StandardCharsets.ISO_8859_1)
Run Code Online (Sandbox Code Playgroud)
或者,您可能需要像 Scala REPL(有时)如何呈现它的表示形式:
"Array(" + newPerson.toByteArray.mkString(", ") + ")"
Run Code Online (Sandbox Code Playgroud)