web-dev-qa-db-fra.com

Vérifier si un fichier existe avant d'appeler openFileInput

Pour lire un fichier sous Android à partir de la zone de stockage privée de votre application, utilisez la fonctionopenFileInput()

Ma question est la suivante: existe-t-il un moyen de vérifier si ce fichier existe avant d'appeler cette fonction? La fonction peut lancer une FileNotFoundException, mais j'ai envie d'appeler ceci puis de faire quelque chose basé sur une try-catch est une mauvaise pratique.

Utiliser File.exist() semble être une chose étrange à utiliser également, car il faudrait instancier une classe et je ne suis pas sûr si le simple fait de lui donner le nom du fichier l’obtiendrait pour le trouver dans la zone privée de mon téléphone.

21
Pieces
public boolean fileExists(Context context, String filename) {    
    File file = context.getFileStreamPath(filename);
    if(file == null || !file.exists()) {
        return false;
    }
    return true;
}

MODIFIER:

En outre, voici une autre manière de classer des fichiers dans un stockage externe.

String fileUrl = "/appname/data.xml";
String file = Android.os.Environment.getExternalStorageDirectory().getPath() + fileUrl;
File f = new File(file);

if(f.exists())
return;
46
coder_For_Life22

La fonction peut passer par une exception FileNotFoundException, mais j'ai envie d'appeler ceci puis de faire quelque chose en fonction d'un catch try est une mauvaise pratique.

Je ne suis pas d'accord. OMI, il teste si le fichier existe avant l'ouverture est une mauvaise pratique. Comparez ces deux versions du code:

File f = new File("someFile");
InputStream is;

Version 1

if (f.exists()) {
    is = new FileInputStream(f);
    ...
} else {
    System.err.println("Doesn't exist");
}

Version 2

try {
    is = new FileInputStream(f);
    ...
} catch (FileNotFoundException ex) {
    System.err.println("Doesn't exist");
}

Il y a un certain nombre de problèmes avec la première version:

  • La version n ° 1 effectue un appel système supplémentaire lorsque vous appelez f.exists(). Cela ralentit la première version en moyenne, sauf s’il existe une forte probabilité que le fichier n’est pas existe.

  • La version 1 a une condition de concurrence. Si un processus externe supprime le fichier à peu près au même moment, vous pourriez vous retrouver avec file.exists() retournant true, puis le constructeur FileInputStream lançant FileNotFoundException. C'est le type de condition de concurrence critique qui peut être exploitée pour casser la sécurité si le fichier en question est critique pour la sécurité. (En fait, il existe également une deuxième condition de concurrence: le fichier est en cours de création et file.exists() renvoie False lorsqu'une tentative d'ouverture ultérieure réussira. Cette condition de concurrence est probablement inoffensive.)

Un autre problème est que le FileInputStream est déclaré comme jetant IOException. Tester pour voir si le fichier existe ne traite que l’un des modes de défaillance possibles. Votre code va devoir attraper et traiter ces autres IOExceptions de toute façon.


@Pieces a commenté:

Les exceptions devraient être pour lorsque quelque chose se passe réellement sur lequel vous n'avez aucun contrôle. Dans ce cas, j'ai le contrôle complet sur elle.

En fait, vous n’avez pas un contrôle total sur cela. Certainement pas dans le cas général. Même dans votre cas d'utilisation particulier, la situation de concurrence critique est toujours possible en théorie. 

Mais le vrai problème avec cette ligne de pensée est que vous finissez par sauter les étapes pour éviter les exceptions dans les situations où les exceptions/la gestion des exceptions sont la solution la meilleure. Cela rend le code plus compliqué, moins lisible et potentiellement plus lent et/ou plus fragile.

Le dogme normal va comme ceci:

"Les exceptions ne doivent être utilisées que dans des situations exceptionnelles".

Ce n'est pas la même chose que de dire ce que vous avez dit. Le mot "exceptionnel" signifie simplement "pas normal". Cela a un sens beaucoup plus large que "quelque chose qui ne va vraiment pas sur lequel vous n'avez aucun contrôle".

J'ai tendance à développer le dogme comme suit:

  • Les exceptions ne devrait pas être utilisées pour le contrôle de flux normal.

  • Les exceptions ne devraient pas être utilisées si elles s'avèrent trop chères en moyenne.

  • Les exceptions devraient être utilisées si les tests que vous utiliseriez pour les éviter ne sont pas fiables.

  • Les exceptions devraient sont utilisées si les tests que vous souhaitez utiliser pour les éviter sont trop coûteux en moyenne.

  • Les exceptions devraient être utilisées si elles simplifient considérablement votre code (modulo ci-dessus). Et le critère de simplicité est de savoir si le code est lisible par un programmeur Java moyen.

(Remarque - "en moyenne" et "aussi cher" ...)

Maintenant, on peut discuter jusqu’à ce que les vaches rentrent à la maison à propos d’un événement {exceptionnel}, mais j’estime qu’il s’agit en réalité d’équilibrer la simplicité relative des approches (dans le contexte) et la moyenne coûts de performance (dans le contexte). Toute règle dogmatique qui ne tient pas compte des compromis et du contexte vous fera du mal dans certains cas.

30
Stephen C

Ce travail pour moi.

try {
  FileInputStream fis = openFileInput(String filename);
  // ... do something
try {
    fis.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
} catch (FileNotFoundException e) { 
  e.printStackTrace();
}

mais il arrive que, parfois, il retourne une exception identique… en travaillant avec adb.

0
rfellons