PHP "echte" Windows Unicode-Textdatei schreiben
Peter Steinfeld
- php
Hallo zusammen,
wie man schon am Titel sehen kann, weiß ich nicht so recht worum es sich hier eigentlich handelt. Hier also der Erklärungsversuch:
Ich möchte mit einem PHP-CLI-Script eine Textdatei erstellen die ich dem windowseigenen ntbackup-programm unterjubeln kann.
Leider erstelle ich zur Zeit nur ANSI (oder ASCII?) Textdateien, welche das ntbackup verschmäht und deshalb (übrigens ohne Fehlermeldung) nicht arbeitet.
Wenn ich eine Textdatei mit dem ntbackup erstelle, und diese in meinem Texteditor (NoteTab Pro) öffne, sehe ich das dies eine Unicode-Datei ist. NoteTab öffnet diese nämlich nur im Lesezugriff, weil leider noch keine komplette Unicodeunterstützung implementiert ist.
Bisher habe ich einige Konvertierungsversuche innerhalb PHP ausprobiert, aber es will mir nicht gelingen eine (Windows)-Unicode-Datei zu erstellen. Es ergibt immer eine einfache Textdatei voller Zahlenfolgen oder ähnlichem. Zum schreiben der Datei nutze ich fopen, fwrite, fclose.
Weiß jemand was da falsch läuft?
Gruß Peter
Hallo Peter,
wie man schon am Titel sehen kann, weiß ich nicht so recht worum es sich hier eigentlich handelt.
ich vermute, um eine Fehlinformation deinerseits, was "Unicode" eigentlich ist.
Leider erstelle ich zur Zeit nur ANSI (oder ASCII?) Textdateien, welche das ntbackup verschmäht und deshalb (übrigens ohne Fehlermeldung) nicht arbeitet.
Also, dass das Windows-eigene Backup da so zickig ist, wusste ich bisher noch nicht; ich nutze es selbst auch nicht. Was du bisher erzeugt hast, sind vermutlich normale Textdateien, in denen jedes Zeichen genau ein Byte belegt. Das Ganze dann vermutlich als ISO-8859-1 (Windows nennt das dann "ANSI") oder noch wahrscheinlicher als Windows-1252 codiert.
Wenn ich eine Textdatei mit dem ntbackup erstelle, und diese in meinem Texteditor (NoteTab Pro) öffne, sehe ich das dies eine Unicode-Datei ist.
Woran siehst du das?
Was du siehst, ist vermutlich, dass diese Datei immer im Wechsel ein reguläres Textzeichen und ein Nullbyte enthält. Ja, das ist wohl Unicode, aber in der bescheuerten Codierung UTF-16, bei der jedes Zeichen 16bit, also zwei Bytes, belegt. Auch regedit erzeugt gern solche Dateien (aber der akzeptiert auch "normale" 8bit-Codierungen wie ISO-8859-x oder Windows-1252, jedoch nicht UTF-8).
Bisher habe ich einige Konvertierungsversuche innerhalb PHP ausprobiert, aber es will mir nicht gelingen eine (Windows)-Unicode-Datei zu erstellen.
Wie schon gesagt: Du suchst nach einer Möglichkeit, Textdateien in UTF-16 zu erzeugen. Dieses Format benutzt Windows übrigens auch intern sehr viel.
So long,
Martin
Hallo Martin,
ich vermute, um eine Fehlinformation deinerseits, was "Unicode" eigentlich ist.
Hmm, jain. Mir war schon klar das das irgendwas Windoofspezifisches sein würde, deshalb schrieb ich im Titel [ "echte" Windows-Unicode.. ].
Leider erstelle ich zur Zeit nur ANSI (oder ASCII?) Textdateien, welche das ntbackup verschmäht und deshalb (übrigens ohne Fehlermeldung) nicht arbeitet.
Also, dass das Windows-eigene Backup da so zickig ist, wusste ich bisher noch nicht; ich nutze es selbst auch nicht. Was du bisher erzeugt hast, sind vermutlich normale Textdateien, in denen jedes Zeichen genau ein Byte belegt. Das Ganze dann vermutlich als ISO-8859-1 (Windows nennt das dann "ANSI") oder noch wahrscheinlicher als Windows-1252 codiert.
Ja genau, es sind einfache Textdateien, als Windows-1252 codiert.
Wenn ich eine Textdatei mit dem ntbackup erstelle, und diese in meinem Texteditor (NoteTab Pro) öffne, sehe ich das dies eine Unicode-Datei ist.
Woran siehst du das?
Bis vorhin nur an der Meldung in der Statuszeile meines Editors:
Read only [2933 bytes, 64 ines, last saved: 10.06.2006 14:47:00, Format: Unicode]
In der Zwischenzeit habe ich mir aber noch einen HexViewer installiert und die Dateien damit mal angeschaut. Es sind die normalen Textzeichen drin jeweils gefolgt von einem NullWert.
Was du siehst, ist vermutlich, dass diese Datei immer im Wechsel ein reguläres Textzeichen und ein Nullbyte enthält. Ja, das ist wohl Unicode, aber in der bescheuerten Codierung UTF-16, bei der jedes Zeichen 16bit, also zwei Bytes, belegt. Auch regedit erzeugt gern solche Dateien (aber der akzeptiert auch "normale" 8bit-Codierungen wie ISO-8859-x oder Windows-1252, jedoch nicht UTF-8).
Ja, so isses.
Wie schon gesagt: Du suchst nach einer Möglichkeit, Textdateien in UTF-16 zu erzeugen. Dieses Format benutzt Windows übrigens auch intern sehr viel.
Ja, so isses wohl.
UTF-16 habe ich nicht gewußt. Deshalb haben auch die Konvertierungen nach UTF-8 nicht gefruchtet.
Ich habe mittlerweile die folgende Lösung gefunden:
Über die COM-Schnittstelle die PHP in den WindowsDistributionen zur Verfügung stellt spreche ich das FSO (FileSystemObject) der ScriptingRuntime-ActiveX-DLL an, und lasse die dann eine "echte" Windows-Unicode-Textdatei schreiben.
Sozusagen VB-Script in PHP, ;-)
Nicht schön aber funktioniert und erspart mir eine weitergehende Auseinandersetzung mit den windowsspezifischen Codierungsformaten.
(Das ist einfach nicht meine Welt.)
Vielen Dank für die Aufklärung und ein schönes Wochenende,
Peter
Hallo Peter,
Bis vorhin nur an der Meldung in der Statuszeile meines Editors:
Read only [2933 bytes, 64 ines, last saved: 10.06.2006 14:47:00, Format: Unicode]
Nur, weil Dein Editor das anzeigt, muss das nicht stimmen. Es gibt einen Unterschied zwischen Unicode und UTF-16 - Windows verwendet UTF-16 (Unicode ist sowieso keine Zeichenkodierung, sondern ein Zeichensatz). UTF-16 hat zwar eine ganze Menge mit Unicode zu tun, ist aber *nicht* das gleiche.
In der Zwischenzeit habe ich mir aber noch einen HexViewer installiert und die Dateien damit mal angeschaut. Es sind die normalen Textzeichen drin jeweils gefolgt von einem NullWert.
Das stimmt so nicht ganz. In UTF-16 ist die Basiseinheit 2 Bytes groß; UTF-16 ist jedoch *keine* 16bit-Kodierung, da es Zeichen gibt, die in UTF-16 auch mit 4 Bytes kodiert werden. Für alle Zeichen aus ISO-8859-1 stimmt die Aussage, da die Kodierungswerte der einzelnen Zeichen in ISO-8859-1 mit den Codepositionen der einzelnen Zeichen im Unicode-Standard decken (und ISO-8859-1 nur ein Byte braucht). Allerdings verwendet Windows ja kein ISO-8859-1 sondern Windows-1252, was ISO-8859-1 ist, allerdings wird dort auch der in den ISO-Standards nicht verwendete Bereich zwischen 0x80 bis 0x9F genutzt - weswegen das Einfügen von Null-Bytes zwischen Windows-1252 *nicht* automatisch zu einem gültigen UTF-16-Text führt, da die zusätzlich eingefügten Zeichen wie das Euro-Zeichen bei 0x80 in Unicode eine komplett andere Codeposition haben, als ihr kodierter Wert in Windows-1252 - beim Eurozeichen wäre das 0x20AC (bei ISO-8859-1 funktioniert das dagegen - naja, fast, denn:) - ferner ist zu beachten, dass UTF-16 zwingend einen sog. BOM (Byte Order Mark) vorschreibt - der gibt an, wie die Bytes angeordnet sind (Little-Endian vs. Big-Endian). Wenn Du also einen ISO-8859-1-Text nimmst und dort dann noch 0-Bytes einfügst, erhälst Du nur dann einen gültigen UTF-16-Text, wenn Du noch einen korrekten BOM an den Anfang des Textes einfügst.
Ich habe mittlerweile die folgende Lösung gefunden:
Über die COM-Schnittstelle die PHP in den WindowsDistributionen zur Verfügung stellt spreche ich das FSO (FileSystemObject) der ScriptingRuntime-ActiveX-DLL an, und lasse die dann eine "echte" Windows-Unicode-Textdatei schreiben.
Hälst Du es nicht für sinnvoller, den Text einfach nach UTF-16 zu konvertieren? Also $text = iconv('Windows-1252', 'UTF-16', $text);
Viele Grüße,
Christian
Hallo Christian,
»»»» In der Zwischenzeit habe ich mir aber noch einen HexViewer installiert und die Dateien damit mal angeschaut. Es sind die normalen Textzeichen drin jeweils gefolgt von einem NullWert.
»»Das stimmt so nicht ganz. In UTF-16 ist die Basiseinheit 2 Bytes groß; UTF-16 ist jedoch *keine* 16bit-Kodierung, da es Zeichen gibt, die in UTF-16 auch mit 4 Bytes kodiert werden. Für alle Zeichen aus ISO-8859-1 stimmt die Aussage, da die Kodierungswerte der einzelnen Zeichen in ISO-8859-1 mit den Codepositionen der einzelnen Zeichen im Unicode-Standard decken (und ISO-8859-1 nur ein Byte braucht). Allerdings verwendet Windows ja kein ISO-8859-1 sondern Windows-1252, was ISO-8859-1 ist, allerdings wird dort auch der in den ISO-Standards nicht verwendete Bereich zwischen 0x80 bis 0x9F genutzt - weswegen das Einfügen von Null-Bytes zwischen Windows-1252 *nicht* automatisch zu einem gültigen UTF-16-Text führt,
Ok, dann habe/hätte ich jetzt einfach nur Glück gehabt weil ich nur Dateipfade speichere, bei denen ich sowieso auf alle möglichen Sonderzeichen und Leerzeichen usw. verzichte.
Hälst Du es nicht für sinnvoller, den Text einfach nach UTF-16 zu konvertieren? Also
$text = iconv('Windows-1252', 'UTF-16', $text);
Ja klar ist das sinnvoller :)
Wie gesagt, bis zur Erklärung von Martin wußte ich ja nicht das die Datei in UTF-16 angelegt sein muß.
Und da ich nun mal sehr ungeduldig bin, bastelte ich mir den Weg über die COM-Schnittstelle zusammen. Jetzt kann ich die paar Zeilen Code ja wieder löschen, ;-)
Danke für die Hilfe,
Peter