[gelöst] Umlaute in QString aus stdString
-
Soo,
die .txt-Dateien liegen im UTF8 vor, trotzdem werden Umlaute in der GUI nicht korrekt dargestellt.
Ich habe festgestellt, dass das Problem schon beim einlesen auftritt, d.h. ich muss da ansetzen.Danke für eure Hilfe.
Viele Grüße
Cherup
-
Cherup schrieb:
Soo,
die .txt-Dateien liegen im UTF8 vor, trotzdem werden Umlaute in der GUI nicht korrekt dargestellt.
Ich habe festgestellt, dass das Problem schon beim einlesen auftritt, d.h. ich muss da ansetzen.Danke für eure Hilfe.
Viele Grüße
CherupSicher das die Daten in der txt datei in UTF-8 vorliegen?
(z.b. die umlaute wie z.b. ä sollte als zwei bytes in der text datei auftauchen, wenn man sich die datei in einem hex editor anschaut.
Wenn du die daten mit einem filestream aus der stl einliest sollte keine konvertierung der daten erfolgen.
-
Ziemlich sicher.
Ich habe die Datei mit dem Unix-Befehl file -bi getestet, dort wurde als charset UTF-8 angegeben.
Habs mir eben auch mal in einem HEX-Editor angeschaut, ein "ö" wird als C3 B6 kodiert, was laut der Unicode/UTF8-Zeichentabelle korrekt ist.Der Code, um die Dateien einzulesen schaut folgendermaßen aus:
string FileData; ifstream is(filePath.c_str()); //filePath wurde der Funktion übergeben FileData.assign( (istreambuf_iterator<char>(is) ), (istreambuf_iterator<char>() ) ); return FileData;
-
Und woher weiß ifstream bzw. string::assign das der Dateiinhalt in UTF8 codiert ist und nicht z.B. UTF16?
-
Softwaremaker schrieb:
Und woher weiß ifstream bzw. string::assign das der Dateiinhalt in UTF8 codiert ist und nicht z.B. UTF16?
ist dem stream in diesm falle egal, da er byteweise einliest.
-
Cherup schrieb:
Ziemlich sicher.
Ich habe die Datei mit dem Unix-Befehl file -bi getestet, dort wurde als charset UTF-8 angegeben.
Habs mir eben auch mal in einem HEX-Editor angeschaut, ein "ö" wird als C3 B6 kodiert, was laut der Unicode/UTF8-Zeichentabelle korrekt ist.Der Code, um die Dateien einzulesen schaut folgendermaßen aus:
string FileData; ifstream is(filePath.c_str()); //filePath wurde der Funktion übergeben FileData.assign( (istreambuf_iterator<char>(is) ), (istreambuf_iterator<char>() ) ); return FileData;
Was ist wenn du den content in FileData wieder in eine Datei schreibst?
Ist es dann nimmer noch utf8?
Normalerweise sollte auch im std::string die umlaute als 2 bytes dargestellt werden. Denn AFAIK macht ein ifstream beim lesen keinerlei Änderungen an dem was es einliest (bis auf line endings konvertierungen)
Schau dir das mal mit nem debugger an, was im std::string drinnsteht.
Wenn da alles passt dann hast du ein problem bei der konvertierung des contents zu QString
-
Im string FileData tritt bereits der Fehler auf, da werden Umlaute nicht korrekt dargestellt.
Wenn ich Daten aus FileData wieder in eine neue .txt-datei schreibe, bleibt es UTF8.
-
Cherup schrieb:
Im string FileData tritt bereits der Fehler auf, da werden Umlaute nicht korrekt dargestellt.
Wenn ich Daten aus FileData wieder in eine neue .txt-datei schreibe, bleibt es UTF8.Was heißt wird nicht korrekt dargestellt? Vermutlich kann dein debugger nichts mit utf-8 kodierten strings anfangen.
Z.b. ein 'ä' wird dann unter umständen als "À" dargestellt.
Das ist dann ein reines Darstellungsproblem.Für mich klingt das so als ob das einlesen funktioniert.
Dann sollte die Konvertierung zu QString mit QString::fromUtf8/fromStdString funktionieren.
-
Tja, das würde ich auch sagen, nur funktioniert es leider nicht...
was meinst du mit QString::fromUtf8/fromStdString, jeweils eins der beiden oder geschachtelt?
(Läuft nur mit fromStdString, frage nur nach um das zu verstehen.)
-
string::assign macht automatisch eine UTF-8 Konvertierung? Ich denke nein. Da liegt das Problem.
-
Hmm gut möglich, nur das der Inhalt der Datei, wenn er gelesen wird und anschließend in eine neue Datei geschrieben wird, weiterhin in UTF8 bleibt.
Wie schon geschrieben, die Datei aus der gelesen wird ist korrektes UTF8, die neue ebenfalls, ich habe bisher noch nichts an meinem Code verändert.Was ist die Alternative zu assign?
-
Softwaremaker schrieb:
string::assign macht automatisch eine UTF-8 Konvertierung? Ich denke nein. Da liegt das Problem.
Nein assign macht keinerlei konvertierung.
Ich denke das Problem liegt aktuell nicht mehr beim einlesen des UTF8 contents in einen std::string.
Ich denke eher das Problem liegt bei der konvertierung des std::string in einen QString.@Cherup: Könntest du mal ein minimalbeispiel posten, welche das Problem zeigt?
-
Sicher.
Qt-Abschnitt:
void MainGUI::createItem(ItemData* itemdata{ QLabel DescriptionLabel = new QLabel(QString::fromStdString(itemdata->getDescription())); }
Klasse ItemData:
class ItemData{ private: string myDescription; public: ItemData(); string getDescription(); void setDescription(string description); }; string ItemData::getDescription(){ return myDescription; } void ItemData::setDescription(string description){ myDescription = description; }
FileAccess-Klasse:
string FileAccess::readFile(path filePath){ //der Datentyp path kommt aus der Boost-Library string FileData; ifstream is(filePath.c_str()); FileData.assign( (istreambuf_iterator<char>(is) ), (istreambuf_iterator<char>() ) ); return FileData; }
Das sind die entsprechenden Code-Fragmente. Kann sein, dass ein oder zwei Schreibfehler drinstecken, habs auf die schnelle aus dem Kopf geschrieben.
Der Ablauf ist, dass erst der Logik-Teil initialisiert wird, dann die Daten aus den Dateien gelesen und den entsprechenden Klassen und Objekten zugewiesen wird, und zum Schluss erst die GUI gebaut wird, die sich die Daten von den Objekten holt.
-
Das ist kein minimalbeispiel, welche das problem zeigt.
Hätte wohl noch dazu schreiben sollen ein funktionierendes minimal beispiel
-
So,
bin leider nicht eher dazu gekommen, ein Minimalbeispiel zu erstellen.
Hättest das "funktionierend" an sich nicht dazu schreiben müssen, wußte schon, dass du das meinst, aber ich hatte keine ZeitAuf jeden Fall hier jetzt ein lauffähiges Beispiel.
Das Problem tritt übrigens auch hier auf, die erzeugte Datei ist aber UTF8, habs gecheckt.main.cpp:
#include "widget.h" #include "dataio.h" #include <QApplication> int main(int argc, char *argv[]) { DataIO* dataIO = new DataIO(); dataIO->writeFile(); QApplication a(argc, argv); Widget w(dataIO); w.show(); return a.exec(); }
DataIO.h:
#ifndef DATAIO_H #define DATAIO_H #include <fstream> #include <string> class DataIO { public: DataIO(); std::string readFile(); void writeFile(); }; #endif // DATAIO_H
DataIO.cpp:
#include "dataio.h" DataIO::DataIO(){} std::string DataIO::readFile(){ std::string filePath = "testFile.txt"; std::string FileData; std::ifstream is(filePath.c_str()); FileData.assign( (std::istreambuf_iterator<char>(is) ), (std::istreambuf_iterator<char>() ) ); return FileData; } void DataIO::writeFile(){ std::string filePath = "testFile.txt"; std::string fileData = "Test für Umlaute wie Ä, Ü, Ö."; std::ofstream os(filePath.c_str()); os << fileData; os.close(); }
widget.h:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QGridLayout> #include <QLabel> #include "dataio.h" class Widget : public QWidget { Q_OBJECT public: Widget(DataIO *dataIO, QWidget *parent = 0); ~Widget(); private: QGridLayout* MainLayout; }; #endif // WIDGET_H
und zu guter letzt noch widget.cpp:
#include "widget.h" Widget::Widget(DataIO* dataIO, QWidget *parent) : QWidget(parent) { MainLayout = new QGridLayout; QLabel* TestLabel = new QLabel(QString::fromStdString(dataIO->readFile())); MainLayout->addWidget(TestLabel); setLayout(MainLayout); } Widget::~Widget(){}
Auf die Boost-Librarys habe ich hier verzichtet.
VG
Cherup
-
Sicher das es utf8 ist? -> Die umlaute sind als 2 bytes in der datei abgelegt.
Mit was entwickelst du?
Wenn es unter windows mit visual studio ist dann sind die umlaute in der text datei nicht als utf-8 kodiert gespeichert.
Da Visual Studio für source code dateien keine utf-8 kodierung verwendet sondern eine ANSI kodierung.Versuch mal statt
std::string fileData = "Test für Umlaute wie Ä, Ü, Ö.";
das hier
// UTF-8 codes for the umlauts be used inside string constants as octal escape sequence (otherwise we would create numbers which are bigger then a char can hold) and in "()" the pure utf8 codepoints // ä: \303\244 (C3 A4) // ö: \303\266 (C3 B6) // ü: \303\274 (C3 BC) // Ä: \303\204 (C3 84) // Ö: \303\226 (C3 96) // Ü: \303\234 (C3 9C) // ß: \303\237 (C3 9F) std::string fileData = "Test für Umlaute wie \303\204, \303\234, \303\226.";
-
Ich entwickel mit dem QtCreator unter Ubuntu 14.04.
Ich bin sicher, dass es UTF-8 ist, der Linuxkonsolen-Befehl "file -bi" gibt mir als charset UTF8 an und im Hex-Editor werden die Umlaute mit 2 Bytes kodiert angezeigt.
Dein Vorschlag funktioniert leider nicht, bleibt die gleiche Ausgabe. Ich habe die testFile.txt vor dem Durchlauf auch gelöscht, damit sie neu angelegt wird.
Vielleicht ist es einfach ein "Ubuntu-Problem", die Group-Boxes werden auch nicht gezeichnet. (Das ist keine Frage nach Hilfe, gibt schon einen längeren Thread dazu )
VG
CherupEdit:
Ich hab nochmal versucht für FileData als Typ den std::wstring zu nutzen und die Rückgabe und die QLabel-Textzuweisung entsprechend auf wString umgestellt.
Ebenfalls kein Erfolg. Es werden allerdings andere Zeichen angezeigt
-
hier wird aus einer kleinen Sache aber ein großer Schuh/Thread!
Du ließt die Datei byteweise in einen std:string.
std:string ist für "single-byte characters" ausgelegt!
http://www.cplusplus.com/reference/string/string/Note that this class handles bytes independently of the encoding used: If used to handle sequences of multi-byte or variable-length characters (such as UTF-8), all members of this class (such as length or size), as well as its iterators, will still operate in terms of bytes (not actual encoded characters).
std::wstring ist für 2-Byte-Zeichen ausgelegt. Wenn du also deine Datei in Unicode 16-Bit wandelst und std::wstring verwendest sollte es gehen.
Ich kenne keine std-C-Funktion für codec-Wandlung, deshalb nutzt man unter Windows dafür auch die Windows-Funktion MultiByteToWideChar etc.
Deshalb die Empfehlung komplett Qt zu verwenden.
-
Softwaremaker schrieb:
hier wird aus einer kleinen Sache aber ein großer Schuh/Thread!
Aber auch nur weil Cherup zuwenig informationen liefert.
Softwaremaker schrieb:
QString::fromStdString() nutzt intern QString::fromUtf8(const char * str, int size = -1)
Stimmt aber nur für Qt5
Laut der Dokumentation von Qt 4 verwendet QString::fromStdString intern QString::fromAscii
http://doc.qt.io/qt-4.8/qstring.html#fromStdString
http://doc.qt.io/qt-5/qstring.html#fromStdString
Und da es bei Ihm mit QString::fromStdString nicht klappt vermute ich dass er Qt4 verwendet.
Wenn ich QString::fromUtf8 verwendet passt es immer. (Egal ob Qt4 oder Qt5)
QString::fromUtf8(FileData.data(), static_cast<int>(FileData.size()));
-
Morgen,
warum liefere ich zu wenig Infos? Ich habe bereits im ersten Beitrag geschrieben, dass ich als OS Linux nutze, auf die Idee nachzuschauen, ob die Datei in UTF8 ist bin ich erst durch euch gekommen und die FileRead-Funktion habe ich auch recht früh gepostet.
Zugegeben, die Qt-Version habe ich noch nicht geschrieben, die ist übrigens 5.2.
Und ja ich hätte auch das Minimalbeispiel früher posten können.
Ich werde versuchen, in Zukunft möglichst mehr Infos in den Startbeitrag zu packen.Ich möchte nach wie vor kein Qt in meiner Kern-Logik haben, die GUI soll als Modul bleiben. Ich werden mir mal in der Qt-Referenz QString::fromUTF8 anschauen um zu verstehen, was du mit deinem Codebeispiel meinst. Und mal sehen, was die Boost-Library für den Daten-IO hergibt.
Cherup