版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/aiynmimi/article/details/89188874
报错情况
Android在使用Assets目录下的资源文件,读取报错:Java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed
。之前,没有见到过这种错误!
我这里使用了TensorFlow Lite文件,后缀为.tflite,在使用AssetsManager加载的时候,就报了这个错!
解决方案
我在Stack Overflow上找到一个答案:
java-io-filenotfoundexception-this-file-can-not-be-opened-as-a-file-descriptor
其中第一个回答,简单介绍了为什么会出现这种情况,就是asset中的文件,aapt会选择性的对其进行压缩,以减少apk的大小,那么当你使用下边代码去加载得到一个MappedByteBuffer
:
AssetFileDescriptor fileDescriptor = assets.openFd(modelFilename);
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
就会报错,因为它已经被压缩了!
其中回答中的一篇引文,对这个问题讲解的很清楚:
Dealing with Asset Compression in Android Apps
在aapt的源码中,Package.cpp
文件列出了默认不压缩的文件后缀:
/* these formats are already compressed, or don't compress well */
static const char* kNoCompressExt[] = {
".jpg", ".jpeg", ".png", ".gif",
".wav", ".mp2", ".mp3", ".ogg", ".aac",
".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
".amr", ".awb", ".wma", ".wmv"
};
也就是说,上边列出的文件后缀,aapt则不对其进行压缩!
然后,就是在第二个回答中,则给出了非常简单的一个解决方案:
就是在build.gradle
中的android{}
块内添加:
android {
...
aaptOptions {
noCompress "tflite" //表示不让aapt压缩的文件后缀
}
...
}