简体   繁体   English

SeekableByteChannel.read()始终返回0,InputStream可以

[英]SeekableByteChannel.read() always returns 0, InputStream is fine

We have a data file for which we need to generate a CRC. 我们有一个需要为其生成CRC的数据文件。 (As a placeholder, I'm using CRC32 while the others figure out what CRC polynomial they actually want.) This code seems like it ought to work: (作为一个占位符,我使用的是CRC32,其他人则弄清楚了他们实际想要的是CRC多项式。)这段代码似乎应该起作用:

broken: 破碎:

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;
}

The System.err and loops stuff is just for debugging; System.errloops内容仅用于调试; we don't actually care how many times it takes. 我们实际上并不关心需要花费多少时间。 The output is: 输出为:

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

There's no way to run the real code inside a debugger to step through it, but from looking at the source to sun.nio.ch.FileChannelImpl.read() it looks like a 0 is returned if the file magically becomes closed while internal data structures are prepared; 没有办法在调试器中运行真实的代码来逐步调试它,但是从查看源代码到sun.nio.ch.FileChannelImpl.read() ,如果文件在内部数据中神奇地关闭,则看起来像返回了0。准备结构; the code below is copied from the Java 7 reference implementation, comments added by me: 下面的代码是从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 (......)
.......

But the debugging code tests isOpen() and gets true. 但是调试代码会测试isOpen()并得到true。 So I don't know what's going wrong. 所以我不知道出了什么问题。

As the current test data files are tiny, I dropped this in place just to have something working: 由于当前的测试数据文件很小,因此我将其放置在适当的位置只是为了使某些功能正常工作:

works for now: 现在可以使用:

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

I don't want to slurp the entire file into memory for the Real Code, because some of those files can be large . 我不想将整个文件插入到Real Code的内存中,因为其中一些文件可能很大 I do note that readAllBytes uses an InputStream in its reference implementation, which has no trouble reading the same file that SeekableByteChannel failed to. 我确实注意到readAllBytes在其参考实现中使用了InputStream,它可以readAllBytes读取SeekableByteChannel失败的相同文件。 So I'll probably rewrite the code to just use input streams instead of byte channels. 因此,我可能会重写代码以仅使用输入流而不是字节通道。 I'd still like to figure out what's gone wrong in case a future scenario comes up where we need to use byte channels. 我仍然想弄清楚出了什么问题,以防将来出现需要使用字节通道的情况。 What am I missing with SeekableByteChannel ? SeekableByteChannel我缺少什么?

检查“ reasonable_buffer_size”是否不为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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