2009-09-03 16 views
18

J'écris une petite application en C qui lit un simple fichier texte et en sort ensuite les lignes une par une. Le problème est que le fichier texte contient des caractères spéciaux comme Æ, Ø et Å entre autres. Quand je lance le programme dans le terminal, la sortie de ces caractères est représentée par un "?".Traitement des caractères spéciaux en C (codage UTF-8)

Y a-t-il une solution facile?

Répondre

28

Pour commencer:

  1. Lire dans la mémoire tampon
  2. Utilisez libiconv ou similaires pour obtenir le type wchar_t de UTF-8 et utiliser les fonctions de manipulation caractère large tels que wprintf()
  3. Utilisez le fonctions de caractères larges dans C! La plupart des fonctions de gestion de fichier/sortie comportent une variante de caractères étendus

Assurez-vous que votre terminal peut gérer la sortie UTF-8. Avoir la configuration locale correcte et manipuler les données de locale peut automatiser beaucoup de l'ouverture et de la conversion de fichier pour vous ... selon ce que vous faites.

Rappelez-vous que la largeur d'un point de code ou d'un caractère en UTF-8 est variable. Cela signifie que vous ne pouvez pas simplement chercher un octet et commencer à lire comme avec ASCII ... parce que vous pourriez atterrir au milieu d'un point de code. De bonnes bibliothèques peuvent le faire dans certains cas.

Voici un code (pas le mien) qui démontre une certaine utilisation de la lecture de fichiers UTF-8 et le caractère large de manipulation en C.

#include <stdio.h> 
#include <wchar.h> 
int main() 
{ 
    FILE *f = fopen("data.txt", "r, ccs=UTF-8"); 
    if (!f) 
     return 1; 

    for (wint_t c; (c = fgetwc(f)) != WEOF;) 
     printf("%04X\n", c); 

    fclose(f); 
    return 0; 
} 

Liens

  1. libiconv
  2. Locale data in C/GNU libc
  3. Some handy info
  4. Another good Unicode/UTF-8 in C resource
+0

Merci mec! Je vais essayer ça ... – o01

+0

Pas de problème. Tenez-vous-y, Unicode en C n'est pas la chose la plus simple au monde ... se familiariser avec les normes aussi :) –

3

Assurez-vous que vous n'abandonnez pas accidentellement des octets; certains caractères UTF-8 ont plus d'un octet de longueur (c'est un peu le point), et vous devez les garder tous.

Il peut être utile d'imprimer le contenu du tampon comme hex, de sorte que vous pouvez vérifier que les octets sont lus en fait:

static void print_buffer(const char *buffer, size_t length) 
{ 
    size_t i; 

    for(i = 0; i < length; i++) 
    printf("%02x ", (unsigned int) buffer[i]); 
    putchar('\n'); 
} 

Vous pouvez le faire après le chargement d'un fichier très court, contenant quelques-uns personnages.

Assurez-vous également que le terminal est réglé sur le codage approprié, afin qu'il interprète vos caractères comme UTF-8.

+0

Mon terminal est défini sur le codage UTF-8. Le programme stocke tous les caractères de chaque ligne du fichier texte dans un tableau char par l'intermédiaire de fgets(); Si je perds des octets, je n'ai aucune idée pourquoi ou comment le réparer ... (Commençons à apprendre C btw) – o01

+0

@Eirik, n'utilisez pas fgets() qui est orienté ASCII. Utilisez fgetwc() de mon message. –

2

probablement votre fichier texte est ISO-8559-1 codé mais votre terminal est UTF-8. Ce type d'incompatibilité est un problème standard lorsqu'il s'agit de la gestion de texte orientée octet; Les autres programmes C (tels que les commandes standard 'cat' et 'more') feront la même chose et ne sont généralement pas considérés comme une erreur ou quelque chose qui doit être corrigé.Si vous voulez opérer sur un niveau de caractères Unicode au lieu de octets, mais vous devrez utiliser wchar comme type de caractères au lieu de char dans votre programme, et fournir des commutateurs pour que l'utilisateur spécifie les entrées. l'encodage de fichier est réellement. (Alors qu'il est parfois possible de deviner, ce n'est pas très fiable.)

2

Je ne sais pas si cela pourrait aider, mais si vous êtes sûr que les encodages de terminal et le fichier d'entrée sont les mêmes, vous pouvez essayer de setlocale():

#include <locale.h> 
… 
setlocale(LC_CTYPE, ""); 
+0

J'ai utilisé 'setlocale (LC_CTYPE," UTF-8 ");'. Il était nécessaire de lire le fichier avec succès même si l'environnement shell était correctement configuré. – lkuty

+0

Avec 'setlocale (LC_CTYPE," ")', chaque partie de la locale qui doit être modifiée est définie en fonction des variables d'environnement. – jgrocha

+0

Oh oui, désolé, ça aurait dû être "" "' et non "NULL". –

Questions connexes