Frage

Umwelt: Gcc / G ++ Linux

Ich habe eine nicht-ASCII-Datei in dem Dateisystem, und ich werde es öffnen.

Jetzt habe ich ein wchar_t *, aber ich weiß nicht, wie es zu öffnen. (Mein trusted fopen öffnet nur char * Datei)

Bitte Hilfe. Vielen Dank.

War es hilfreich?

Lösung

Es gibt zwei mögliche Antworten:

Wenn Sie sicher, dass alle Unicode-Dateinamen machen wollen sind darstellbaren, können Sie hartcodieren die Annahme, dass sich das Dateisystem verwendet UTF-8 Dateinamen. Dies ist der „moderne“ Linux-Desktop-App-Ansatz. konvertieren Sie einfach Ihre Strings aus wchar_t (UTF-32) auf UTF-8 mit Bibliotheksfunktionen (iconv gut funktionieren würde) oder eine eigene Implementierung (aber Lookup die Spezifikationen, so dass Sie es nicht falsch bekommt schrecklich wie Shelwien tat), dann verwenden Sie fopen .

Wenn Sie die Dinge, die mehr Standards orientiert tun möchten, sollten Sie wcsrtombs verwenden, um die wchar_t Zeichenfolge in ein Multibyte char Zeichenfolge in das Gebietsschema des Kodierung konvertiert werden (was hoffentlich UTF-8 ist sowieso auf jedem modernen System) und die Verwendung fopen . Beachten Sie, dass dies erfordert, dass Sie vorher das Gebietsschema mit setlocale(LC_CTYPE, "") oder setlocale(LC_ALL, "") gesetzt.

Und schließlich, nicht gerade eine Antwort, aber eine Empfehlung:

Dateinamen als wchar_t Strings zu speichern ist wahrscheinlich ein schrecklicher Fehler. Sie sollten stattdessen speichern Dateinamen als abstrakte Byte-Strings, und solche, die nur konvertieren just-in-time wchar_t für sie in der Benutzeroberfläche angezeigt wird (wenn es für die sogar notwendig ist, viele UI-Toolkits Ebene Byte-Strings selbst nutzen und tun, um die Interpretation als Zeichen für Sie). Auf diese Weise beseitigen Sie viele mögliche unangenehme Ecke Fällen und Sie nie in eine Situation kommen, wo einige Dateien aufgrund ihrer Namen nicht zugänglich sind.

Andere Tipps

Linux ist nicht UTF-8, aber es ist die einzige Wahl für Dateinamen sowieso

(Dateien können alles, was Sie wollen, müssen innen sie.)


In Bezug auf Dateinamen, Linux hat nicht wirklich eine Zeichenfolge codiert, zu befürchten. Dateinamen sind Byte-Zeichenfolge, die Notwendigkeit nullterminierte sein.

Das bedeutet nicht genau, dass Linux ist UTF-8, aber es bedeutet, dass es mit breiten Zeichen nicht kompatibel ist, da sie eine Null in einem Byte haben könnten, die nicht das Ende Byte ist.

Aber UTF-8 bewahrt das nicht-NULL-Werte-außer-at-the-End-Modell, so dass ich zu der Annahme, dass der praktische Ansatz ist "Convert to UTF-8" für Dateinamen.

Der Inhalt von Dateien ist eine Frage für Normen über dem Niveau Linux-Kernel, also hier gibt es nichts Linux-y, dass Sie oder tun wollen. Der Inhalt von Dateien werden nur die Anliegen der Programme, die sie lesen und schreiben. Linux nur speichert und gibt den Byte-Stream, und es können alle eingebetteten nuls haben Sie wollen.

Convert wchar String in UTF-8-Zeichen-String, dann fopen verwenden.

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

Schauen Sie sich dieses Dokument

http://www.firstobject.com/wchar_t- String-on-linux-osx-windows.htm

Ich denke, Linux folgt POSIX-Standard, der alle Dateinamen als UTF-8 behandelt.

Ich nehme an, es ist der Name der Datei, die Nicht-ASCII-Zeichen enthält, nicht die Datei selbst, wenn Sie auf „Nicht-ASCII-Datei in Dateisystem“ sagen. Es spielt eigentlich keine Rolle, was die Datei enthält.

Sie können dies mit normalen fopen, aber Sie werden die Codierung der Dateisystem-Anwendungen entsprechen müssen.

Es hängt davon ab, welche Version von Linux und was Dateisystem Sie verwenden und wie Sie haben es eingerichtet, aber wahrscheinlich, wenn man Glück hat, die Dateisystem-Anwendungen UTF-8. Also nehmen Sie sich wchar_t (was wahrscheinlich ein UTF-16-codierte Zeichenfolge ist?), Wandelt es in ein char-String in UTF-8 codiert, und übergeben, dass 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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top