繁体   English   中英

在Java / Scala中将字节数组转换为字符串时修剪字节数组

[英]Trimming byte array when converting byte array to string in Java/Scala

使用ByteBuffer,我可以将字符串转换为字节数组:

val x = ByteBuffer.allocate(10).put("Hello".getBytes()).array()
> Array[Byte] = Array(104, 101, 108, 108, 111, 0, 0, 0, 0, 0)

将字节数组转换为字符串时,我可以使用new String(x) 但是,字符串成为hello????? ,我需要在将字节数组转换为字符串之前减少它。 我怎样才能做到这一点?

我使用这段代码来减少零,但我想知道是否有更简单的方法。

def byteArrayToString(x: Array[Byte]) = {
    val loc = x.indexOf(0)
    if (-1 == loc)
      new String(x)
    else if (0 == loc)
      ""
    else
      new String(x.slice(0,loc))
}

假设0: Byte是一个尾随值,那么

implicit class RichToString(val x: java.nio.ByteBuffer) extends AnyVal {
  def byteArrayToString() = new String( x.array.takeWhile(_ != 0), "UTF-8" )
}

因此

val x = ByteBuffer.allocate(10).put("Hello".getBytes())

x.byteArrayToString
res: String = Hello

一些String构造函数byte[]接受偏移+长度 - 这消除了在手工创建新修剪数组之前的需要。

使用其中一个重载的构造函数可能如下所示:

def byteArrayToString(x: Array[Byte]) = {
    val loc = x.indexOf(0)
    if (-1 == loc)
      new String(x)
    else if (0 == loc)
      ""
    else
      new String(x, 0, loc, "UTF-8") // or appropriate encoding
}

或者,保持indexOf的略有变化:

def byteArrayToString(arr: Array[Byte]) = {
    val loc = arr.indexOf(0)
    // length passed to constructor can be 0..arr.length
    new String(arr, 0, if (loc >= 0) loc else arr.length, "UTF-8")
}

或者,一行(感谢find / Option):

def byteArrayToString(arr: Array[Byte]) = {
    new String(arr, 0, arr.find(_ == 0) orElse arr.length, "UTF-8")
}

关于编码的思考:

  1. 通常建议使用显式编码,并且应使用getBytes指定的相同编码,因为默认值可能会更改 这是标准的字符集名称

  2. 字节0 可能出现在数据结束之前的编码输出中,具体取决于字符串输入(即NUL)和使用的编码。

如果你只有一个String ,我会使用.getBytes() -

val x:Array[Byte] = "Hello".getBytes("UTF-8");

输出是

x: Array[Byte] = Array(72, 101, 108, 108, 111)

对于多个String ,我会使用ByteArrayOutputStream ,就像这样 -

val baos = new java.io.ByteArrayOutputStream(10); //  <-- I might not use 10.
                                                  //  <-- Smells of premature opt.
baos.write("Hello".getBytes("UTF-8"));
baos.write(", World!".getBytes("UTF-8"));

val x:Array[Byte] = baos.toByteArray(); // <-- x:Array[Byte], to specify the type.

输出是

x: Array[Byte] = Array(72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33)

你可以这样做:

val bb = java.nio.ByteBuffer.allocate(10).put("Hello".getBytes)
val s = new String(bb.array, 0, bb.position)

虽然这不会在ByteBuffer中表明你已经读过任何东西。 正常的模式是flip和使用limit ,但如果你只是抓住阵列,你也可以只使用position并在完成之前clear ,然后再阅读更多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM