为什么 FileChannel 读取永远不会结束?

Why FileChannel reading never ends?

当我执行以下 class

import java.io.*;
import java.nio.*;
import java.nio.file.*;
import java.nio.channels.*;

public class FileChannelTest {                                                                                                                      
    public static void main(final String... args) throws IOException {                                                                              
        final File file = File.createTempFile("temp", null);                                                                                        
        file.deleteOnExit();                                                                                                                        
        // write some                                                                                                                               
        try(OutputStream output = new FileOutputStream(file)) {                                                                                     
            output.write(new byte[128]);                                                                                                            
            output.flush();                                                                                                                         
        }                                                                                                                                           
        System.out.println("length: " + file.length());                                                                                             
        // read to end                                                                                                                              
        try(FileChannel channel                                                                                                                     
            = FileChannel.open(file.toPath(), StandardOpenOption.READ)) {                                                                           
            final ByteBuffer buffer = ByteBuffer.allocate(128);                                                                                     
            for(int read; (read = channel.read(buffer)) != -1; ) {                                                                                  
                System.out.println("read: " + read);                                                                                                
            }                                                                                                                                       
        }                                                                                                                                           
    }                                                                                                                                               
}

阅读循环永无止境。

$ java -version
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)
$ java FileChannelTest.java
$ java FileChannelTest
length: 128
read: 128
read: 0
read: 0
read: 0
...
...
...

FileChannel.read(ByteBuffer) 说,

Reads a sequence of bytes from this channel into the given buffer. Bytes are read starting at this channel's current file position, and then the file position is updated with the number of bytes actually read. Otherwise this method behaves exactly as specified in the ReadableByteChannel interface.

否则是什么意思?

当您读入 ByteBuffer 时,它只能读取缓冲区中可用的字节数,即 byteBuffer.remaining() 这意味着一旦缓冲区已满,当您读取它时 returns 0.

我建议您使用 clear() 如果您已经读取了所有读取的数据,或者如果您只使用了一部分读取的数据则使用 compact()

      for(int read; (read = channel.read(buffer)) != -1; ) {                                                                                  
            System.out.println("read: " + read);    
            buffer.clear(); // so we can read more data                                                                                           
      }   

上面@Peter Lawrey 的回答提供了无限循环的解决方案。除此之外,根据我的理解,回答你关于 otherwiseFileChannel class 的文档中意味着什么的问题:

来自Java docs :

Reads a sequence of bytes from this channel into the given buffer. Bytes are read starting at this channel's current file position, and then the file position is updated with the number of bytes actually read.

此方法在阻塞和 non-blocking I/O 模式下以及 thread-safety 要求方面的行为与 ReadableByteChannel.read 方法完全相同。 它执行的唯一额外 操作(OOP 术语中的读取专业化)是 FileChannel.read 实现还将使用从通道实际读取的字节数增加文件位置。

希望这对您有所帮助