2010-12-17 5 views
6

Ich habe eine Funktion, die ich eine UTF-8-Zeichenfolge übergeben durch ein Zeichen * übergeben muss, und ich habe den Char-Zeiger auf ein einzelnes Byte Zeichenfolge. Wie kann ich die Zeichenfolge in UTF-8-Codierung in C++ konvertieren? Gibt es einen Code, den ich dazu verwenden kann? Danke!Wie konvertiert man ein Ein-Byte-Const char * in eine UTF-8-Codierung

+7

Welche Codierung ist Ihre ursprüngliche Zeichenfolge? – ybungalobill

+0

Die Zeichenfolge wird von einem Aufruf von readddir abgeleitet, um den Pfad und die Namen der Dateien im Dateisystem zu lesen. Also, ich weiß nicht, welche Codierung es ist. Aber ich nehme an, es ist nicht anders als etwas wie folgt zu machen: char * string = "Irgendeine seltsame Zeichenfolge wie è". –

+0

Pfadnamen unter Linux erzwingt keine bestimmte Kodierung. Die einzige Regel ist, dass sie kein/enthalten darf. So kann jeder einen Dateinamen mit einer beliebigen Kodierung oder sogar einem Dateinamen erstellen, der in einem beliebigen Zeichensatz illegal kodiert ist. Sie können vermuten, dass es ISO8859-1 ist und es mit der iconv() - Funktion transformieren. – nos

Antwort

2

Um eine Zeichenkette in eine andere Zeichenkodierung zu konvertieren, verwenden Sie eine verschiedene Zeichencodierung Bibliotheken. Eine beliebte Wahl ist iconv (der Standard auf den meisten Linux-Systemen).

Um dies zu tun, müssen Sie zuerst die Codierung Ihrer Eingabe herausfinden. Leider gibt es dafür keine allgemeine Lösung. Wenn die Eingabe nicht ihre Kodierung spezifiziert (wie es zum Beispiel Webseiten im Allgemeinen tun), müssen Sie raten.

Wie zu Ihrer Frage: Sie schreiben, dass Sie die Zeichenfolge von Aufruf readdir auf einem FAT32-Dateisystem erhalten. Ich bin mir nicht ganz sicher, aber ich glaube, readdir wird die Dateinamen zurückgeben, wie sie vom Dateisystem gespeichert werden.Im Fall von FAT/FAT32:

  • Die kurzen Dateinamen in einigen DOS-codiert sind code page - die Codepage, wie die Dateien abhängt, in dem geschrieben, gibt es keine Möglichkeit AFAIK von nur das Dateisystem zu erzählen.
  • Die langen Dateinamen sind in UTF-16.

Wenn Sie den Standard vfat Linux-Kernel-Modul verwenden, um die FAT32-Partition zugreifen zu können, sollten Sie lange Dateinamen von readdir erhalten (es sei denn, eine Datei nur hat einen 8.3-Namen). Diese können als UTF-16 dekodiert werden. FAT32 speichert intern die langen Dateinamen in UTF-16. Der vfat Treiber wird sie in die Codierung konvertieren, die durch den Mount-Parameter iocharset= gegeben wird (wobei der Standardwert die Standardsystemcodierung ist, glaube ich).

Zusätzliche Informationen:

Sie müssen möglicherweise mit den Mount-Optionen codepage und iocharset (siehe http://linux.die.net/man/8/mount) spielen Dateinamen rechts auf dem FAT32-Volumes zu erhalten. Versuchen Sie, so zu mounten, dass Dateinamen in einer Linux-Konsole korrekt angezeigt werden, und fahren Sie fort. Es gibt einige weitere Erklärungen hier: http://www.nslu2-linux.org/wiki/HowTo/MountFATFileSystems

+0

Der letzte Link löste mein spezifisches Problem. Es schien ausreichend zu sein, das Gerät mit geeigneten Parametern zu installieren, damit es richtig funktioniert. Ich bezeichne dies als die akzeptierte Antwort, da es meine spezifische Situation gelöst hat und es den allgemeinen Fall richtig erklärt. Danke trotzdem an alle! –

4

Nehmen wir an, Sie suchen nach iconv. Wenn Sie den Konverter öffnen (iconv_open), übergeben Sie von und an Codierung. Wenn Sie eine leere Zeichenfolge wie von übergeben, wird es aus dem Gebietsschema konvertieren, das auf Ihrem System verwendet wird, das mit dem Dateisystem übereinstimmen sollte.

Unter Windows haben Sie ziemlich genau das gleiche mit MultiByteToWideChar wo Sie CP_ACP als die Codepage übergeben. Unter Windows können Sie jedoch einfach die Unicode-Version der Funktionen aufrufen, um Unicode sofort zu erhalten, und dann mit WideCharToMultiByte und CP_UTF8 in UTF-8 konvertieren.

1

Ich denke, das oberste Bit ist auf die 1-Byte-Zeichenfolge festgelegt, so dass die Funktion, die Sie übergeben, erwartet mehr als 1 Byte übergeben wird.

Zuerst die Zeichenfolge in Hex ausgeben.

heißt

unsigned char* str = "your string"; 
for (int i = 0; i < strlen(str); i++) 
    printf("[%02x]", str[i]); 

haben jetzt eine Lese der Wikipedia-Artikel über die UTF8-Codierung, die es gut erklärt.

UTF-8 ist eine variable Breite, bei der jedes Zeichen zwischen 1 und 4 Byte belegen kann.

Konvertieren Sie daher das Hex in Binär und sehen Sie, was der Codepunkt ist.

, d.h. wenn das erste Byte 11110 (binär) startet, erwartet es eine 4-Byte-Zeichenfolge. Da ascii 7-Bit 0-127 ist, ist das oberste Bit immer Null, also sollte es nur 1 Byte geben. Übrigens beginnen die Bytes, die auf das erste Byte in einem breiten Zeichen einer UTF8-Zeichenfolge folgen, "10 ..." für die oberen Bits. Dies sind die Fortsetzungsbytes ... darüber beklagt sich Ihre Funktion ... d.h. die Fortsetzungsbytes fehlen, wenn sie erwartet werden. Also ist die Saite nicht ganz so wahr wie du dachtest.

Sie konvertieren kann mit als jemand iconv vorgeschlagen, oder vielleicht diese Bibliothek http://utfcpp.sourceforge.net/

+0

Ich habe versucht mit der Zeichenfolge "/ system/mnt/usb0/audio/07 Dracula Der Pfähler.mp3" und ich habe [2f] [73] [79] [73] [74] [65] [6d] [2f] [6d] [6e] [74] [2f] [75] [73] [62] [30] [2f] [61] [75] [64] [69] [6f] [2f] [30] [37 ] [20] [44] [72] [61] [63] [75] [6c] [61] [20] [44] [65] [72] [20] [50] [66] [e4] [ 68] [6c] [65] [72] [2e] [6d] [70] [33]. Es erscheint ziemlich seltsam, da das Zeichen ä Teil des ASCII-Satzes ist, und so sollte es in Ordnung sein. Liege ich falsch? Vielen Dank! –

+0

@Luca - Ja, du liegst falsch (sorry). ASCII englische Zeichen (weniger als 0x80) sind identisch mit ihren UTF-8-Entsprechungen. ä auf e4 konvertiert, was kein gültiges UTF-8 ist. –

+0

Ah, ich verstehe! Ok, UTF-8 ist nicht abwärtskompatibel mit erweitertem ASCII. Dies erklärt, warum ich das Problem mit "è" und "ä" bemerkte. Vielen Dank! –

Verwandte Themen