UTF8控制台输出:MultiByteToWideChar vs mbsrtowcs

时间:2015-08-24 11:38:48

标签: c utf-8 windows-console

我想从UTF-8文件中读取一个短行并在Windows控制台中显示它。

我成功完成了 MultiByteToWideChar Winapi功能:

void mbtowchar(const char* input, WCHAR* output) {
  int len = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0);
  MultiByteToWideChar(CP_UTF8, 0, input, -1, output, len);
}

void main() {
  setlocale(LC_ALL,"");
  char in[256];

  FILE* file = fopen("data.txt", "r");
  fgets(in, 255, file);
  fclose(file);

  mbtowchar(in, out);
  printf("%ls",out);
}

...但我没有使用ISO mbsrtowcs 功能(非ASCII字符混乱):

void main() {
  setlocale(LC_ALL,"");
  char in[256];
  wchar_t out[256];

  FILE* file = fopen("data.txt", "r");
  fgets(in, 255, file);
  fclose(file);

  const char* p = in;
  mbstate_t mbs = 0;
  mbsrtowcs(out, &p, 255, &mbs);

  printf("%ls",out);
}

我是否对mbsrtowcs做错了或者这两个函数之间有什么重要的区别?是否可以使用ISO功能在Windows控制台中可靠地打印UTF-8? (假设安装了匹配的控制台字体。)

注意:我使用MinGW gcc编译器。对我来说C ++是最后的解决方案,我想和C一起使用。

1 个答案:

答案 0 :(得分:4)

mbsrtowcs的“错误”是它从8位字符(char)的系统定义的可变宽度编码转换为“宽”字符的固定宽度数组( wchar_t)。今天宽字符被理解为Unicode代码点,但“多字节”并不一定意味着UTF-8。在Windows上,它实际上是指various pre-Unicode encodings of Asian scripts。令人沮丧的是,Windows doesn't support UTF-8完全是本地“多字节”编码,apparently never will

因此尝试使用mbsrtowcs来解释UTF-8在Win32上注定要失败。您必须使用MultiByteToWideChar,作为您的第一个代码段,或切换到其他一些将UTF-8转换为UTF-16的方法。 (由于UTF-8和UTF-16都编码UCS代码点,如果您的目标是避免依赖专有扩展,您甚至可以编写自己的简单例程来执行此操作。)