Comment puis-je lire les chaînes Unicode-16 d'un fichier en utilisant les méthodes POSIX dans Linux?

j'ai un fichier contenant UNICODE-16 chaînes que je voudrais lire dans un programme Linux. Les chaînes ont été écrites raw à partir du format wchar interne de Windows. (Windows utilise-t-il toujours UTF-16? par exemple dans les versions japonaises)

je crois que je peux les lire en utilisant des lectures brutes et la conversion avec wcstombs_l. Cependant, je ne sais pas quel endroit utiliser. L'exécution "locale-a" sur mes machines Ubuntu et Mac OS X à jour donne zéro locales avec utf-16 dans leur nom.

y a-t-il un meilleur moyen?

mise à jour: la bonne réponse et d'autres ci-dessous m'ont aidé à utiliser libiconv. Voici une fonction que j'utilise pour faire la conversion. Je l'ai actuellement dans une classe qui fait les conversions en une seule ligne de code.

// 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: %sn",
           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 = %dn", 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: %sn", strerror(errno));
    iconv_close(cd);
    free(*dest);
    *dest = NULL;
    return -1;
  }

  iconv_close(cd);

  return 0;
} // iwcstombs_alloc()
5
demandé sur Harvey 2009-02-05 20:09:54

4 réponses

(Windows utilise-t-il toujours UTF-16? par exemple dans les versions japonaises)

Oui, le WCHAR de NT est toujours UTF-16LE.

(le’ System codepage', qui pour les installations japonaises est en effet cp932/Shift-JIS, existe toujours dans NT pour le bénéfice des nombreuses, nombreuses applications qui ne sont pas Unicode-native, FAT32 paths, et ainsi de suite.)

cependant, wchar_t n'est pas garanti d'être 16 bits et sur Linux il ne sera pas, UTF-32 (UCS-4) est utilisé. Il est donc peu probable que wcstombs_l soit heureux.

la bonne chose serait d'utiliser une bibliothèque comme iconv pour la lire dans n'importe quel format que vous utilisez en interne - probablement wchar_t. Vous pourrait essayer de le pirater vous-même en insérant des octets, mais vous obtiendriez probablement des choses comme les substituts faux.

Runing "paramètres régionaux" sur ma mise à jour de Ubuntu et Mac OS X machines rendements zéro locales avec utf-16 en leur nom.

en effet, Linux ne peut pas utiliser UTF-16 comme encodage local par défaut grâce à tous les \0s.

4
répondu bobince 2009-02-05 18:43:50

la manière la plus simple est de convertir le fichier de utf16 à utf8 encodage UNIX natif, puis de le lire,

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

vous pouvez également utiliser iconv(3) (Voir man 3 iconv) pour convertir la chaîne en utilisant C. La plupart des autres langues ont aussi des fixations à iconv.

que vous pouvez utiliser N'importe quelle locale UTF-8 comme en_US.UTF-8 qui sont habituellement celui par défaut sur la plupart des distributions linux.

6
répondu 2009-02-05 19:41:26

Vous pouvez lire en binaire, puis faire votre propre conversion rapide: http://unicode.org/faq/utf_bom.html#utf16-3 Mais il est probablement plus sûr d'utiliser une bibliothèque (comme libiconv) qui gère les invalides séquences correctement.

2
répondu Mihai Nita 2009-02-09 09:15:08

je recommande fortement d'utiliser un encodage Unicode comme représentation interne de votre programme. Utilisez L'UTF-16 ou L'UTF-8. Si vous utilisez UTF-16 en interne, il est évident qu'aucune traduction n'est nécessaire. Si vous utilisez UTF-8, Vous pouvez utiliser une locale avec .UTF-8 comme en_US.UTF-8 .

1
répondu Adam Rosenfield 2009-02-05 17:20:57