FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed

2019年4月11日 18点热度 0条评论 来源: 木大白易

报错情况

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压缩的文件后缀
    }
	...
}
    原文作者:木大白易
    原文地址: https://blog.csdn.net/aiynmimi/article/details/89188874
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。