读取二进制文件内容的快速方法无法正常工作

时间:2016-08-08 21:42:13

标签: java android io bin

我正在创建一个Android应用程序,需要读取~5 MB的二进制文件才能使用Apache OpenNLP的词性标记器。我尝试了一个相当迂回的路径来快速读取文件,使用ByteBuffer和自定义ByteBufferInputStream类。我以为我正确地做了,但是当我检查方法返回的POSModel时,结果是' null'。应该发生的是ByteBuffer从二进制文件中读取信息,然后将其作为InputStream提供给POSModel构造函数。

以下是从二进制文件中获取词性模型的代码:

public POSModel setupPOSModel() {
        ByteBufferInputStream modelIn = null;
        POSModel model = null;
        try {
            InputStream stream = getResources().openRawResource(R.raw.en_pos_maxent);
            byte[] b = IOUtils.toByteArray(stream);
            ByteBuffer buf = ByteBuffer.wrap(b);

            modelIn = new ByteBufferInputStream(buf);
            model = new POSModel(modelIn);
        } catch (IOException e) {
            // Model loading failed, handle the error
            e.printStackTrace();
        } finally {
            if (modelIn != null) {
                try {
                    modelIn.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
//at this point 'model' is null
        System.out.println("POS MODEL: " + model);
        return model;
    }

这里是ByteBufferInputStream的代码,我从另一个Stack Overflow问题得到了这个代码:

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;

public class ByteBufferInputStream extends InputStream {

    private int bbisInitPos;
    private int bbisLimit;
    private ByteBuffer bbisBuffer;

    public ByteBufferInputStream(ByteBuffer buffer) {
        this(buffer, buffer.limit() - buffer.position());
    }

    public ByteBufferInputStream(ByteBuffer buffer, int limit) {
        bbisBuffer = buffer;
        bbisLimit = limit;
        bbisInitPos = bbisBuffer.position();
    }

    @Override
    public int read() throws IOException {
        if (bbisBuffer.position() - bbisInitPos > bbisLimit)
            return -1;
        return bbisBuffer.get();
    }
}

现在,我的最终目标只是阅读" en_pos_maxent"二进制文件尽可能快(目前,使用常规的InputStream,大约需要20秒),所以如果有一种比我的迂回方式更好的方法来使用ByteBuffer快速获取文件内容,那么该替代方法也可以工作。 / p>

更新

这里是方法引发的异常的堆栈跟踪:

08-08 14:59:38.220 2735-3351/com.newssummary W/System.err: java.util.zip.ZipException: CRC mismatch
08-08 14:59:38.220 2735-3351/com.newssummary W/System.err:     at java.util.zip.ZipInputStream.readAndVerifyDataDescriptor(ZipInputStream.java:215)
08-08 14:59:38.220 2735-3351/com.newssummary W/System.err:     at java.util.zip.ZipInputStream.closeEntry(ZipInputStream.java:164)
08-08 14:59:38.220 2735-3351/com.newssummary W/System.err:     at opennlp.tools.util.model.BaseModel.loadModel(BaseModel.java:245)
08-08 14:59:38.220 2735-3351/com.newssummary W/System.err:     at opennlp.tools.util.model.BaseModel.<init>(BaseModel.java:179)
08-08 14:59:38.220 2735-3351/com.newssummary W/System.err:     at opennlp.tools.postag.POSModel.<init>(POSModel.java:105)
08-08 14:59:38.220 2735-3351/com.newssummary W/System.err:     at com.newssummary.MainActivity$override.setupPOSModel(MainActivity.java:245)
08-08 14:59:38.220 2735-3351/com.newssummary W/System.err:     at com.newssummary.MainActivity$override.access$dispatch(MainActivity.java)
08-08 14:59:38.220 2735-3351/com.newssummary W/System.err:     at com.newssummary.MainActivity.setupPOSModel(MainActivity.java:0)
08-08 14:59:38.221 2735-3351/com.newssummary W/System.err:     at com.newssummary.MainActivity$4.doAsync(MainActivity.java:190)
08-08 14:59:38.221 2735-3351/com.newssummary W/System.err:     at com.newssummary.MainActivity$4.doAsync(MainActivity.java:182)
08-08 14:59:38.221 2735-3351/com.newssummary W/System.err:     at com.arasthel.asyncjob.AsyncJob$4.run(AsyncJob.java:91)
08-08 14:59:38.221 2735-3351/com.newssummary W/System.err:     at java.lang.Thread.run(Thread.java:818)

1 个答案:

答案 0 :(得分:0)

如果没有详细了解POSModel初始化引发的异常,我只能在此处进行一些简化,以完全避免ByteBuffer。考虑使用ByteArrayInputStream,如下所示:

import java.io.ByteArrayInputStream;

final byte[] data = IOUtils.toByteArray(stream);
final InputStream memstream = new ByteArrayInputStream(data);

model = new POSModel(memstream);

或者,考虑使用BufferedInputStream而不是先将整个资源手动读入大缓冲区。

您共享的异常跟踪表明模型数据发生了一些损坏,无论是在实际资源数据中,还是作为IOUtils.toByteArrayByteBufferInputStream的副作用实现。尝试使用ByteArrayInputStream,让我们知道它是怎么回事。