从InputStream读取迭代器[Byte]或Array [Byte]

时间:2015-05-15 09:57:51

标签: scala byte inputstream type-conversion

我将数据对象表示为Iterator[Byte],它是从InputStream实例创建的。

问题在于Byte是从-128到127的有符号整数,而read中的InputStream方法返回0到255之间的无符号整数。这尤其是有问题的,因为通过语义-1应该表示输入流的结束。

缓解这两种类型之间不兼容性的最佳方法是什么?是否有一种优雅的方式在一个到另一个之间进行转换?或者我应该使用Int代替Bytes,即使它感觉不那么优雅?

def toByteIterator(in: InputStream): Iterator[Byte] = {
  Iterator.continually(in.read).takeWhile(-1 !=).map { elem =>
    convert // need to convert unsigned int to Byte here
  }
}

def toInputStream(_it: Iterator[Byte]): InputStream = {
  new InputStream {
    val (it, _) = _it.duplicate
    override def read(): Int = {
      if (it.hasNext) it.next() // need to convert Byte to unsigned int
      else -1
    }
  }
}

2 个答案:

答案 0 :(得分:1)

不幸的是,它与类InputStream的糟糕设计有关。如果您使用read(),则会出现此问题。您应该使用read(byte[])代替。 但正如你所说,你也可以使用Int。这取决于你。

答案 1 :(得分:1)

是的,您可以轻松地将字节转换为int,反之亦然。

首先,int to byte只能用toByte转换:

scala> 128.toByte
res0: Byte = -128

scala> 129.toByte
res1: Byte = -127

scala> 255.toByte
res2: Byte = -1

因此,elem => convert可能只是_.toByte

其次,可以将带符号的int中的带符号函数转换为带符号的java.lang.Byte,称为toUnsignedInt

scala> java.lang.Byte.toUnsignedInt(-1)
res1: Int = 255

scala> java.lang.Byte.toUnsignedInt(-127)
res2: Int = 129

scala> java.lang.Byte.toUnsignedInt(-128)
res3: Int = 128

所以你可以在第二段代码中写java.lang.Byte.toUnsignedInt(it.next())

但是,最后一种方法仅在Java 8之后才可用。我不了解旧版Java中的替代方法,但其实际实现非常简单:

public static int toUnsignedInt(byte x) {
    return ((int) x) & 0xff;
}

所以你只需要写

it.next().toInt & 0xff