2016-08-08 10 views
0

Apache OpenNLPの品詞タグを使用するために〜5 MBのバイナリファイルを読み込む必要のあるAndroidアプリを作成しています。 ByteBufferとカスタムのByteBufferInputStreamクラスを使用して、ファイルをすばやく読み取るためにかなり迂回したルートを試しました。私はそれを正しくやっていると思っていましたが、メソッドによって返されたPOSModelをチェックすると、nullになることが判明しました。起こるはずのことは、ByteBufferがバイナリファイルから情報を読み込み、それをPOSModelコンストラクタのInputStreamとして与えることです。ここでバイナリファイルの内容を読み込む高速の方法が正しく動作しない

はバイナリファイルから音声モデルの一部を取得するためのコードです:

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、用のコードです:

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を使用してからth別の方法でも動作する可能性があります。

更新:

ここでの方法によってスローされた例外のスタックトレースです:あなたはPOSModel初期化によってスローされた例外について、より詳細に行かなくても

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

'POSModel'の初期化は' IOException'をスローしますか?あなたはスタックトレースを共有できますか? – oldrinb

+0

toByteArrayを呼び出すときに、ストリーム全体がすでに配列にコピーされています。 – lionscribe

+1

'ByteBufferInputStream'と' ByteBuffer'とバイト配列を取り除き、 '元の*ストリームを' POSModel'のコンストラクタに直接渡します。それが十分に速くない場合は、 'BufferedInputStream'でラップしてください。これらの余分な偽善者は時間と空間を無駄にし、バグを導入するだけです。 – EJP

答えて

0

が、私は少しを提案することができますここでは簡略化のために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を試してみましょう。

+0

助けてくれてありがとう。私がBufferedInputStreamを使用しなかったのは、BufferedInputStreamの速度が通常のInputStreamの速度とほぼ同じであったからです。 – Me2

+1

@ Me2これは、入力ストリームがすでにバッファされていることを示します。 – EJP

+2

5MBのリソースを読み取るのに20秒近くかかることはありません。あなたが持っている問題は、POSModelの内部にあるようです。あなたがバッファで何をしていても、役立たないでしょう。 – lionscribe