将 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= 的位置的编码].
所以在对应于 50da041d
和 7709e969
的位置,你有两个不同的字节数组,它们恰好包含相同的元素(这些元素是 [=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(", ") + ")"
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= 的位置的编码].
所以在对应于 50da041d
和 7709e969
的位置,你有两个不同的字节数组,它们恰好包含相同的元素(这些元素是 [=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(", ") + ")"