简体   繁体   中英

Why FileChannel reading never ends?

When I execute following 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);                                                                                                
            }                                                                                                                                       
        }                                                                                                                                           
    }                                                                                                                                               
}

The reading loop never ends.

$ 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) says,

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.

What does Otherwise mean?

When you read into a ByteBuffer, it can only read as many bytes as is available in the buffer ie byteBuffer.remaining() This means once the buffer is full, when you do a read it returns 0 .

I suggest you use either clear() if you have consumed all the data read, or compact() if you have consumed only a portion of the data read.

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

The answer from @Peter Lawrey above provides the solution to your infinite loop. In addition to this, to answer your question about what otherwise means in the documentation of FileChannel class as per my understanding :

From the 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.

This method will behave exactly like the ReadableByteChannel.read method under blocking and non-blocking I/O mode and in terms of thread-safety requirements. The only additional operation it performs (read specialization in OOP terminology) is that the FileChannel.read implementation will also increment the file position with the number of bytes actually read from the channel.

Hope this helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM