首页 文章

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

提问于
浏览
0

当我执行以下课程时

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)说,

从该通道读取一个字节序列到给定的缓冲区 . 从该通道的当前文件位置开始读取字节,然后使用实际读取的字节数更新文件位置 . 否则,此方法的行为与ReadableByteChannel接口中指定的完全相同 .

Otherwise 是什么意思?

2 回答

  • 3

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

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

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

    上面@Peter Lawrey的答案提供了无限循环的解决方案 . 除此之外,根据我的理解,回答你关于 otherwiseFileChannel 类文档中的含义的问题:

    来自Java docs

    从该通道读取一个字节序列到给定的缓冲区 . 从该通道的当前文件位置开始读取字节,然后使用实际读取的字节数更新文件位置 .

    此方法的行为与阻塞和非阻塞I / O模式下的 ReadableByteChannel.read 方法以及线程安全要求完全相同 . 它执行的 only additional 操作(读取OOP术语中的特化)是 FileChannel.read 实现还将使用从通道实际读取的字节数来增加文件位置 .

    希望这可以帮助

相关问题