使用fread()和printf()读取和打印中文字符?

时间:2015-04-19 19:26:54

标签: c unicode fread chinese-locale

我正试图从一个虚拟中读取汉字,我在这里找到了一些关于这个问题的问题,但没有什么对我有用或适合我的需要。我正在使用来自this question的fread()实现,但它不起作用。我正在运行Linux。

  #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;
  }

我使用以下文本文件来测试它:

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

和程序输出:

个 
你
������ 

任何人都有关于这个问题的任何智慧?

编辑:此外,这是我的所有代码,因为我不确定它失败的地方。那里有一些我测试的东西,以确保我可以打印与问题不完全相关的unicode wchars。

2 个答案:

答案 0 :(得分:1)

如果您确实需要一次读取UTF-8(或者更确切地说是区域设置charmap)文件,则可以使用fscanf,如下所示。但请注意,这是代码点而不是字符,由于组合代码,字符可能包含多个代码点,而且某些代码点绝对不可打印。

#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;
}

大多数情况下,您可能不需要使用区域设置功能,因为如果将UTF-8视为不透明编码,它通常会起作用。部分原因是因为所有非ASCII字符的全部其组件字节在128..253范围内(不是拼写错误,254和255未使用)另一部分是字节128..159始终是连续字节字符的所有起始字节都是160..253,这意味着错误只会破坏一个字符而不是流的其余部分。 (好吧,代码点vs字符真的只是试图说服你将UTF-8划分为“字符”可能不会做你想要的)。

答案 1 :(得分:0)

您告诉fread在每次通话中读取两个2字节值;但是,您要读取的字符具有3字节UTF-8编码。通常,您需要整体解码UTF-8流,而不是固定大小的字节块。