Question

Environnement: gcc / g ++ Linux

J'ai un fichier non-ascii dans le système de fichiers et je vais l'ouvrir.

J'ai maintenant wchar_t *, mais je ne sais pas comment l'ouvrir. (Mon seul fait confiance fopen ouvre char * fichier)

S'il vous plaît aider. Merci beaucoup.

Était-ce utile?

La solution

Il y a deux réponses possibles:

Si vous voulez vous assurer que tous les noms de fichiers Unicode sont représentables, vous pouvez coder en dur l'hypothèse que le système de fichiers utilisations des noms de fichiers UTF-8. Ceci est le Linux « moderne » approche desktop-app. Il suffit de convertir vos chaînes de wchar_t (UTF-32) en UTF-8 avec des fonctions de bibliothèque (iconv fonctionnerait bien) ou votre propre implémentation (mais rechercher les spécifications afin de ne pas horriblement mal comme Shelwien a fait), puis utilisez fopen .

Si vous voulez faire les choses façon plus axée sur les normes, vous devez utiliser wcsrtombs pour convertir la chaîne de wchar_t à une chaîne de char multi-octets dans l'encodage des paramètres régionaux (qui est, espérons-UTF-8 de toute façon sur tout système moderne) et l'utilisation fopen . Notez que cela exige que précédemment défini les paramètres régionaux avec setlocale(LC_CTYPE, "") ou setlocale(LC_ALL, "").

Et enfin, pas exactement une réponse, mais une recommandation:

Enregistrement des noms de fichiers sous forme de chaînes wchar_t est probablement une erreur horrible. Vous devriez plutôt stocker les noms de fichiers sous forme de chaînes d'octets abstraites, et seulement convertir ceux wchar_t juste à temps pour les afficher dans l'interface utilisateur (si elle est encore nécessaire pour cela, de nombreuses boîtes à outils de l'interface utilisateur utilisent eux-mêmes des chaînes d'octets simples et faire l'interprétation en tant que caractères pour vous). De cette façon, vous éliminez beaucoup de cas d'angle désagréables possibles, et que vous rencontrez jamais une situation où certains fichiers sont inaccessibles en raison de leur nom.

Autres conseils

Linux n'est pas UTF-8, mais il est le seul choix pour les noms de fichiers de toute façon

(Les fichiers peuvent avoir tout ce que vous voulez dans les.)


En ce qui concerne les noms de fichiers, linux n'a pas vraiment une chaîne encodant à craindre. Les noms de fichiers sont des chaînes d'octets qui doivent être mis fin nulle.

Cela ne veut pas dire précisément que Linux est UTF-8, mais cela ne signifie que ce n'est pas compatible avec les caractères larges car ils pourraient avoir un zéro dans un octet qui est pas l'octet final.

Mais UTF-8 conserve le modèle non-nulls-sauf-à-la-fin, je dois donc croire que l'approche pratique est « converti en UTF-8 » pour les noms de fichiers.

Le contenu des fichiers est une question de normes au-dessus du niveau de Linux, donc ici il n'y a rien Linux-y que vous pouvez ou si vous voulez faire. Le contenu des fichiers sera uniquement la préoccupation des programmes qui lisent et écrivent les. Linux seulement stocke et retourne le flux d'octets, et il peut avoir tous les embarqués que vous voulez nuls.

string wchar Convertir en chaîne UTF8 char, puis utilisez fopen.

typedef unsigned int   uint;
typedef unsigned short word;
typedef unsigned char  byte;

int UTF16to8( wchar_t* w, char* s ) {
  uint  c;
  word* p = (word*)w;
  byte* q = (byte*)s; byte* q0 = q;
  while( 1 ) {
    c = *p++;
    if( c==0 ) break;
    if( c<0x080 ) *q++ = c; else 
      if( c<0x800 ) *q++ = 0xC0+(c>>6), *q++ = 0x80+(c&63); else 
        *q++ = 0xE0+(c>>12), *q++ = 0x80+((c>>6)&63), *q++ = 0x80+(c&63);
  }
  *q = 0;
  return q-q0;
}

int UTF8to16( char* s, wchar_t* w ) {
  uint  cache,wait,c;
  byte* p = (byte*)s;
  word* q = (word*)w; word* q0 = q;
  while(1) {
    c = *p++;
    if( c==0 ) break;
    if( c<0x80 ) cache=c,wait=0; else
      if( (c>=0xC0) && (c<=0xE0) ) cache=c&31,wait=1; else 
        if( (c>=0xE0) ) cache=c&15,wait=2; else
          if( wait ) (cache<<=6)+=c&63,wait--;
    if( wait==0 ) *q++=cache;
  }
  *q = 0;
  return q-q0;
}

Consultez ce document

http://www.firstobject.com/wchar_t- string-sur-linux-osx-windows.htm

Je pense que Linux suit la norme POSIX, qui traite de tous les noms de fichiers en UTF-8.

Je prends c'est le nom du fichier qui contient des caractères non-ascii, et non le fichier lui-même, quand vous dites « fichier non-ascii dans le système de fichiers ». Il n'a pas d'importance ce que le fichier contient.

Vous pouvez le faire avec fopen normal, mais vous devrez correspondre à l'encodage des utilisations du système de fichiers.

Cela dépend de quelle version de Linux et ce système de fichiers que vous utilisez et comment vous avez configuré, mais probablement, si vous avez de la chance, le système de fichiers utilise UTF-8. Alors, prenez votre wchar_t (ce qui est probablement une chaîne encodée UTF-16?), Le convertir en une chaîne char codée en UTF-8, et passer que pour fopen.

// locals
string file_to_read;           // any file
wstring file;                  // read ascii or non-ascii file here 
FILE *stream;
int read = 0;    
wchar_t buffer= '0';

if( fopen_s( &stream, file_to_read.c_str(), "r+b" ) == 0 )   // in binary mode
  {      
      while( !feof( stream ))
      { 
     // if ascii file second arg must be sizeof(char). if non ascii file sizeof( wchar_t)
        read = fread( & buffer, sizeof( char ), 1, stream );  
        file.append(1, buffer);
      }
  }

file.pop_back(); // since this code reads the last character twice.Throw the last one
fclose(stream);

// and the file is in wstring format.You can use it in any C++ wstring operation
// this code is fast enough i think, at least in my practice
// for windows because of fopen_s
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top