FileChannel和FileInputStream中的read(ByteBuffer)和read(byte [])之间的区别

时间:2013-01-10 06:12:20

标签: java io nio

我刚接触 NIO ,我发现一篇文章说'基于块的传输通常比基于流的传输更有效'。 这意味着read(ByteBuffer)是基于块的传输,read(byte [])是基于流的传输。

我想知道两种方法之间的内在差异。

ps:我也听说基于块的传输正在传输字节数组,而基于流的传输正在逐个传输字节。我认为这是错的, 因为java.io.FileInputStream.read(byte [])也传输字节数组。

3 个答案:

答案 0 :(得分:3)

使Bytebuffer更有效的一件事是使用直接内存。这样可以避免从直接内存复制到byte []。如果您只是将数据从一个频道复制到另一个频道,则速度可提高30%。如果逐字节读取,使用ByteBuffer可能会稍慢,因为它有更多的开销访问每个字节。如果你用它来读取二进制文件,例如intdouble它可以更快,因为它可以在一次访问中获取整个值。

答案 1 :(得分:1)

我认为您在谈论buffer-basedstream-based I / O操作。 Java NIO是面向缓冲区的,因为数据首先被读入缓冲区然后被处理。这提供了一种灵活性。此外,在处理缓冲区之前,您需要确保缓冲区包含您需要的所有数据。另一方面,使用stream-based I / O,您从流中读取一个或多个字节,这些字节不会缓存在任何位置。这是阻塞I / O,而buffer-based I / O(Java NIO)是非阻塞IO。

答案 2 :(得分:0)

虽然我不会使用“基于流”来表征read(byte[]),但在某些情况下,ByteBuffer的效率会提高byte[]

请参阅A simple rule of when I should use direct buffers with Java NIO for network I/O?ByteBuffer.allocate() vs. ByteBuffer.allocateDirect()

支持ByteBuffer的内存可以(如果“直接”)更容易让JVM传递给操作系统并执行IO技巧(例如直接将内存传递给读写调用),以及可能不在JVM的堆上。支持byte[]的内存位于JVM堆上,IO通常不会直接进入阵列使用的内存(而是经常通过反弹缓冲区---因为GC可能会“移动”数组对象在IO处于挂起状态或数组内存可能不连续的情况下在内存中。

但是,如果你必须在Java中操作数据,ByteBuffer可能没什么区别,因为你最终必须将数据复制到Java堆中来操纵它。如果你正在进行数据拷贝进行操作,那么直接ByteBuffer就可以获胜。