2015-04-19 2 views
0

J'essaie de lire les caractères chinois d'un infile, et j'ai trouvé quelques questions sur le sujet ici mais rien qui fonctionne pour moi ou convient à mes besoins. J'utilise l'implémentation fread() de this question, mais cela ne fonctionne pas. Je cours Linux.Lire et imprimer des caractères chinois en utilisant fread() et printf()?

#define UNICODE 
    #ifdef UNICODE 
    #define _UNICODE 
    #else 
    #define _MBCS 
    #endif 

    #include <locale.h> 
    #include <stdio.h> 
    #include <wchar.h> 
    #include <string.h> 
    #include <stdlib.h> 
    int main(int argc, char * argv[]) { 
     FILE *infile = fopen(argv[1], "r"); 
     wchar_t test[2] = L"\u4E2A"; 
     setlocale(LC_ALL, ""); 
     printf("%ls\n", test); //test 
     wcscpy(test, L"\u4F60"); //test 
     printf("%ls\n", test); //test 
     for (int i = 0; i < 5; i++){ 
       fread(test, 2, 2, infile); 
       printf("%ls\n", test); 
     } 
return 0; 
    } 

J'utilise le fichier texte suivant pour le tester:

一个人 
两本书 
三张桌子 
我喜欢一个猫     

et les sorties programme:

个 
你 
������ 

Quelqu'un at-il la sagesse sur le sujet?

Éditer: Aussi, c'est tout mon code parce que je ne suis pas sûr d'où il échoue. Il y a quelques trucs là où je fais des tests pour m'assurer que je peux imprimer des wchars Unicode qui ne sont pas entièrement pertinents à la question.

+0

Windows ou Linux? Si Windows, essayez d'ouvrir le fichier en tant que binaire 'fopen (argv [1]," rb ")' – user3386109

+0

Pouvez-vous s'il vous plaît supprimer les numéros de ligne de votre échantillon de code? Ils rendent difficile l'exécution du code lorsque j'essaie de vous aider. – fuz

+0

@ user3386109 pas seulement cela, vous voudrez peut-être l'ouvrir comme un flux orienté caractères larges. – fuz

Répondre

0

Vous indiquez à fread de lire deux valeurs de 2 octets dans chaque appel; Cependant, les caractères que vous voulez lire ont des codages UTF-8 de 3 octets. En général, vous devez décoder le flux UTF-8 dans son ensemble, pas dans des blocs d'octets de taille fixe.

1

Si vous avez vraiment besoin de lire un fichier UTF-8 (ou plutôt un fichier de charme local) un point de code à la fois, vous pouvez utiliser fscanf comme ci-dessous. Mais notez, c'est codes points pas caractères, les caractères peuvent se composer de plusieurs points de code en raison de la combinaison de codes et certains des codes ne sont certainement pas imprimables.

#include <locale.h> 
#include <stdio.h> 
#include <wchar.h> 
#include <string.h> 
#include <stdlib.h> 
int 
main(int argc, char *argv[]) 
{ 
    FILE *infile = fopen(argv[1], "r"); 
    wchar_t test[2] = L"\u4E2A"; 
    setlocale(LC_ALL, ""); 
    printf("%ls\n", test); //test 
    wcscpy(test, L"\u4F60");  //test 
    printf("%ls\n", test); //test 
    for (int i = 0; i < 5; i++) { 
     fscanf(infile, "%1ls", test); 
     printf("%ls\n", test); 
    } 
    return 0; 
} 

La plupart du temps, vous aurez probablement pas besoin d'utiliser la fonctionnalité locale parce que généralement fonctionne UTF-8 si vous le traiter comme un codage opaque. En partie parce que tous les caractères non ASCII ont tous octets de leurs composants dans la gamme 128..253 (pas une faute de frappe, 254 et 255 sont inutilisés) une autre partie est que les octets 128..159 sont toujours des octets de continuation tous les octets de début pour caractères sont 160..253 ce qui signifie qu'une erreur va juste casser un caractère pas le reste du flux. (D'accord, les points de code et les caractères ne sont vraiment là que pour essayer de vous convaincre que diviser UTF-8 en "caractères" ne fera probablement pas ce que vous voulez).

+0

C'est une bonne réponse, merci. dans quelques heures, je vais essayer d'exécuter le même programme avec UWF-16 entrée instwad. La complexité des «codespoints» ne semble pas en valoir la peine. –

+0

UTF-16 a tous les problèmes que UTF-8 a plus, c'est un mauvais choix pour n'importe quel système d'exploitation. Par exemple "" est quatre octets en UTF-16. Il a un avantage plutôt important sur Windows, car une grande partie de l'OS-API l'utilise, mais même cela ne fait pas vraiment un bon choix. – user3710044