作为 Iterator[Byte] 或 Array[Byte] 从 InputStream 读取
Reading from InputStream as an Iterator[Byte] or Array[Byte]
我将数据对象表示为 Iterator[Byte]
,它是从 InputStream
实例创建的。
问题在于Byte
是-128到127的有符号整数,而InputStream
中的read
方法returns是0到127的无符号整数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
}
}
}
不幸的是,这与 class InputStream
的糟糕设计有关。如果您改用 read() you will have that problem. You should use read(byte[]) 。
但是正如您所说,您也可以使用 Int
。这取决于你。
是的,您可以轻松地将 byte 转换为 int,反之亦然。
首先,int 到 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
我将数据对象表示为 Iterator[Byte]
,它是从 InputStream
实例创建的。
问题在于Byte
是-128到127的有符号整数,而InputStream
中的read
方法returns是0到127的无符号整数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
}
}
}
不幸的是,这与 class InputStream
的糟糕设计有关。如果您改用 read() you will have that problem. You should use read(byte[]) 。
但是正如您所说,您也可以使用 Int
。这取决于你。
是的,您可以轻松地将 byte 转换为 int,反之亦然。
首先,int 到 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