scala-将Int序列化为ArrayBuffer[Byte]。小把戏出错了

scala-将Int序列化为ArrayBuffer[Byte]。小把戏出错了,scala,bit-manipulation,Scala,Bit Manipulation,我想将一个数组序列化为字节数组或数组缓冲区 我意识到我可以使用“java.nio.ByteBuffer”,但我只是为了好玩而尝试,并试图自己去做 以下代码适用于正整数,但在序列化负整数时出错。 有人能解释一下原因或者给我一个更正吗 import scala.collection.mutable.ArrayBuffer object b { val INTBYTES:Int = 4 // int is 4 bytes def toArrayBuf(x:Int): ArrayBuffer

我想将一个数组序列化为字节数组或数组缓冲区

我意识到我可以使用“java.nio.ByteBuffer”,但我只是为了好玩而尝试,并试图自己去做

以下代码适用于正整数,但在序列化负整数时出错。 有人能解释一下原因或者给我一个更正吗

import scala.collection.mutable.ArrayBuffer

object b {
  val INTBYTES:Int = 4 // int is 4 bytes

  def toArrayBuf(x:Int): ArrayBuffer[Byte] = {
    val buf = new ArrayBuffer[Byte](INTBYTES)
    for(i <- 0 until INTBYTES) {
      buf += ((x >>> (INTBYTES - i - 1 << 3)) & 0xFF).toByte
    }
    buf
  }
}
但是这个带负int的函数做了一些奇怪的事情:-

scala> val test2:Int = 0x8f0f0f0f
test2: Int = -1894838513

scala> println(test2.toBinaryString)
10001111000011110000111100001111

scala> val t2 = b.toArrayBuf(test2)
t2: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(-113, 15, 15, 15)

scala> t2.foreach( it => printf("%s ",it.toInt.toBinaryString))
11111111111111111111111110001111 1111 1111 1111
请注意,整个int的第一个字节已填充为1,它应为“10001111”

有什么想法吗

供参考 即时通讯使用:-

scala -version
Scala code runner version 2.10.1 -- Copyright 2002-2013, LAMP/EPFL
java -fullversion
java full version "1.7.0_40-b31"
with OpenJDK

感谢Scala的
ToBinarysting
方法遵从
Integer
上的Java方法。从这些文件中:

公共静态字符串toBinaryString(int i)

返回整数参数的无符号字符串表示形式 以2为底的整数。无符号整数值是参数加号 2^32如果参数是否定的;否则,它等于 论点此值在中转换为ASCII数字字符串 二进制(基2),无额外的前导0

换句话说,它是按规定工作的。您的位旋转似乎是正常的,但当您打印出数字时,您需要意识到字符的数量取决于数据类型的长度。(例如,二进制中的-1:Int是11111111111,而-1:Byte是11111111。)正数可以不使用它,因为前导零没有显示,如上所述

解决方案:将您自己的
设置为字节的二进制字符串
,或者仅从Int版本中获取最右边的8位数字就可以了(尽管效率较低),即


Scala的
tobinarysting
方法遵从
Integer
上的Java方法。从这些文件中:

公共静态字符串toBinaryString(int i)

返回整数参数的无符号字符串表示形式 以2为底的整数。无符号整数值是参数加号 2^32如果参数是否定的;否则,它等于 论点此值在中转换为ASCII数字字符串 二进制(基2),无额外的前导0

换句话说,它是按规定工作的。您的位旋转似乎是正常的,但当您打印出数字时,您需要意识到字符的数量取决于数据类型的长度。(例如,二进制中的-1:Int是11111111111,而-1:Byte是11111111。)正数可以不使用它,因为前导零没有显示,如上所述

解决方案:将您自己的
设置为字节的二进制字符串
,或者仅从Int版本中获取最右边的8位数字就可以了(尽管效率较低),即


根据Luigi的建议,我为Byte砍掉了一个皮条客,该皮条客提供了一个正常工作的Tobinarysting,以防其他人遇到类似的问题

object b {
  val INTBYTES:Int = 4 // int is 4 bytes
  val SIZEBYTE:Short = 8

  def toArrayBuf(x:Int): ArrayBuffer[Byte] = {
    val buf = new ArrayBuffer[Byte](INTBYTES)
    for(i <- 0 until INTBYTES) {
      buf += ((x >>> (INTBYTES - i - 1 << 3)) & 0xFF).toByte
    }
    buf
  }

  def toBinaryString(x: Byte): String = {
    val buf = new StringBuilder(SIZEBYTE)
    for(i <- 0 until SIZEBYTE) {
      buf.append((x >>> (SIZEBYTE - i - 1)) & 0x01)
    }
    buf.toString()
  }
}

//pimp Byte
implicit def fooBar(byte: Byte) = new {def toBinaryString = b.toBinaryString(byte)}


感谢Luigi

接受Luigi的建议,我为Byte创建了一个pimp,它提供了一个正常工作的Tobinarysting,以防其他人遇到类似问题。我就是这么做的

object b {
  val INTBYTES:Int = 4 // int is 4 bytes
  val SIZEBYTE:Short = 8

  def toArrayBuf(x:Int): ArrayBuffer[Byte] = {
    val buf = new ArrayBuffer[Byte](INTBYTES)
    for(i <- 0 until INTBYTES) {
      buf += ((x >>> (INTBYTES - i - 1 << 3)) & 0xFF).toByte
    }
    buf
  }

  def toBinaryString(x: Byte): String = {
    val buf = new StringBuilder(SIZEBYTE)
    for(i <- 0 until SIZEBYTE) {
      buf.append((x >>> (SIZEBYTE - i - 1)) & 0x01)
    }
    buf.toString()
  }
}

//pimp Byte
implicit def fooBar(byte: Byte) = new {def toBinaryString = b.toBinaryString(byte)}


感谢Luigi

如果您想在scala中实现类似的功能,您可能需要查看akka.util.ByteString及其构建器。它包含各种有用的方法来转换具有不同端点的原语。它是不变的,所以它不像ByteBuffer那么低级。很好的建议,鲁迪格,我会用它,但正如我提到的,我是在为自己做实验,以获得更好的理解,干杯如果你想在scala中使用类似的东西,你可能想看看akka.util.ByteString及其构建器。它包含各种有用的方法来转换具有不同端点的原语。它是不变的,所以它不像ByteBuffer那么低级。好的建议鲁迪奇,我会用它,但正如我提到的,我正在为自己做实验,以获得更好的理解,干杯!谢谢你的回答。我很高兴这个小把戏是正确的,似乎很遗憾scala没有有用的二进制表示格式和转换用于接近机器类型。太好了!谢谢你的回答。我很高兴这个小把戏是正确的,但scala没有提供有用的二进制表示格式和转换,这似乎是一个遗憾。
object b {
  val INTBYTES:Int = 4 // int is 4 bytes
  val SIZEBYTE:Short = 8

  def toArrayBuf(x:Int): ArrayBuffer[Byte] = {
    val buf = new ArrayBuffer[Byte](INTBYTES)
    for(i <- 0 until INTBYTES) {
      buf += ((x >>> (INTBYTES - i - 1 << 3)) & 0xFF).toByte
    }
    buf
  }

  def toBinaryString(x: Byte): String = {
    val buf = new StringBuilder(SIZEBYTE)
    for(i <- 0 until SIZEBYTE) {
      buf.append((x >>> (SIZEBYTE - i - 1)) & 0x01)
    }
    buf.toString()
  }
}

//pimp Byte
implicit def fooBar(byte: Byte) = new {def toBinaryString = b.toBinaryString(byte)}
scala> val test:Int = 0x4f0f0f0f
test: Int = 1326386959

scala> println(test.toBinaryString)
1001111000011110000111100001111

scala> val t1 = toArrayBuf(test)
t1: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(79, 15, 15, 15)

scala> t1.foreach( it => printf("%s ",it.toBinaryString))
01001111 00001111 00001111 00001111 
scala> val test2:Int = 0x8f0f0f0f
test2: Int = -1894838513

scala> println(test2.toBinaryString)
10001111000011110000111100001111

scala> val t2 = toArrayBuf(test2)
t2: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(-113, 15, 15, 15)

scala> t2.foreach( it => printf("%s ",it.toBinaryString))
10001111 00001111 00001111 00001111