5

我有一个包含 UNICODE-16 字符串的文件,我想将其读入 Linux 程序。这些字符串是从 Windows 的内部 WCHAR 格式原始写入的。(Windows 是否总是使用 UTF-16?例如在日文版本中)

我相信我可以使用原始读取和使用 wcstombs_l 进行转换来读取它们。但是,我不知道要使用什么语言环境。在我最新的 Ubuntu 和 Mac OS X 机器上运行“locale -a”会产生零语言环境,其名称中包含 utf-16。

有没有更好的办法?

更新:正确答案和下面的其他人帮助我使用 libiconv。这是我用来进行转换的函数。我目前将它放在一个类中,该类将转换为一行代码。

// Function for converting wchar_t* to char*. (Really: UTF-16LE --> UTF-8)
// It will allocate the space needed for dest. The caller is
// responsible for freeing the memory.
static int iwcstombs_alloc(char **dest, const wchar_t *src)
{
  iconv_t cd;
  const char from[] = "UTF-16LE";
  const char to[] = "UTF-8";

  cd = iconv_open(to, from);
  if (cd == (iconv_t)-1)
  {
    printf("iconv_open(\"%s\", \"%s\") failed: %s\n",
           to, from, strerror(errno));
    return(-1);
  }

  // How much space do we need?
  // Guess that we need the same amount of space as used by src.
  // TODO: There should be a while loop around this whole process
  //       that detects insufficient memory space and reallocates
  //       more space.
  int len = sizeof(wchar_t) * (wcslen(src) + 1);

  //printf("len = %d\n", len);

  // Allocate space
  int destLen = len * sizeof(char);
  *dest = (char *)malloc(destLen);
  if (*dest == NULL)
  {
    iconv_close(cd);
    return -1;
  }

  // Convert

  size_t inBufBytesLeft = len;
  char *inBuf = (char *)src;
  size_t outBufBytesLeft = destLen;
  char *outBuf = (char *)*dest;

  int rc = iconv(cd,
                 &inBuf,
                 &inBufBytesLeft,
                 &outBuf,
                 &outBufBytesLeft);
  if (rc == -1)
  {
    printf("iconv() failed: %s\n", strerror(errno));
    iconv_close(cd);
    free(*dest);
    *dest = NULL;
    return -1;
  }

  iconv_close(cd);

  return 0;
} // iwcstombs_alloc()
4

4 回答 4

6

最简单的方法是将文件从 utf16 转换为 utf8 本机 UNIX 编码,然后读取它,

iconv -f utf16 -t utf8 file_in.txt -o file_out.txt

您还可以使用 iconv(3)(参见 man 3 iconv)使用 C 转换字符串。大多数其他语言也绑定到 iconv。

您可以使用任何 UTF-8 语言环境,例如 en_US.UTF-8,这通常是大多数 Linux 发行版的默认语言环境。

于 2009-02-05T19:41:26.760 回答
4

(Windows 是否总是使用 UTF-16?例如在日文版本中)

是的,NT 的 WCHAR 始终是 UTF-16LE。

(用于日语安装的“系统代码页”确实是 cp932/Shift-JIS,在 NT 中仍然存在,以造福于许多非 Unicode 原生的应用程序、FAT32 路径等。)

但是,wchar_t 不能保证为 16 位,在 Linux 上也不会,使用的是 UTF-32 (UCS-4)。所以 wcstombs_l 不太可能高兴。

正确的做法是使用 iconv 之类的库将其读入您在内部使用的任何格式 - 大概是 wchar_t。您可以尝试通过插入字节来自己破解它,但您可能会弄错像代理这样的东西。

在我最新的 Ubuntu 和 Mac OS X 机器上运行“locale -a”会产生零语言环境,其名称中包含 utf-16。

事实上,由于所有的 \0,Linux 不能使用 UTF-16 作为语言环境的默认编码。

于 2009-02-05T18:43:50.400 回答
3

您可以读取二进制文件,然后进行自己的快速转换: http ://unicode.org/faq/utf_bom.html#utf16-3 但是使用正确处理无效序列的库(如 libiconv)可能更安全。

于 2009-02-09T09:15:08.400 回答
1

我强烈建议使用 Unicode 编码作为程序的内部表示。使用 UTF-16 或 UTF-8。如果您在内部使用 UTF-16,那么显然不需要翻译。如果您使用 UTF-8,则可以使用其中包含的语言环境,.UTF-8例如en_US.UTF-8.

于 2009-02-05T17:20:57.683 回答