私は初心者の Android プログラマーで、AssetManager からアセットを読み取るためのさまざまな方法を使用する際に奇妙な問題に遭遇しました。
この問題を示すサンプル コードを以下に添付しました。「hello」を含む単純なテキスト ファイル アセット (「hello.txt」) を読み取ります。生のバイトとして読み込み、文字の 16 進値 (68 65 6c 6c 6f) を出力します。
私が試した方法は次のとおりです(コードの順序で):
- AssetFileDescriptor (AFD) を開き、InputStream を作成します: 最初の 3 バイトのみを読み取ります (68 65 6c ffffffff ffffffff)
- AFD を開き、基になるファイル記述子を取得し、FileInputStream を作成します: 完全に間違ったデータ (50 4b 3 4 a)
- InputStream を直接開く: 正しい (68 65 6c 6c 6f)
また、同じ 3 つの方法を繰り返しました。今回は最初にバイト配列に読み込みます。これにより (驚くべきことに!) 最初の結果が変更されますが、それ以外は同じ結果が得られます (便宜上、ここで繰り返します)。
- AFD を開き、InputStream を作成し、最初にバイト配列に読み込みます: 正しい (68 65 6c 6c 6f)
- AFD を開き、基になるファイル記述子を取得し、FileInputStream を作成し、最初にバイト配列に読み込みます: 完全に間違ったデータ (50 4b 3 4 a)
- InputStream を直接開き、最初にバイト配列に読み込みます: 正しい (68 65 6c 6c 6f)
最初のケース (3 バイトのみが読み込まれる場合) を除いて、他のケースでは正確に 6 バイト (末尾の改行を含む) が読み込まれ、その後は予想どおり -1 が返されることに注意してください。これには、間違ったデータが読み込まれた場合も含まれます。
誰もこれに遭遇したことがありますか?これはバグですか、それとも何か間違ったことをしましたか?
ありがとう!
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
AssetManager am = getAssets();
StringBuilder sb = new StringBuilder();
try {
AssetFileDescriptor afd = am.openFd("hello.txt");
InputStream instream = afd.createInputStream();
sb.append(String.format("afd.createInputStream(): %x %x %x %x %x\n", instream.read(), instream.read(), instream.read(), instream.read(), instream.read()));
instream.close();
afd.close();
}
catch (IOException e) {
throw new RuntimeException(e);
}
try {
AssetFileDescriptor afd = am.openFd("hello.txt");
InputStream instream = new FileInputStream(afd.getFileDescriptor());
sb.append(String.format("new FileInputStream(afd): %x %x %x %x %x\n", instream.read(), instream.read(), instream.read(), instream.read(), instream.read()));
instream.close();
afd.close();
}
catch (IOException e) {
throw new RuntimeException(e);
}
try {
InputStream instream = am.open("hello.txt");
sb.append(String.format("am.open(): %x %x %x %x %x\n", instream.read(), instream.read(), instream.read(), instream.read(), instream.read()));
instream.close();
}
catch (IOException e) {
throw new RuntimeException(e);
}
try {
AssetFileDescriptor afd = am.openFd("hello.txt");
InputStream instream = afd.createInputStream();
byte[] b = new byte[instream.available()];
instream.read(b);
sb.append(String.format("afd.createInputStream() -> byte[]: %x %x %x %x %x\n", b[0], b[1], b[2], b[3], b[4]));
instream.close();
afd.close();
}
catch (IOException e) {
throw new RuntimeException(e);
}
try {
AssetFileDescriptor afd = am.openFd("hello.txt");
InputStream instream = new FileInputStream(afd.getFileDescriptor());
byte[] b = new byte[(int) afd.getLength()];
instream.read(b);
sb.append(String.format("new FileInputStream(afd) -> byte[]: %x %x %x %x %x\n", b[0], b[1], b[2], b[3], b[4]));
instream.close();
afd.close();
}
catch (IOException e) {
throw new RuntimeException(e);
}
try {
InputStream instream = am.open("hello.txt");
byte[] b = new byte[instream.available()];
instream.read(b);
sb.append(String.format("am.open() -> byte[]: %x %x %x %x %x\n", b[0], b[1], b[2], b[3], b[4]));
instream.close();
}
catch (IOException e) {
throw new RuntimeException(e);
}
// print result
TextView textview = (TextView) findViewById(R.id.textview);
textview.setText(sb.toString());
Log.d("blah", sb.toString());
}