Domanda

Ho un file che contiene testo Unicode in una codifica non dichiarata.Voglio scansionare questo file alla ricerca di qualsiasi punto di codice arabo nell'intervallo da U + 0600 a U + 06FF e mappare ogni punto di codice Unicode applicabile a un byte di ASCII, in modo che il file appena prodotto sarà composto da caratteri puramente ASCII, con tutti i punti di codice inferiori a 128.

Come faccio a farlo?Ho provato a leggerli nello stesso modo in cui leggi ASCII, ma il mio terminale mostra ?? perché è un carattere multibyte.

NOTA : il file è costituito da un sottoinsieme del set di caratteri Unicode e la dimensione del sottoinsieme è inferiore alla dimensione dei caratteri ASCII.Pertanto sono in grado di eseguire una mappatura 1: 1 da questo particolare sottoinsieme Unicode ad ASCII.

È stato utile?

Soluzione

Questo è impossibile o banale. Ecco gli approcci banali:

  • Se nessun punto di codice supera 127, scrivilo semplicemente in ASCII. Fatto.

  • Se alcuni punti di codice superano 127, è necessario scegliere come rappresentarli in ASCII. Una strategia comune consiste nell'usare la sintassi XML, come in α per U + 03B1. Questo richiederà fino a 8 caratteri ASCII per ogni punto di codice Unicode trans-ASCII trascritto.

Quelle impossibili lascio come esercizio per il poster originale. Non menzionerò nemmeno gli approcci sciocchi ma possibili (leggi: stupidi), poiché questi sono legione. La distruzione dei dati è un crimine capitale nel trattamento dei dati e dovrebbe essere trattata come tale.

Nota che presumo che per "carattere Unicode" intendi in realtà "punto di codice Unicode"; cioè un carattere visibile dal programmatore. Per i caratteri visibili all'utente, è invece necessario "Unicode grapheme (cluster)".

Inoltre, a meno che non normalizzi prima il tuo testo, odierai il mondo. Suggerisco NFD.


MODIFICA

Dopo ulteriori chiarimenti da parte del poster originale, sembra che ciò che vuole fare sia molto facilmente realizzabile utilizzando strumenti esistenti senza scrivere un nuovo programma. Ad esempio, questo converte un certo set di caratteri arabi da un file di input UTF-8 in un file di output ASCII:

$ perl -CSAD -Mutf8 -pe 'tr[ابتثجحخد][abttjhhd]' < input.utf8 > output.ascii

Questo gestisce solo questi punti di codice:

U+0627 ‭ ا  ARABIC LETTER ALEF
U+0628 ‭ ب  ARABIC LETTER BEH
U+0629 ‭ ة  ARABIC LETTER TEH MARBUTA
U+062A ‭ ت  ARABIC LETTER TEH
U+062B ‭ ث  ARABIC LETTER THEH
U+062C ‭ ج  ARABIC LETTER JEEM
U+062D ‭ ح  ARABIC LETTER HAH
U+062E ‭ خ  ARABIC LETTER KHAH
U+062F ‭ د  ARABIC LETTER DAL

Quindi dovrai estenderlo a qualsiasi mappatura desideri.

Se lo desideri in uno script invece che in uno strumento da riga di comando, è anche facile, inoltre puoi parlare dei personaggi per nome impostando una mappatura, ad esempio:

 "\N{ARABIC LETTER ALEF}"   =>  "a",
 "\N{ARABIC LETTER BEH}"    =>  "b",
 "\N{ARABIC LETTER TEH}"    =>  "t",
 "\N{ARABIC LETTER THEH}"   =>  "t",
 "\N{ARABIC LETTER JEEM}"   =>  "j",
 "\N{ARABIC LETTER HAH}"    =>  "h",
 "\N{ARABIC LETTER KHAH}"   =>  "h",
 "\N{ARABIC LETTER DAL}"    =>  "d",

Se si suppone che questo sia un componente in un programma C ++ più grande, forse vorrai implementarlo in C ++, possibilmente ma non necessario utilizzando la libreria ICU4C, che include il supporto alla traslitterazione.

Ma se tutto ciò di cui hai bisogno è una semplice conversione, non capisco perché dovresti scrivere un programma C ++ dedicato. Sembra troppo lavoro.

Altri suggerimenti

Non puoi leggere i dati se non conosci il formato.Apri il file con microsoft word e vai su "Salva con nome", "Altri formati", "Testo normale (.txt)", salva.Nella casella di conversione, seleziona "Altra codifica", "Unicode" (che è UTF16LE) e "OK".Il file è ora salvato come UTF16LE.

std:ifstream infile("myfile.txt", std::ios::binary); //open stream
infile.seekg (0, ios::end); //get it's size
int length = infile.tellg();
infile.seekg (0, ios::beg);
std::wstring filetext(length/2); //allocate space
ifstream.read((char*)&filetext[0], length); //read entire file
std::string final(length/2);
for(int i=0; i<length/2; ++i) { //"shift" the variables to "valid" range
    if (filetext[length/2] >= 0x600 && filetext[length/2] <= 0xFF)
        final[length/2] = filetext[length/2]-0x600;
    else
        throw std::exception("INVALID CHARACTER");
}
//done

Avvertimenti dappertutto: dubito fortemente che questo si tradurrà in ciò che desideri, ma questo è il meglio che può essere gestito, dal momento che non ci hai detto la traduzione che deve essere eseguita o il formato del file.Inoltre, presumo che il tuo computer e il compilatore siano uguali ai miei.In caso contrario, tutto o in parte potrebbe essere sbagliato, ma è il meglio che posso fare con queste informazioni mancanti che non ci hai comunicato.

Per analizzare i punti di codice Unicode, devi prima decodificare il file nella sua rappresentazione Unicode non codificata (che è equivalente a UTF-32). Per fare ciò, devi prima sapere come è stato codificato il file in modo che possa essere decodificato. Ad esempio, i codepoint Unicode U+0600 e U+06FF sono codificati come 0xD8 0x80 e 0xDB 0xBF in UTF-8, come 0x00 0x06 e 0xFF 0x06 in UTF-16LE, come 0x06 0x00 e 0x06 0xFF in UTF-16BE, ecc.

Se il file inizia con un BOM, allora conosci la codifica esatta utilizzata e puoi interpretare il resto del file di conseguenza. Ad esempio, UTF-8 BOM è 0xEF 0xBB 0xBF, UTF-16LE è 0xFF 0xFE, UTF-16BE è 0xFE 0xFF e così via.

Se il file non inizia con una distinta materiali, è necessario analizzare i dati ed eseguire l'eriristica su di esso per rilevare la codifica, ma non è affidabile al 100%. Sebbene sia abbastanza facile rilevare le codifiche UTF, è quasi impossibile rilevare le codifiche Ansi con qualsiasi misura di affidabilità. Anche il rilevamento di codifiche UTF senza una BOM presente a volte può causare risultati falsi (leggi questo , questo e this ).

Non indovinare mai, rischierai la perdita di dati. Se non conosci la codifica esatta utilizzata, chiedila all'utente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top