我正在创建一个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)
答案 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.toByteArray
或ByteBufferInputStream
的副作用实现。尝试使用ByteArrayInputStream
,让我们知道它是怎么回事。