java.io.FileNotFoundException:此文件无法作为文件描述符打开; 它可能是压缩的

ihu*_*cos 37 java android filenotfoundexception cordova

我正在编写一个来自android的音板.问题是有些声音有效,有些无效.这是我得到的声音的回溯不起作用

05-31 13:23:04.227 18440 18603 W System.err: java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed
05-31 13:23:04.227 18440 18603 W System.err:    at android.content.res.AssetManager.openAssetFd(Native Method)
05-31 13:23:04.227 18440 18603 W System.err:    at android.content.res.AssetManager.openFd(AssetManager.java:331)
05-31 13:23:04.227 18440 18603 W System.err:    at com.phonegap.AudioPlayer.startPlaying(AudioPlayer.java:201)
05-31 13:23:04.227 18440 18603 W System.err:    at com.phonegap.AudioHandler.startPlayingAudio(AudioHandler.java:181)
05-31 13:23:04.235 18440 18603 W System.err:    at com.phonegap.AudioHandler.execute(AudioHandler.java:64)
05-31 13:23:04.235 18440 18603 W System.err:    at com.phonegap.api.PluginManager$1.run(PluginManager.java:86)
05-31 13:23:04.235 18440 18603 W System.err:    at java.lang.Thread.run(Thread.java:1096)
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

ano*_*non 72

您可以为某些扩展禁用资产压缩,如下所示:

android {
    aaptOptions {
        noCompress "pdf"
    }
}
Run Code Online (Sandbox Code Playgroud)

资源

  • 您可以使用以下命令验证哪些条目已压缩:“unzip -lv MyApplication.apk”“方法”列中的“存储”表示文件未压缩。 (2认同)

Nic*_*ong 35

在assets文件夹中打开压缩文件有一个限制.这是因为未压缩文件可以直接内存映射到进程虚拟地址空间,因此避免再次需要相同数量的内存进行解压缩.

在Android应用中处理资产压缩讨论了处理压缩文件的一些技巧.您可以aapt通过使用未压缩的扩展(例如mp3)来欺骗不压缩文件,或者您可以手动将它们添加到apk不压缩而不是aapt完成工作.

  • 在浪费了几个小时之后,我终于设法从原始而不是资产中读取文件,它们不再是"未压缩"的. (2认同)

dev*_*jay 14

人们正在使用Tensorflow Lite文件运行此问题,

将以下行添加到android {}中的Gradle文件中。

aaptOptions {
    noCompress "tflite"
}
Run Code Online (Sandbox Code Playgroud)


Fre*_*aya 9

您应该禁用该文件的压缩。只需添加:

    aaptOptions {
       noCompress "your-file-name"
    }
Run Code Online (Sandbox Code Playgroud)

到你的应用级build.gradle文件里面android { }


ska*_*man 5

之所以会出现这种明显令人恼火的情况,是因为在.apk构建时,某些资产在存储之前会被压缩,而其他资产则被视为已经压缩过(例如图像、视频)而被置之不理。后一组可以使用打开openAssetFd,前一组不能 - 如果你尝试,你会得到“这个文件不能作为文件描述符打开;它可能被压缩”错误。

一种选择是欺骗构建系统不压缩资产(请参阅@nicstrong 答案中的链接),但这很繁琐。最好尝试以更可预测的方式解决问题。

我想出的解决方案使用的事实是,虽然您无法AssetFileDescriptor为资产打开 ,但您仍然可以打开InputStream. 您可以使用它来将资产复制到应用程序的文件缓存中,然后为此返回一个描述符:

@Override
public AssetFileDescriptor openAssetFile(final Uri uri, final String mode) throws FileNotFoundException
{
    final String assetPath = uri.getLastPathSegment();  // or whatever

    try
    {
        final boolean canBeReadDirectlyFromAssets = ... // if your asset going to be compressed?
        if (canBeReadDirectlyFromAssets)
        {
            return getContext().getAssets().openFd(assetPath);
        }
        else
        {
            final File cacheFile = new File(getContext().getCacheDir(), assetPath);
            cacheFile.getParentFile().mkdirs();
            copyToCacheFile(assetPath, cacheFile);
            return new AssetFileDescriptor(ParcelFileDescriptor.open(cacheFile, MODE_READ_ONLY), 0, -1);
        }
    }
    catch (FileNotFoundException ex)
    {
        throw ex;
    }
    catch (IOException ex)
    {
        throw new FileNotFoundException(ex.getMessage());
    }
}

private void copyToCacheFile(final String assetPath, final File cacheFile) throws IOException
{
    final InputStream inputStream = getContext().getAssets().open(assetPath, ACCESS_BUFFER);
    try
    {
        final FileOutputStream fileOutputStream = new FileOutputStream(cacheFile, false);
        try
        {
            //using Guava IO lib to copy the streams, but could also do it manually
            ByteStreams.copy(inputStream, fileOutputStream); 
        }
        finally
        {
            fileOutputStream.close();
        }
    }
    finally
    {
        inputStream.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

这确实意味着您的应用程序将保留缓存文件,但这很好。它也不会尝试重新使用您可能关心或可能不关心的现有缓存文件。


Q L*_*ker 5

可以通过调用以下方法抛出此异常:

final AssetFileDescriptor afd = activity.getAssets().openFd(path);
Run Code Online (Sandbox Code Playgroud)

res/raw我通过将文件保存在目录而不是资产文件夹中解决了问题,然后AssetFileDescriptor以这种方式获取:

final AssetFileDescriptor afd = activity.getResources().openRawResourceFd(rawId);
Run Code Online (Sandbox Code Playgroud)

然后 就FileNotFoundException消失了,文件不再被压缩。