java.io.FileNotFoundException: этот файл не может быть открыт как дескриптор файла;это вероятно сжато - PullRequest
28 голосов
/ 31 мая 2011

Я программирую деки с 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)

есть идеи?

Ответы [ 8 ]

62 голосов
/ 27 октября 2015

Вы можете отключить сжатие ресурсов для некоторых расширений, например так:

android {
    aaptOptions {
        noCompress "pdf"
    }
}

Источник

31 голосов
/ 31 мая 2011

Существует ограничение на открытие сжатых файлов в папке ресурсов. Это связано с тем, что несжатые файлы могут напрямую отображаться в памяти в виртуальном адресном пространстве процессов, что позволяет избежать повторного сжатия того же объема памяти.

Работа со сжатием активов в приложениях для Android обсуждает некоторые методы работы со сжатыми файлами. Вы можете обмануть aapt, чтобы не сжимать файл, используя несжатое расширение (например, mp3), или вы можете вручную добавить их в apk без сжатия вместо получения aapt для выполнения работы.

4 голосов
/ 26 октября 2018

Просто добавьте:

    aaptOptions {
       noCompress "your-file-name"
    }

В файл build.gradle.

4 голосов
/ 19 июня 2014

Эта явно раздражающая ситуация возникает из-за того, что при построении .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();
    }
}

Это означает, что ваше приложение оставит файлы кеша лежащими, но это нормально.Он также не пытается повторно использовать существующие файлы кэша, которые могут вас не интересовать.

3 голосов
/ 22 июля 2013

Вы должны получить это исключение, только если пытаетесь открыть FileDesriptor.Для того, чтобы просто прочитать файл, вы можете пройти через InputStream (AssetManager.open("filename.ext")).Это сработало для меня.

Если вам нужен заранее размер файла, вам нужен FileDescriptor (и, следовательно, несжатый файл), чтобы вызвать его метод getLength(), в противном случае вы должны прочитать весь поток вопределить его размер.

1 голос
/ 05 сентября 2018

Это исключение можно вызвать, вызвав:

final AssetFileDescriptor afd = activity.getAssets().openFd(path);

Я исправил проблему, сохранив файл в каталоге res/raw вместо папки assets, затем получил AssetFileDescriptor следующим образом:

final AssetFileDescriptor afd = activity.getResources().openRawResourceFd(rawId);

Затем FileNotFoundException исчезает, и файл больше не сжимается.

1 голос
/ 15 июля 2015

Я сделал прогулку, я использую:

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, 0, read1);
            }
        } finally {
            try {
                if(inputStream != null) {
                    inputStream.close();
                }
            } finally {
                if(outputStream != null) {
                    outputStream.close();
                }

            }

        }

    }
}
0 голосов
/ 10 ноября 2018

Если размер файла, который нужно получить из папки ресурсов, превышает 1 МБ, то мне сработало сжатие файла в виде 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, 0, BUFFER_SIZE)) != -1 ) {
            fout.write(buffer, 0, size);
        }

        zin.closeEntry();
    } finally {
        fout.flush();
        fout.close();
    }
}
...