java.io.FileNotFoundException:该文件不能作为文件描述符打开它可能被压缩了

如何解决java.io.FileNotFoundException:该文件不能作为文件描述符打开它可能被压缩了

| 我正在从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)
有任何想法吗?     

解决方法

        在资产文件夹中打开压缩文件存在限制。这是因为未压缩的文件可以直接内存映射到进程的虚拟地址空间,因此避免了再次需要相同数量的内存进行解压缩。 在Android Apps中处理资产压缩讨论了一些处理压缩文件的技术。您可以通过使用未压缩的扩展名(例如
mp3
)来欺骗ѭ1not不压缩文件,或者您可以将它们手动添加到
apk
中而不进行压缩,而不是让
aapt
完成工作。     ,        您可以为某些扩展名禁用资产压缩,如下所示:
android {
    aaptOptions {
        noCompress \"pdf\"
    }
}
资源     ,        人们正在使用Tensorflow Lite文件运行此问题, 将以下行添加到android {}中的Gradle文件中。
aaptOptions {
    noCompress \"tflite\"
}
    ,        之所以会出现这种令人恼火的情况,是因为在构建“ 7”时,有些资产在存储之前会被压缩,而另一些资产则被视为已压缩(例如,图像,视频)并被单独放置。后一组可以使用ѭ8opened打开,前一组则不能-如果尝试尝试,则会出现\“此文件无法作为文件描述符打开;可能已压缩\”错误。 一种选择是欺骗构建系统以使其不压缩资产(请参阅@nicstrong的答案中的链接),但这很奇怪。最好以更可预测的方式尝试解决该问题。 我提出的解决方案使用的事实是,虽然您无法为资产开价9英镑,但仍然可以开10英镑。您可以使用它来将资产复制到应用程序的文件缓存中,然后返回该描述符的描述:
@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),-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();
    }
}
这确实意味着您的应用将保留缓存文件,但这很好。它还不会尝试重复使用您可能会或不会在意的现有缓存文件。     ,        只需添加:
    aaptOptions {
       noCompress \"your-file-name\"
    }
到您的build.gradle文件。     ,        仅当尝试打开
FileDesriptor
时,才应获得此异常。仅读取文件,您可以通过
InputStream
AssetManager.open(\"filename.ext\")
)。这对我有用。 如果事先需要文件大小,则需要
FileDescriptor
(因此需要一个未压缩的文件)来调用其
getLength()
方法,否则必须读取整个流以确定其大小。     ,        我已经走了一圈,我用:
ParcelFileDescriptor mFileDescriptor = context.getAssets().openFd(file).getParcelFileDescriptor();
但是返回:java.io.FileNotFoundException:该文件不能作为文件描述符打开;不能将其作为文件描述符打开。它可能被压缩了。 代替此实现,我直接使用ParcelFileDescriptor形式的函数打开文件。
private void openRenderer(Context context,String fileName) throws IOException {  

File file=  FileUtils.fileFromAsset(context,fileName);
        ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.open(file,ParcelFileDescriptor.MODE_READ_WRITE); 

        mPdfRenderer = new PdfRenderer(parcelFileDescriptor);
    }`

    public class FileUtils {
    private FileUtils() {
    }

    public static File fileFromAsset(Context context,String assetName) throws IOException {
        File outFile = new File(context.getCacheDir(),assetName );
        copy(context.getAssets().open(assetName),outFile);

        return outFile;
    }

    public static void copy(InputStream inputStream,File output) throws IOException {
        FileOutputStream outputStream = null;

        try {
            outputStream = new FileOutputStream(output);
            boolean read = false;
            byte[] bytes = new byte[1024];

            int read1;
            while((read1 = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes,read1);
            }
        } finally {
            try {
                if(inputStream != null) {
                    inputStream.close();
                }
            } finally {
                if(outputStream != null) {
                    outputStream.close();
                }

            }

        }

    }
}
    ,        可以通过调用以下方法引发此异常:
final AssetFileDescriptor afd = activity.getAssets().openFd(path);
我通过将文件保存在
res/raw
目录而不是资产文件夹中来解决此问题,然后通过以下方式获取get9ѭ:
final AssetFileDescriptor afd = activity.getResources().openRawResourceFd(rawId);
然后ѭ24消失了,该文件不再压缩。     ,        如果要从资产文件夹中获取的文件大于1MB,那么对我有用的是将文件压缩为zip文件,然后在使用前将其解压缩,然后将其存储在未压缩的外部存储中。
InputStream fileInputStream = getAssets().open(\"your_file.your_file_extension.zip\");
unzipInputStream(fileInputStream,\"your_folder_in_external_storage\");
我使用的
unzipInputStream
方法是这样的:
public static void unzipInputStream(InputStream inputStream,String location)
{
    try {
        if ( !location.endsWith(File.separator) ) {
            location += File.separator;
        }
        File f = new File(location);
        if(!f.isDirectory()) {
            f.mkdirs();
        }
        ZipInputStream zin = new ZipInputStream(new BufferedInputStream(inputStream,BUFFER_SIZE));
        try {
            ZipEntry ze;
            while ((ze = zin.getNextEntry()) != null) {
                String path = location + ze.getName();
                File unzipFile = new File(path);

                if (ze.isDirectory()) {
                    if(!unzipFile.isDirectory()) {
                        unzipFile.mkdirs();
                    }
                } else {
                    createParentDirectoriesIfMissing(unzipFile);
                    unzipFile(zin,unzipFile);
                }
            }
        } finally {
            zin.close();
        }
    } catch (Exception e) {
        Log.e(\"\",\"Unzip exception\",e);
    }
}

private static void createParentDirectoriesIfMissing(File unzipFile)
{
    File parentDir = unzipFile.getParentFile();
    if ( null != parentDir ) {
        if ( !parentDir.isDirectory() ) {
            parentDir.mkdirs();
        }
    }
}

private static void unzipFile(ZipInputStream zin,File unzipFile) throws IOException
{
    int size;
    byte[] buffer = new byte[BUFFER_SIZE];
    FileOutputStream out = new FileOutputStream(unzipFile,false);
    BufferedOutputStream fout = new BufferedOutputStream(out,BUFFER_SIZE);

    try {
        while ( (size = zin.read(buffer,BUFFER_SIZE)) != -1 ) {
            fout.write(buffer,size);
        }

        zin.closeEntry();
    } finally {
        fout.flush();
        fout.close();
    }
}
    ,        我只是遇到了同样的问题,因为gnome-sound-recorder创建了OGG文件,我无法使用MediaPlayer播放这些文件。因此,我使用ffmpeg将其转换为MP3并成功了。所以我想这是最简单的方法。
ffmpeg -i youroggfile yournewfile.mp3
我还注意到的是,它仍然在资源中显示一个问号,并且当我使用R.raw.yournewfile访问它时,我没有在代码中写入\ .mp3 \扩展名。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-