SeekableByteChannel.read()总是返回0,InputStream没问题

时间:2014-06-19 18:40:47

标签: java nio

我们有一个数据文件,我们需要生成一个CRC。 (作为占位符,我使用CRC32,而其他人想出他们实际想要的CRC多项式。)这段代码似乎应该有效:

破:

Path in = ......;

try (SeekableByteChannel reading =
    Files.newByteChannel (in, StandardOpenOption.READ))
{
System.err.println("byte channel is a " + reading.getClass().getName() +
  " from " + in + " of size " + reading.size() + " and isopen=" + reading.isOpen());
    java.util.zip.CRC32 placeholder = new java.util.zip.CRC32();
    ByteBuffer buffer = ByteBuffer.allocate (reasonable_buffer_size);

    int bytesread = 0;
    int loops = 0;
    while ((bytesread = reading.read(buffer)) > 0) {
        byte[] raw = buffer.array();
System.err.println("Claims to have read " + bytesread + " bytes, have buffer of size " + raw.length + ", updating CRC");
        placeholder.update(raw);
        loops++;
        buffer.clear();
    }
    // do stuff with placeholder.getValue()
}
catch (all the things that go wrong with opening files) {
    and handle them;
}

System.errloops内容仅用于调试;我们实际上并不关心它需要多少次。输出是:

byte channel is a sun.nio.ch.FileChannelImpl from C:\working\tmp\ls2kst83543216xuxxy8136.tmp of size 7196 and isopen=true finished after 0 time(s) through the loop

没有办法在调试器中运行实际代码来逐步执行它,但是从查看源代码到sun.nio.ch.FileChannelImpl.read()如果文件在内部神奇地关闭时,它看起来像是0准备数据结构;下面的代码是从Java 7参考实现中复制的,我添加了评论:

// sun.nio.ch.FileChannelImpl.java
public int read(ByteBuffer dst) throws IOException {
    ensureOpen();              // this throws if file is closed...
    if (!readable)
        throw new NonReadableChannelException();
    synchronized (positionLock) {
        int n = 0;
        int ti = -1;
        Object traceContext = IoTrace.fileReadBegin(path);
        try {
            begin();
            ti = threads.add();
            if (!isOpen())
                return 0;       // ...argh
            do {
                n = IOUtil.read(fd, dst, -1, nd);
            } while (......)
.......

但调试代码测试isOpen()并获得真实。所以我不知道出了什么问题。

由于目前的测试数据文件很小,我把它放在适当位置只是为了让某些东西工作:

目前有效:

try {
    byte[] scratch = Files.readAllBytes(in);
    java.util.zip.CRC32 placeholder = new java.util.zip.CRC32();
    placeholder.update(scratch);
    // do stuff with placeholder.getValue()
}

我不想将整个文件粘贴到Real Code的内存中,因为其中一些文件可能是 large 。我注意到readAllBytes在其参考实现中使用了一个InputStream,它可以读取SeekableByteChannel失败的同一个文件。所以我可能会重写代码只使用输入流而不是字节通道。我仍然想知道在我们需要使用字节通道的情况下出现未来情况时出了什么问题。 SeekableByteChannel我错过了什么?

1 个答案:

答案 0 :(得分:0)

检查'rational_buffer_size'是否为零。