6
votes

File.Cooding n'a aucun effet, la variable d'environnement LC_All fait-elle

Dans le programme Java suivant s'exécutant sous Linux à l'aide de OpenJDK 1.6.0_22, je liste simplement le contenu du répertoire effectué sous forme de paramètre à la ligne de commande. Le répertoire contient les fichiers qui ont des noms de fichiers dans UTF-8 (par exemple hindi, mandarin, allemand, etc.).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>

int main(int argc, char *argv[])
{
    char *argdir = argv[1];
    DIR *dp = opendir(argdir);
    struct dirent *de;
    while(de = readdir(dp)) {
        char *abspath = (char *) malloc(strlen(argdir)  + 1 + strlen(de->d_name) + 1);
        strcpy(abspath, argdir);
        abspath[strlen(argdir)] = '/';
        strcpy(abspath + strlen(argdir) + 1, de->d_name);
        printf("%d %s ", de->d_type, abspath);
        FILE *fp = fopen(abspath, "r");
        if (fp) {
            printf("Success");
        }
        fclose(fp);
        putchar('\n');
    }
}


4 commentaires

Je ne suis pas sûr de savoir qui est responsable de décoder les arguments de la ligne de commande. Pourrait être la coquille, pourrait être Java. Est-ce que cela fonctionne comme prévu si vous obtenez le nom de fichier de quelque part ailleurs (chaîne littéral ou lecture de stdin ou à partir d'un fichier de propriétés)?


Pourquoi faites-vous le abspath danse? Juste à des fins de démonstration ici? Vous pouvez faire F.ListFiles () au lieu de F.List () pour obtenir des objets de fichier directement (cela fonctionne probablement).


@Thilo son juste un exemple de programme.


@Thilo: Il semble que le sun.jnu.encoding mentionné dans la question affecte l'interprétation de la ligne de commande. Dans un LC_CTYPE = POSIX SETUP, mais avec une borne UTF-8, si je passe -dsun.jnu.encoding = uf-8 , le caractère non ASCII d'un L'argument de ligne de commande est imprimé comme un seul ? même quand il est deux octets. Si je passe -dfile.encoding = utf-8 aussi, il est également imprimé comme UTF-8. Si je ne passe que ce dernier, alors je reçois deux glyphes de symbole non disponibles non disponibles imprimés.


3 Réponses :


5
votes

Je ne suis pas sûr où vous lisez sur fichier.ex. / code>. Je ne vois pas que cela a mentionné avec l'autre Propriétés standard telles que documentées avec system.geproperties . Mais à en juger de mes expériences, il semble que cette valeur influence l'encodage du fichier contenu , pas de noms . system.out en particulier n'imprimera pas les caractères non-ASCII si fichier.encoding est posix . .

D'autre part, la manière Linux de décider quel codage s'applique aux noms de fichiers est le lc_ctype facette du paramètre locale actuel. Je ne vois aucune raison pour laquelle Java devrait remplacer cela. Autant d'autres plates-formes (Windows en particulier) utilisent toujours UNICODE pour les noms de fichiers, pas d'octets, il est peu de point dans l'exposition des détails de niveau d'octet du système de fichiers à une application Java.


2 commentaires

Merci :) Lien supplémentaire: Publib .Boulder.ibm.com / Infocenter / Iseries / V5R3 / ...


Les noms de fichier sont (dans les JVM Oracle et OpenJDK) concernés par la propriété "Sun.jnu.encoding". Voir happygiraffe.net/blog/2009/09/24/java- codage de la plate-forme



10
votes

note: enfin, je pense que je l'ai cloué. Je ne confirmant pas que c'est juste. Mais avec une lecture du code et des tests, c'est ce que j'ai découvert et je n'ai pas de temps supplémentaire pour y examiner. Si quelqu'un est intéressé, ils peuvent le vérifier et dire si cette réponse est bonne ou mal - je serais heureux :)

La référence que j'ai utilisée était de cette archive disponible sur le site de OpenJDK: openjdk-6-src-b25-01_may_2012.tar.gz

  1. Java traduit toute la chaîne en codage local de la plate-forme dans cette méthode: JDK / SRC / Share / Native / Common / JNI_UTIL.C - JNU_GETSRINGPLATFORDS () . Propriété système sun.jnu.encoding est utilisé pour déterminer le codage de la plate-forme.

  2. La valeur de sun.jnu.encoding est définie sur jdk / src / solaris / natif / java / lang / java_props_md.c - getjavaproperties () Utilisation de SetLocale () Méthode de libc. Variable d'environnement lc_all est utilisé pour définir la valeur de sun.jnu.encoding . Valeur donnée à l'invite de commande à l'aide de -dsun.jnu.encoding à Java est ignoré.

  3. appel à fichier.exists () a été codé dans le fichier jdk / src / partage / classes / java / io / fichier.java et son retour comme

    retour ((fs.getboolatianattributes (this) et fichiersystem.ba_existes)! = 0);

  4. getboolcanattributes () est codé de manière native (et je saute des étapes dans le code de la navigation dans de nombreux fichiers) dans JDK / SRC / Share / natif / java / io / UNIXFileSystem_md. C en fonction: Java_Java_IO_unixFileSystem_getboolAnattributes0 () . Ici la macro with_field_platform_string (env, fichier, ids.path, chemin) convertit la chaîne de chemin sur le codage de la plate-forme.

  5. La conversion en mauvais état en un codage incorrect enverra une mauvaise chaîne C (tableau de caractères de caractère) à l'appel ultérieur à Stat () méthode. Et il retournera avec le résultat que le fichier ne peut pas être trouvé.

    Leçon: lc_all est très important


0 commentaires

2
votes

S'il vous plaît voir bug 4163515 sur java.com. Il explique que:

  1. File.Cooding est spécifique à la mise en œuvre Sun (Maintenant Oracle) de JVM - Autres ne peut pas le soutenir
  2. sera considéré comme en lecture seule
  3. Pour le changer, vous modifierez l'environnement dans lequel le JVM fonctionne (ce que vous avez fait avec LC_ALL)

    Notez également que même si modification de fichier.Cooding "fonctionne" pour votre plate-forme, vous ne le ferez pas - car il ne modifie pas le codage par défaut utilisé par Oracle JVM en général, mais uniquement dans certains sous-systèmes. Lorsque l'insecte affiche le codage par défaut utilisé par les constructeurs de chaînes prenant des matrices d'octets ne sont pas affectés par ce paramètre.


0 commentaires