IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Problème getc avec unicode


Sujet :

C

  1. #1
    Candidat au Club
    Inscrit en
    Juin 2008
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Problème getc avec unicode
    Bonjour tout le monde.
    Alors voilà, j'ai un souci avec une petite fonction de mon crû, qui est censée simplement stocker un fichier texte dans une chaîne de caractère, afin de pouvoir traiter cette dernière (extraction d'infos intéressantes). Voici mon code (et désolé si il y avait une façon plus simple/élégante de faire la même chose, je suis pas un pro en prog ) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
     
    int lectureFichier (char nom_fic[], char *ad) {
        char carac = 0;
        FILE* input=fopen(nom_fic,"r");
        fseek (input, 2, SEEK_SET);  //pour éviter les 2 premiers caractères du fichier, qui sont inutiles
        if (input != NULL)
        {
           carac=fgetc(input);
           do
            {
                if (carac != 0){
                if (carac != 10){
                if (carac != 13){
                    *ad = carac;
                }}}
                carac=fgetc(input);
                ad++;
                } while (carac != EOF); 
            fclose(input);
        }
        return 0;
    }
     
     
    void main() {
        char nom_fic[50] = "Mayhem.TextGrid";
        char ana[10000];
        lectureFichier (nom_fic, ana);
        int taille = strlen (ana);
        printf ("longueur du texte = %d lettres\n", taille);
        printf ("%s", ana);
    }
    Bon, ce petit truc marche très correctement sur la plupart fichiers textes que j'essaie, sauf avec ceux qui sont en Unicode (pas de pot, c'est justement des fichiers en unicode que je dois traiter).
    En gros, si le fichier est en unicode, rien n'est stocké dans ma chaine ana, à la fin elle est de taille 0 et vide !

    Quelqu'un aurait-il une idée du pourquoi, et surtout, une piste pour me dépêtrer de ce problème qui m'ennuie depuis un petit moment ?

    Merci !

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 578
    Points
    41 578
    Par défaut
    1. fseek() utilisé ainsi n'est pas garanti marcher pour un fichier ouvert en mode texte. Franchement, pour sauter deux caractères, appeler deux fois fgetc() est plus simple et est portable...
    2. Quel genre d'unicode ? UTF-8 ? UCS-2/UTF-16 ?
    3. fgetc() retourne un int. Si tu utilises un char, le caractère 0xFF est confondu avec EOF...

  3. #3
    Candidat au Club
    Inscrit en
    Juin 2008
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Whaou merci pour cette réponse ultra-rapide !
    Alors les précisions :

    en fait je n'ai pas écris dans le code que j'ai donné ce que j'ai fait pour trouver le problème : je faisais un printf de *ad juste après son assignation à l'intérieur de la boucle, et ça marche, ça donne le bon caractère.

    Donc 1 : je ne pense pas que le problème vienne de là, le fseek marche bien et saute bien les caractères de signature.

    2 : alors je n'ai pas trouvé exactement, juste que c'était du unicode big endian (commence par -2 -1 0 si on convertit en ASCII (enfin c'est ce qu'il me sort)).

    3 : Le problème doit bien être quelque chose du genre, mais ça voudrait dire que ma sortie de boucle se ferait de façon inadéquate, or, cf plus haut, ma boucle s'arrête bien à la fin du fichier...

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 578
    Points
    41 578
    Par défaut
    Ah, OK, j'avais mal vu.
    Sur de l'unicode big-endian, si le premier caractère est un caractère ISO-8859-1, alors le premier octet est nul. Cela met en évidence l'erreur de ton printf: Tu cherches à afficher des caractères UCS-2 ou UTF-16 comme si c'étaient des caractères ASCII étendus...

    Utilise wprintf() à la place de printf() quand le fichier est en UCS-2/UTF-16.

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Juste une remarque en passant, tu fais un fseek(2) pour sauter les 2 premiers caractères mais il n'est pas dit que ces 2 caractères soit présents (voir le fichier en attachement).

    Il me semble que le mieux est de lire ces 2 caractères et de tester leur valeur pour savoir si tu dois les ignorer.

    Ma remarque à 0,01€
    Fichiers attachés Fichiers attachés

  6. #6
    Candidat au Club
    Inscrit en
    Juin 2008
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Euh, pour répondre à ram_0000, je dirais que je suis vraiment sûr que ces deux caractères sont présents, le but de mon programme n'étant pas de traiter de façon générique tous les textes, mais seulement des textes très spécifiques, tous en unicode.

    Sinon, j'avais déjà essayé d'utiliser des widecharacters à la place des char, de cette façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    int lectureFichier (char nom_fic[], char *ad) {
        wchar_t carac = 0;
        FILE* input=fopen(nom_fic,"r");
        fseek (input, 2, SEEK_SET);
        if (input != NULL)
        {
           carac=fgetwc(input);
           do
            {
                if (carac != 0){
                if (carac != 13){
                *ad = carac;
                wprintf("%c", *ad);
                }
                }
                carac=fgetwc(input);
                ad++;
            } while (carac != WEOF ); 
             fclose(input);
        }
        return 0;
    }
     
     
    void main() {
        char nom_fic[50] = "Mayhem.TextGrid";
        printf ("%s\n", nom_fic);
        wchar_t ana[10000];
        lectureFichier (nom_fic, ana);
        int taille = strlen (ana);
        printf ("longueur du texte = %d lettres\n", taille);
        printf ("%s", ana);
    }
    ce qui ne me donnait rien du tout. J'ai également essayé toutes les combinaisons entre les wprintf, les wchar_t et les printf et char, sans arriver à rien de mieux : rien n'est stocké dans ma chaîne de valeurs ana....
    Du coup je me demande si je ne fais pas fausse route sur ma méthode, et si il n'existe pas d'autres techniques pour analyser un fichier texte. Mon idée à moi était de passer par une première phase d'extraction des caractères de mon fichier vers une chaîne unique avant de d'utiliser les fonctions adéquates pour en sortir seulement certains éléments. Qu'en pensez-vous?

  7. #7
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par Lota123 Voir le message
    Euh, pour répondre à ram_0000, je dirais que je suis vraiment sûr que ces deux caractères sont présents, le but de mon programme n'étant pas de traiter de façon générique tous les textes, mais seulement des textes très spécifiques, tous en unicode.
    Crois en mon expérience, ce qui peut arriver arrivera et toujours au pire moment.
    C'est toujours quand il pleut que tu crèves une roue et que tu t'apercoit que le pneu de secours est dégonflé.

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 578
    Points
    41 578
    Par défaut
    En effet, ça ne marchera pas non plus, sauf si tu utilises une certaine extension Microsoft sous Windows.
    Pour lire des caractères unicode 16 bits en C standard, tu dois lire les octets toi-même.
    Je n'ai pas testé, mais ça doit être un truc de ce genre:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    #include <stdio.h>
    #include <wchar.h>
     
    int lectureFichier (char const *nom_fic, wchar_t *ad) {
    	FILE* input=fopen(nom_fic,"r");
    	if (input != NULL)
    	{
    		int byte1 = 0;
    		int byte2 = 0;
    		/* Sauter les deux premiers bytes */
    		fgetc(input);
    		fgetc(input);
     
    		byte1=fgetc(input);
    		byte2=fgetc(input);
    		while(byte1 != EOF && byte2 != EOF)
    		{
    			/* big-endian */
    			int wcaracval = ((byte1 << 8) || byte2);
    			wchar_t wcarac = (wchar_t)wcaracval;
    			if (wcarac != 0){
    				if (wcarac != 13){
    	            			*ad = wcarac;
    					wprintf(L"%c", *ad);
    					ad++;
    				}
    			}
    			byte1=fgetc(input);
    			byte2=fgetc(input);
    		}
    		fclose(input);
    	}
    	return 0;
    }
     
     
    int main(void) {
    	wchar_t ana[10000];
    	char const *nom_fic = "Mayhem.TextGrid";
    	size_t taille;
     
    	printf ("%s\n", nom_fic);
    	lectureFichier (nom_fic, ana);
    	taille = wcslen(ana);
    	printf ("longueur du texte = %d lettres\n", taille);
    	wprintf(L"%s", ana);
    	return 0;
    }

  9. #9
    Candidat au Club
    Inscrit en
    Juin 2008
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Oui tout à fait, c'est quelque chose dans le genre... En fait je viens de résoudre mon problème d'une autre façon, mais qui s'en rapproche (même si elle ressemble plus à du bricolage que la tienne). En fait j'ai tout simplement rajouté un ad-- juste avant l'allocation du *ad, parce que je me rendais compte qu'en fait les caractères n'étaient stockées qu'une adresse sur deux (d'où la fin de chaîne prématurée).
    En tout cas, merci beaucoup pour vos conseils, j'ai enfin pu m'en sortir !
    Bonne journée

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 578
    Points
    41 578
    Par défaut
    Ce que tu fais ne marche que si le texte unicode ne contient que des caractères ISO 8859-1. S'il contient un symbole Euro par exemple, le premier octet de ce caractère ne sera pas nul...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec Unicode
    Par pdgnr dans le forum Windows Forms
    Réponses: 6
    Dernier message: 07/01/2008, 23h06
  2. [CR(10)]Problème avec unicode (japonais)
    Par speed034 dans le forum SAP Crystal Reports
    Réponses: 2
    Dernier message: 26/05/2005, 09h55
  3. Problème mémoire avec une dll par chargement dynamique
    Par widze19 dans le forum C++Builder
    Réponses: 6
    Dernier message: 15/12/2003, 13h20
  4. problèmes bizarres avec jdbc
    Par jaimepasteevy dans le forum PostgreSQL
    Réponses: 8
    Dernier message: 12/12/2003, 12h00
  5. problème JSP avec JBuilder et Weblogic 7
    Par viny dans le forum JBuilder
    Réponses: 2
    Dernier message: 24/04/2003, 08h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo