ASCII Problem in Japan?
-
Hallo
Ich habe eine tolle Applikation geschrieben, welche weltweit eigentlich eingesetzzt werden soll.
Mit der App. lassen sich Konfigurationsdateien öffnen. Der Dateninhalt ist normaler ASCII-Text, die Datenwerte entsprechend mit einem ':' Zeichen getrennt.
Bezüglich der Datensicherheit habe ich den Inhalt exor verknüpft, dann einen MD-5 Hash berechnet und angefügt. Dann das ganze noch Base64 codiert.
Jetzt jammern die Japaner, dass sie die Datei nicht öffnen können. Bei mir gehts prima und auch anderswo habe ich noch keine schlechten rückmeldungen.
Frage: Kennen die Japaner das ASCII System etwas nicht??
Bemerkung:
Es ist eine VC++ MFC Applikation welche Win2000 benötigt
-
sky21 schrieb:
Frage: Kennen die Japaner das ASCII System etwas nicht??
Klar kennen sie es, nur hat die japanische Schrift ein paar mehr Zeichen und deshalb verwenden sie lieber UNICODE (16-Bit-Zeichen).
-
CStoll (off) schrieb:
sky21 schrieb:
Frage: Kennen die Japaner das ASCII System etwas nicht??
Klar kennen sie es, nur hat die japanische Schrift ein paar mehr Zeichen und deshalb verwenden sie lieber UNICODE (16-Bit-Zeichen).
Muss ich dann das Programm in unicode kompilieren oder wie? wohl kaum oder?
muss gleich mal bei wikipedia vorbeigehen und gucken, was unicode ist. *argh*
-
Vermutlich speichern die Japaner die Textdateien als Unicode (also mit 16Bit-Zeichen), und Dein Programm erwartet ASCII (8Bit-Zeichen). Das kann Probleme bereiten, wenn Du als Stringende eine 8Bit-0 erwartest, da bei Unicode die ASCII-Zeichen im Hibyte alle mit 0 aufgefüllt werden.
Beispiel:
H,a,l,l,o als 8Bit wird in Unicode eingebettet in 8Bit-Darstellung dann zu
0,H,0,a,0,l,0,l,0,o
Prüfst Du nun z.B. auf != 0, so gibt's Probleme.
Vermutlich basiert Dein Problem auf irgendeiner derartigen Sache. Du kannst mit dem Visual Studio aber Textdateien auch als Unicode abspeichern und damit Testdateien erstellen.
-
Hallo und danke für die Antwort.
Ich verstehe es aber noch nicht ganz. Was muss ich nun konkret machen, dass die Applikation auch auf System mit Unicode funktionieren?Ich habe gelesen, dass ab Windows NT intern auch mit unicode gearbeitet wird. Nun, in wiefern betrifft das mich als Programmierer?
Brauche ich nun zwei Versionen? Eine in Unicode für solche, die auch eine Windows-Unicode oberfläche haben und eine mit ASCII? <Hier> in Europa scheint mein Programm zu funktionieren. Nur die Asiaten meckern. Die Applikationssprache ist Englisch.
Thanks for your help!
-
sky21 schrieb:
Hallo und danke für die Antwort.
Ich verstehe es aber noch nicht ganz. Was muss ich nun konkret machen, dass die Applikation auch auf System mit Unicode funktionieren?In Deinem Fall solltest Du das zunächst isoliert betrachten. Königsweg wäre natürlich, die ganze App als Unicode zu realisieren, aber Du hast ja ein konkretes Problem hier und jetzt - also zunächst Bugfixing.
Besorg Dir die Dateien, mit denen es Probleme gibt, und debugge Dein Programm mit diesen Dateien. Du wirst dann evtl das Problem isoliert lösen können.
Ansonsten solltest Du Dir ein Testsystem aufbauen, auf dem ein japanisches oder chinesisches Windows installiert ist (kann man ja über ein Image realisieren, so daß man keinen Rechner fest verbraten muß), auf diesem Compiler + Debugger installieren.
Wenn Du Applikationen mit dem Anspruch "weltweit" schreibst, mußt Du sowas haben. Es wird Dir teilweise auch eine Idee der Probleme vermitteln, die Deine Anwender haben.
sky21 schrieb:
Ich habe gelesen, dass ab Windows NT intern auch mit unicode gearbeitet wird. Nun, in wiefern betrifft das mich als Programmierer?
Meistens nicht. Auch eine Nicht-Unicode-Applikation läuft in Asien richtig, aber sobald Du Dateien öffnen willst, kann es Probleme geben. Zum Beispiel auch, wenn der User bei "File Open" eine Datei mit japanischem Namen anklickt, auch dies wird in Deinem Programm nicht richtig funktionieren.
Intern verwendet NT nur Unicode für die Strings. Es gibt für jede Api-Funktion mit einem String-Parameter 2 Versionen, eine mit 8Bit, eine mit Unicode. Die haben als Postfix ein A oder ein W. Je nach Compilierungsmodell (Unicode oder nicht) werden nun die Api-Aufrufe entweder auf die A oder W Version gemappt. Intern sind die A-Funktionen so realisiert, daß alle 8Bit-Strings konvertiert werden, danach wird die W-Funktion aufgerufen, und danach werden die Ergebnisse wieder zurück auf 8Bit konvertiert.
sky21 schrieb:
Brauche ich nun zwei Versionen? Eine in Unicode für solche, die auch eine Windows-Unicode oberfläche haben und eine mit ASCII? <Hier> in Europa scheint mein Programm zu funktionieren. Nur die Asiaten meckern.
Nein, eine Unicode-Version würde auch für ASCII funktionieren, wenn Du beim Laden und Speichern die richtigen Funktionen verwendest - diese lesen auch eine ASCII-Datei richtig ein und stellen diese intern als Unicode dar.
Aber das setzt voraus, daß von Anbeginn an Deine Applikation als Unicode ausgelegt ist - Du mußt sie also als Unicode-Projekt compilieren, überall bei Strings mit L"HalloWelt" arbeiten, und die ganzen Stringfunktionen müssen mit den 16-Bit-Funktionen ausgeführt sein. Glücklich, wenn Du z.B. mit MFC CString verwendet hast, dann würde dies relativ rasch funktionieren.
Du mußt Dir dazu aber sicherlich die Artikel auf der MSDN durchlesen... da gibt's viel Material zum Thema Unicode.
Welche Lib verwendest Du denn für die Oberfläche?
-
Danke für die ausführliche Info.
Es ist eben so, dass selbst die mitgelieferten Dateien (Konfig.-Dateien) nicht mit meiner Applikation geöffnet werden können. Genau diese Dateien lassen sich bei mir prima öffnen.
Ich verwende die MS MFC mit VC++ 6.0
Ach ja:
Ich lese die Dateien als Strings ein und verarbeite die darin enthaltenen Daten.
Vielleicht sollte ich die Datei als Bytestream einlesen?
-
Ich verstehe.
Bist Du sicher, daß Dein Anwender die gleichen MFC-DLLs wie Du verwendet? Vielleicht setzen die Jungs die Unicode-MFC-DLL ein und Du die andere? Lieferst Du die MFC-DLLs bei der Installation mit? Besser ist es bei so einem Fall, wenn Du die MFC statisch linkst und nicht dynamisch, dann hast Du darüber mehr Kontrolle.
Vermutlich wird nämlich beim Laden eine Unicode-Funktion aufgerufen (daher mein Verdacht mit der DLL), Du erwartest aber natürlich ASCII, und dann stolperst Du über die Nullbytes im String.
Die Idee mit dem Einlesen als Bytestream klingt daher vernünftig. Und alle Libs statisch linken.
Dennoch solltest Du über ein System mit chinesischem oder japanischen Windows nachdenken. Du wirst dann nämlich auch feststellen, daß die Zeichensätze dort etwas höher sind, so daß mancher Button - der bei uns hoch genug ist - dort ein Teil vom Text abschneidet/verdeckt.
-
Hi Marc++us und danke für deine Tipps.
Zu deiner Frage: Nein, die MCF-DLL ist statisch gelinkt!
Also ich poste jetzt 'mal VC++ code hier, obschons halt nicht gerade zur "Rund um die Programmierung" gehört. Aber es soll nur das Phänomen besser beschreiben.
Also ich habe folgende Funktion, welche angeblich nicht korrekt ausgeführt wird (Hier bei mir auf dem europäischen Festland funktionierts prima).
// Datei auswählen, inhalt de-codieren bool DataImporter::getFileData( CString &sFileName, CObArray &oaParData, bool bUseFileDialog, int CONFIGTYPE, ErrorObject &err, int DECODING_FLAGS){ err.init(); int FILETYPES = FILETYPE_MCF|FILETYPE_MCFT; // open file dialog if(bUseFileDialog){ if(!openFileDialog(sFileName, FILETYPES, err)){ err.doSetImpact(IMP_FILE_OPEN_MCFMCFT); return false; } } oaParData.RemoveAll(); // read string data CStringArray saStringedData; if(!readFileData(sFileName, saStringedData, err, DECODING_FLAGS)){ err.doSetImpact(IMP_FILE_OPEN_MCFMCFT); return false; } // convert stringed data into datablocks DataConverter_Param dcp; if(!dcp.convertStringToParam(saStringedData, oaParData, m_sCHN, m_sFileTime, err)){ err.doSetImpact(IMP_FILE_OPEN_MCFMCFT); return false; } // check if opened file last time if(!checkConfigType(CONFIGTYPE, m_sCHN, err)){ return false; } return true; }
Es ist zu erkennen, dass ich im Wesentlichen 4 Methoden aufrufe:
-
Ein File-Öffnen-Auswahl-Dialog erscheint. Wenn der Benutzer keine Auswahl getroffen hat, dann wird return false aufgerufen.
-
Bei 'readFileData' wird der Dateeiinhalt gelesen. Speziell ist hier, dass der Dateninhalt im 6bit-ASCII Code vorliegen (Base64 codiert). Ich de-codiere die Daten, dann erhalte ich die 8-Bit-Binärdatenwerte, mache eine EXOR-Verknüpfung der Daten (leichte Chiffrierung) und erhalte nun 8-Bit ASCII-Daten im druckbaren Bereich! Die letzten paar Zeichen sind die angehängte Checksumme (MD5 Hash!!). Ich trenne den Hash also hab und bilde den Hashwert über die gesamten Daten und vergleiche den erhaltenen Wert mit dem ausgelesenen Wert. Dies funktioniert wohl gut in 99.999% aller Fälle nicht? Eben!
-
Ich konvertiere das StringArray (=Rohdaten im druckbaren ASCII Bereich) in ein Parameterobjet um. Pro CStringelement im Array ist ein Parameter definiert.
Datentrennzeichen sind :, ;, |
als resultat sollte ich ein Objektarray mit den abgefüllten ParameterObjekten erhalten. -
Ein letzter Check (nixht wichtig.)
Interessant ist nun, dass die bei den Japaner generierten Fehlermeldung zu grosser Sicherheit in der Methode 3) erzeugt worden ist. Also nicht etwa beim Datenlesen, sondern eher in der Konvertierungsmethode. Lustig ist also zu wissen, wie sie an der Methode 3 Vorbeigekommen sind ,ohne dass ein Datenintegritätsfehler (unterscheidliche Hashwerte) geworfen wurde.
Windows auf Japanisch: Hmmm jo ich glaub so etwas müsste ich wohl sofort beschaffen.
-
-
-
Schick den Jungs mal eine modifizierte Exe, in der Du in dieser Funktion jeden Parameter in einem Textfile mitloggst, so daß Du Deinen Verdacht mit dem Ausstieg genau prüfen kannst.
-
Du solltest folgende Fehlerquelle in Deiner Konfiguration in Betracht ziehen:
Daß der Pfadname, aus der Du die Konfigdatei lädst, enthält einen japanischen Namen (ist also ein Unicode-Pfadname). Also sozusagen "Eigene Dokumente" oder "Programme" auf japanisch.
Der OpenFileDialog würde nun mit einem true zurückkehren, da die Datei existiert, die Auswahl ist perfekt. Aber Du erhälst jetzt einen Dateinamen, der folgendem Muster entspricht:
0, H, 0, a, 0, l, 0, l, 0, W, 0, e, 0, l, 0, t
Aber Hallo! Intelsystem - Reihenfolge ist Lowbyte first, d.h. im Speicher hast Du einen Inhalt H, 0, etc stehen.
Was macht readFileData, wenn sFileName keinen gültigen String enthält?
Denk mal über diese Sache nach, vielleicht fällt Dir dann noch eine zusätzliche Fehlerquelle ein, die ich jetzt nicht sehen kann.
Aber damit kann es passieren, daß ein formal gültiger OpenFileDialog einen (für Dich) ungültigen Dateinamen liefert.
-
-
So wie ich es sehe, hat UNICODE probleme mit dem erweiterten ASCII-Satz.
ich habe im File, welche auf den Jp-Windows geöffnet wird z.B. die Zeile:
100:Französisch|French|||;
Anscheinend können die Japaner das 'ö'-Zeichen nicht auslesen. Die Dateizeil wird in ein CString gespeichert.
Das Problem bei CString ist, dass sobald ein 0x00 oder ein anderes (nicht alle) ASCII-Steuerzeichen gelesen wird, dass dann abgebrochen wird.Es steht dann vermutlich im CString "100:Franz"
Diese Datenzeile ist nicht vollständig und kann somit nicht verarbeitet werden. Es gibt einen Fehler.
So, was ich jetzt nicht verstehe ist, weshalb abgebrochen wird? Ich meine, das Programm liest ja nicht das 'ö' ein, sondern der Bytewert (also irgend ein wert im 8. ASCIIbit). Von mir aus kann's doch Schnuppe sein, ob jetzt auf dem PC ein 'ö' oder halt ein anderes Zeichen dafür angezeigt wird.
-
Erweitertes-ASCII ist genauso eine ASCII Erweiterung wie Unicode. Die ersten 7Bit Unicode sind ja auch ASCII kompatibel. Das was man unter DOS als Extended-ASCII kennt, ist also quasi eine primitive Unicode form. Aber da eben deutlich weniger Zeichen unterstützt werden, ziemlich eingeschränkt.
Es wird abgebrochen weil du im Text-Modus liest (der unterscheidet sich unter Window vom Binär-Modus!). Sprich sobald ein EOF Zeichen kommt hört der auf zu lesen.
UTF-8 könnte eine Lösung für dich sein. Obwohl unter Windows wohl UCS-2/UTF-16 gängiger ist:
http://www.cl.cam.ac.uk/~mgk25/unicode.html
http://www.unicode.org/
-
Danke für die Info & Links.
Ich denke ich sollte versuchen, vor dem einlesen der Daten die Codepage auf <Western> zu stellen (also #1252). Dann sollten die Zeichen eigentlich <normal> interpretierbar sein. Nicht? Denn sämtliche Texte sind in diesem <Latin-1> Format (Da lassen sich die Zeichen aus dem engl. franz. etc. ganz gut abbilden).