ifstream: Unicode Code Points vs. Escape Sequenz
-
Hallo Zusammen !
Ich bin gerade dabei in c++ via ifstream eine Datei binär zu öffnen. Der Pfad zur Datei besteht aus Sonderzeichen (öäüß usw.). Mit Hilfe eines UTF-16 Converters wandle ich die Sonderzeichen in Unicode Code Points um ( z.B. ä = \u00e4 etc.). Nun da sich die Code Points laufend verändern habe ich das Problem wie ich die Unicode ID zusammenbaue. Nämliche wenn ich die ersten vier Zeichen fest definiere (\u00) kann ich das mit den letzten zwei Zeichen nicht bewerkstelligen, da laufend andere Sonderzeichen bzw. Codepoints das ifstream anlaufen. Nur wenn ich die Komplette Unicode ID in einem Rutsch angebe "\u00e4" bekommt das ifstream das hin die Datei zu öffnen. Was ich aber nicht möchte da die Unicode IDs Variable sein sollen. Mein Compiler(g++ (GCC) 4.1.2 20061115 (prerelease) (SUSE Linux)) sagt mir dann immer "error: incomplete universal character name \u00" wo er ja auch im Prinzip recht hat.
Nur erkennt er nicht das nach dem "\u00" noch eine Variable kommt wo der Rest des Unicode zeichen drin steht. Und wenn ich anstelle von "\u00" "\\u00" schreibe bekommt das ifstream die Datei nicht auf (Pfad nicht gefunden).Hat jemand eine Idee wie ich das Problem lösen kann ?
Zum besserem Verständnis hier ein Stückchen Code:
//############################################################################
char unicode_id[] ={"/tmp/\u00"}
strcat(unicode_id, variable_mit_dem_rest_des_utf-16_codepoints);//z.B. e4
strcat(unicode_id,"datei.txt")ifstream f;
//f.open("/tmp/\u00e4/datei.txt", ios::binary);//so funktionierts, ist aber nicht gewünscht.
f.open(unicode_id, ios::binary);//So klappts leider nicht bei mir
f.seekg(0, ios::end);
long double gesammt_groesse = 0;
gesammt_groesse = f.tellg();
cout<<"Dateigroesse: "<<gesammt_groesse<<endl;//############################################################################
Vielen Dank im Voraus
B.-D.PS: System Infos:
SuSE 10.2 Kenrel 2.6.22.6
g++ (GCC) 4.1.2 20061115 (prerelease) (SUSE Linux)
-
charset und dateinamen sind eine unheimlich kranke geschichte. es gibt hier keine standards. im endeffekt ist der dateiname eine kombination von bits ohne weitere bedeutung.
charsets bezüglich dateinamen hängen also vom dateisystem, dem dateisystem image, vom os und von der api, die für den zugriff auf das dateisystem verwendet wird, ab. einen dateinamen mit nicht-ascii zeichen in den sourcecode zuschrieben ist deshalb nicht sehr günstig.
jetzt aber zum gcc und charsets. gcc hat eine option namens "-finput-charset". damit kann man das charset angeben, in dem die sourcecode datei vorliegt (code plus string- und buchstabenkonstanten). den default für diese option sucht sich gcc aus den locale umgebungsvariablen. weiters gibt es noch zwei optionen: "-fexec-charset" und "-fwide-exec-charset". beide sind dafür zuständig, in welches charset string- und buchstabenkonstanten verwandelt werden, bevor die datei compiliert wird. das passiert aber nur temporär. die sourcecode datei wird nicht verändert. wide in der zweiten option ist für solche konstanten gedacht, die ein L als prefix haben (wchar_t konstanten):wchar_t* text = L"öäü"; wchar_t letter = L'Ö';
wenn du wirklich den dateinamen hardcoden willst, dann speichere die datei als utf8 und lass den gcc die stringkonstante nach utf16 umwandeln. iconv -l listet die möglichen parameter für die oben genannten optionen auf.
-
Hallo !
Mein eigentliches Problem liegt nicht darin den richtigen converter, charset oder locale zu bestimmen, das macht schon alles ICU4C. Ich habe nur das Problem die Escape Sequenz variabel zu halten. Da \u00 keine gültige Escape sequenz ist. Mit "\\u00", "\134u00" oder "\x5cu00" klappt das alles nicht, da ifstream die Datei dann nicht finden kann. Es kommt immer ein -1 zurück.
Gibt es nicht die Möglichkeit dem gcc zu sagen das er bitte dir Prüfung auf korrekte Escape Sequenz unterlassen soll (Mein Programm soll natürlich aber noch funktionieren) ?
Vielen Dank im Voraus
B.-D.
-
in deinem code beispiel fehlt das ICU4U komplett.
willst du, dass die unicode escape sequence zur laufzeit oder zur compilierzeit erkannt wird? derzeit passiert das zur laufzeit vom gcc. die escape sequence is mehr oder weniger ein teil der sprache c++. du kannst das nicht teilen. das wäre so, als würdst du das if in i und f teilen. wenn du willst, dass die escape sequences zur laufzeit erkannt werden sollen, musst du diese im c++ code escapen:const char* text = "bla\\u00E4bla";
wieso verwendest du diese ICU4U?