Domanda

Ambiente: Gcc / G ++ Linux

Ho un file non-ASCII nei file system e ho intenzione di aprirla.

Ora ho un wchar_t *, ma non so come aprirlo. (Il mio fidato FOPEN solo apre char * file)

Si prega di aiuto. Grazie mille.

È stato utile?

Soluzione

Ci sono due possibili risposte:

Se si vuole fare in modo tutti i nomi di file Unicode sono rappresentabili, è possibile hard-code l'ipotesi che le usi filesystem UTF-8 nomi di file. Questo è l'approccio di Linux desktop app "moderna". Basta convertire le corde da wchar_t (UTF-32) a UTF-8 con funzioni di libreria (iconv avrebbe funzionato bene) o la propria implementazione (ma occhiata le specifiche in modo da non farlo terribilmente storto come Shelwien ha fatto), quindi utilizzare fopen .

Se si vuole fare le cose più standard-oriented modo, si dovrebbe usare wcsrtombs per convertire la stringa wchar_t ad una stringa multibyte char nella codifica del locale (che si spera è UTF-8 in ogni caso su qualsiasi sistema moderno) e l'uso fopen . Si noti che questo richiede che precedentemente impostato il locale con setlocale(LC_CTYPE, "") o setlocale(LC_ALL, "").

E, infine, non è esattamente una risposta, ma una raccomandazione:

Memorizzazione nomi di file come stringhe wchar_t è probabilmente un terribile errore. Si dovrebbe invece archiviare i nomi di file come stringhe di byte astratti, e solo convertire coloro ai wchar_t just-in-time per la loro visualizzazione nell'interfaccia utente (se è ancora necessario a tal; molti toolkit UI utilizzano stringhe di byte di pianura se stessi e fare l'interpretazione come caratteri per te). In questo modo si eliminano molti possibili casi angolo brutte, e non avete mai incontrare una situazione in cui alcuni file sono inaccessibili a causa dei loro nomi.

Altri suggerimenti

Linux non è UTF-8, ma è l'unica scelta per i nomi dei file in ogni caso

(I file possono avere tutto quello che vuoi all'interno di loro.)


Per quanto riguarda i nomi dei file, linux non hanno davvero una stringa di codifica di cui preoccuparsi. I nomi dei file sono stringhe di byte che devono essere terminata da null.

Questo non significa esattamente che Linux è UTF-8, ma significa che non è compatibile con caratteri estesi in quanto potrebbero avere uno zero in un byte che non è il byte finale.

Ma UTF-8 di preservare il modello no-null-tranne-at-the-end, quindi devo credere che l'approccio pratico è "convertito in UTF-8" per i nomi dei file.

Il contenuto dei file è una questione per gli standard sul livello del kernel di Linux, ecco non c'è nulla di Linux-y che si può o vuole fare. Il contenuto dei file sarà esclusivamente la preoccupazione dei programmi che leggono e scrivono. Linux solo negozi e ritorna il flusso di byte, e può avere tutte le nuls incorporati che si desidera.

stringa Converti wchar a stringa utf8 char, quindi utilizzare 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;
}

Dai un'occhiata a questo documento,

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

Credo che Linux segue standard POSIX, che tratta tutti i nomi di file come UTF-8.

Lo prendo è il nome del file che contiene caratteri non ASCII, non il file stesso, quando si dice "il file non-ASCII nei file system". Essa in realtà non importa quale sia il file contiene.

Si può fare questo con fopen normale, ma si dovrà corrispondere alla codifica gli usi filesystem.

Dipende da quale versione di Linux e del filesystem che si sta utilizzando e come hai impostato in su, ma probabilmente, se siete fortunati, gli usi filesystem UTF-8. Quindi prendere il vostro wchar_t (che è probabilmente una stringa codificata UTF-16?), Convertirlo in una stringa char codifica UTF-8, e passare che a 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top