何时使用字节数组和何时使用字节缓冲区?


Answers:


60

实际上,有许多种处理字节的方法。我同意选择最佳的方法并不总是那么容易:

  • byte[]
  • java.nio.ByteBuffer
  • java.io.ByteArrayOutputStream(与其它流组合)
  • java.util.BitSet

byte[]仅仅是一个原始阵列,只是包含的原始数据。因此,它没有用于构建或处理内容的便捷方法。

AByteBuffer更像是建造者。它创建一个byte[]。与数组不同,它具有更方便的辅助方法。(例如append(byte)方法)。在用法上并不是那么简单。(大多数的教程是太复杂或质量较差,但是这一个会得到你的地方。把它一步?然后阅读有关的诸多陷阱。)

您可能会很想说aByteBuffer做对byte[],aStringBuilder做对什么String。但是ByteBuffer该类存在特定的差异/缺点。就像使用数组,ByteBuffer有一个固定的大小。因此,在实例化它时,您已经必须指定缓冲区的大小。

这就是原因之一,ByteArrayOutputStream之所以经常喜欢使用,是因为它像aArrayList一样会自动调整大小。(它有一个toByteArray()方法)。有时将其包装在实用DataOutputStream这样做的好处是,您将获得一些其他的便捷调用(例如,writeShort(int)如果您需要写入2个字节)。

BitSet当您要执行位级操作时,它会派上用场。您可以获取/设置各个位,并且具有类似的逻辑运算符方法xor()。(该toByteArray()方法仅在Java 7中引入。)

当然,根据您的需求,您可以结合所有这些来建立您的byte[]


1
您的回答非常有帮助
LiLi

26

ByteBuffer是新IO软件包(nio)的一部分,该软件包是为快速处理基于文件的数据而开发的。具体来说,Apache是​​一种非常快速的Web服务器(用C编写),因为它从磁盘读取字节并将其直接放入网络,而无需通过各种缓冲区将它们改组。它通过内存映射文件来完成此任务,而Java的早期版本则没有。随着nio的出现,用Java编写与Apache一样快的Web服务器成为可能。当您想要非常快的文件到网络吞吐量时,则要使用内存映射文件和ByteBuffer。

数据库通常使用内存映射文件,但是这种用法在Java中很少有效。在C / C ++中,可以加载大量内存并将其转换为所需的类型化数据。由于Java的安全性模型,这通常不可行,因为您只能转换为某些本机类型,而这些转换效率不是很高。当您仅将字节作为纯字节数据进行处理时,ByteBuffer效果最佳。一旦需要将其转换为对象,其他java io类通常会表现更好并且更易于使用。

如果您不处理内存映射文件,那么您实际上就不必费心ByteBuffer了-您通常会使用字节数组。如果您要构建Web服务器,并以尽可能快的吞吐量处理基于文件的原始字节数据,则ByteBuffer(特别是MappedByteBuffer)是您最好的朋友。


2
限制不是Java安全模型。JVM体系结构阻止您将字节转换为类型化的数据。
Stephen C

安全模型还影响ByteBuffer的可用性-至少在我已经进行了几年测试的测试中。每次您调用ByteBuffer类中的强制转换函数之一时,都会执行SecurityManager代码,这会使整个过程变慢。这就是为什么常规的Java io函数通常可以更快地读取Java基本类型的原因。这与C相反,C使用强制转换的内存映射文件比使用stdio快得多。
JRalph 2011年

查看代码,安全管理器调用仅在DirectByteBuffer情况下出现。我认为这是因为该方法正在使用Unsafe
Stephen C

3

1
我无法重现第一个链接的结论,即FileChannel在读取byte []方面比FileInputStream快得多。我怀疑,由于它们使用的文件长度为100MB,因此实际上是对从操作系统的磁盘缓存而不是硬盘驱动器读取数据进行基准测试。这可以解释为什么他们的测试暗示了250MB / s的带宽,这对于磁盘来说是非常快的。在我使用1.5GB文件的测试中,两种方法均达到40MB / s的吞吐量,这表明磁盘是瓶颈,而不是CPU。当然,使用固态磁盘的里程可能会有所不同。
meriton'3

5
让我们知道为什么这些链接可能会有所帮助,您可以提高此答案的质量。仅链接的答案并不理想。
james.garriss 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.