53 votes

java.io.FileNotFoundException : Ce fichier ne peut pas être ouvert en tant que descripteur de fichier ; il est probablement compressé.

Je suis en train de programmer un soundboard à partir d'Android. Le problème est que certains sons fonctionnent, et d'autres pas. Voici le traceback que j'obtiens pour les sons qui ne fonctionnent pas

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)

Des idées ?

107voto

bowmanb Points 599

Vous pouvez désactiver la compression des actifs pour certaines extensions de la manière suivante :

android {
    aaptOptions {
        noCompress "pdf"
    }
}

Source

46voto

DeeJay Points 543

Les personnes travaillant avec le fichier Tensorflow Lite ont rencontré ce problème,

Ajoutez les lignes suivantes à votre fichier Gradle ( android/app/build.gradle ) à l'intérieur du android{} bloc.

aaptOptions {
    noCompress "tflite"
}

45voto

Nic Strong Points 4195

Il y a des limitations à l'ouverture de fichiers compressés dans le dossier assets. En effet, les fichiers non compressés peuvent être mappés directement dans l'espace d'adressage virtuel du processus, ce qui évite d'avoir besoin de la même quantité de mémoire pour la décompression.

Gestion de la compression des ressources dans les applications Android discute de quelques techniques pour traiter les fichiers compressés. Vous pouvez tromper aapt de ne pas compresser le fichier en utilisant une extension qui n'est pas compressée (par ex. mp3 ) ou vous pouvez les ajouter manuellement au apk sans compression au lieu d'obtenir aapt pour faire le travail.

9voto

frederick nyawaya Points 1234

Vous devez désactiver la compression pour ce fichier. Il suffit d'ajouter :

    aaptOptions {
       noCompress "your-file-name"
    }

Au niveau de votre application build.gradle fichier à l'intérieur android { }

5voto

skaffman Points 197885

Cette situation très irritante est due au fait que, lorsque le .apk est construit, certains actifs sont compressés avant d'être stockés, tandis que d'autres sont traités comme étant déjà compressés (par exemple, les images, les vidéos) et sont laissés tels quels. Ce dernier groupe peut être ouvert à l'aide de openAssetFd Le premier groupe ne le peut pas - si vous essayez, vous obtenez l'erreur "This file can not be opened as a file descriptor ; it is probably compressed" (Ce fichier ne peut pas être ouvert en tant que descripteur de fichier ; il est probablement compressé).

Une option est de tromper le système de construction pour qu'il ne compresse pas les actifs (voir le lien dans la réponse de @nicstrong), mais c'est délicat. Il vaut mieux essayer de contourner le problème de manière plus prévisible.

La solution que j'ai trouvée utilise le fait que, bien que vous ne puissiez pas ouvrir un AssetFileDescriptor pour l'actif, vous pouvez toujours ouvrir un InputStream . Vous pouvez l'utiliser pour copier la ressource dans le cache de fichiers de l'application, puis renvoyer un descripteur à cet effet :

@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();
    }
}

Cela signifie que votre application laissera traîner des fichiers de cache, mais ce n'est pas grave. Elle n'essaie pas non plus de réutiliser les fichiers de cache existants, ce qui n'est pas forcément important pour vous.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X