AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Unicode in Textfiles...

Ein Thema von himitsu · begonnen am 20. Feb 2006 · letzter Beitrag vom 22. Feb 2006
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#1

Unicode in Textfiles...

  Alt 20. Feb 2006, 15:24
Ich mach das jetzt einfach mal öffentlich (denke nicht, daß PAX was dagegen haben wird),
damit auch mal andere mitreden, oder auch was davon haben können

Zitat von PAX (per PN):
Zitat:
Die TNT-Controls seh'n nicht schlecht aus. Und wenn ich mich entscheiden muss, werd' ich wohl bei NT bleiben. (arbeite selbst mit 2000P)

Nach Möglichkeit versuche ich aber so zu arbeiten, das es unter 95 bis XP (demnächst natürlich auch Longhorn) läuft.
Auf der HomePage werden zusätzlich noch downloadbare Schriftarten eingebunden, so das man auch ohne die entsprechende Sprachunterstützung was erkennt.
Es ist schon richtig schwer etwas so zu schreiben, das es bei möglichst vielen läuft.

Und das mit UCS4 jetzt noch nicht so viel los ist, hatte ich mir schon gedacht.
Der Unicode Standard v4.0.0, mit dem die 4-Byte Unicodezeichen eingeführt wurden, ist glaube ich auch erst dieses Jahr offiziell rausgekommen.
Da aber die von Microsoft ja sonst alles einbauen, egal ob es richtig funktioniert oder nicht, hätte da also auch schon etwas vorhanden sein können.


Question Gibt es noch 'ne Möglichkeit an diesen Artikel ran zu kommen. Werd' mich zwar mal etwas umschauen. Hab aber keine großen Hoffnungen.
grüß dich, himitsu!

ich schreib n programm, wo ich auch osteuropäische und asiatische schriftzeichen verwenden können muss. ich benutze dafür die tnt-tools. das problem ist, wenn ich beispielsweise eine zeichenkette mit russischen zeichen habe (innerhalb einer tnt-komponente) und möchte die in eine datei schreiben, dann kann ich das nicht einfach über den normalen typ string machen - das hab ich inzwischen mitbekommen. offensichtlich muss ich dabei also mit widestring arbeiten. es geht nur irgendwie nicht, eine file of record zu machen, wobei im record nun nicht mehr der typ string ist, sondern widestring?

Delphi-Quellcode:
type Vocable = record
      Vlinks,Vrechts: widestring;
end;

var
  Form1: TForm1;
  Datei: file of Vocable;
naja ok. aber wenn man sich theoretisch einen font selbst macht, wo an den entsprechenden positionen einfach ein anderes zeichen gemalt ist, dann würde das ganz ohne tnt machbar sein. woher bekommt man denn derartig manipulierte fonts? ich bräuchte russisch, türkisch, italienisch, französisch, usw. (möglichst viel).

kannst du mir vielleicht helfen?

danke für deine aufmerksamkeit!

viva los tioz!


PAX
Erstmal zu den Fonts ... theoretisch könnte man die sich selber machen (hatte ich auch mal, weil ich 'ne andere Schrift und noch'n paar spezielle Zeichen brauchte), oder man sucht mal im INet ... irgendwo schwirren ja die gewünschten Fonts meistens auch schon fertig rum,
aber soooo optimal ist das dann ja auch nicht, da du dann ja jedesmal auf den nötigen Font umstellen und diese Information (welcher Font benötigt wird) auch noch irgendwie mit speichern mußt.

Am Einfachsten ist es also, wenn du bei Unicode bleibst (da ist ja schon alles vorhanden, bzw. wer's braucht, weiß wo/wie er/sie sich die nötigen Fonst installieren muß).


Nun gibt's aber auch mehrere Varianten, wie du nun den String speicherst.
Leider gibt's aber keine "gute" Möglichkeit die Standard-Textdatei-Funktionen so zu ändern, daß diese WideString-tauglich werden, also so wie ich es z.B. in 64-Bit für TextFile / File of xxx gemacht hatte, damit diese Funktionen 64-Bit-tauglich (also für Dateien größer 2 GB) sind.

Die Idee mit dem Record ist leider total falsch gewählt, denn Ansi-/WideStrings sind sozusagen dynamische Array's und so wie bei diesen dynamischen Arrays ist die Variable in Wirklichkeit nur ein Pointer aud den entsprechende Datenbereich. (OK, aus irgendwelchen gründen ist das beim WideString nicht ganz die Wahrheit, da dort Borland, warum auch immer einen OLE-String mißbraucht, aber das ist hierfür mal ein bissl unwichtig)

Also speicherst du mit dem Record nur die Pointer, welche nach dem Laden dann auf irgendwas, aber nicht unbedingt auf deine gewünschten WideStrings zeigen.


Die Typen-Defs für nachfolgendes:
Delphi-Quellcode:
Var F: File/File of Byte/oder ähnliches;
  T: TextFile;
  L: LongInt/Integer;
  W: WideString;
  C: WideChar;
  S: AnsiString;
Ansonsten ist nachfolgend immer ein schematischer Code zum Speichern und danach zum Aulesen angegeben und die Sachen zum öffnen/schließen der Dateien sind auch einfach mal weggelassen worden


Wenn nur ein einziger String in der Datei rumliegt:
Delphi-Quellcode:
Write(F, @W[1], Length(W) * 2);

SetLength(W, FileSize div 2);
Read(F, @W[1], Length(W) * 2);
Mit Längenangabe:
Delphi-Quellcode:
L := Length(W);
Write(F, @L, 4);
Write(F, @W[1], L * 2);

Read(F, @L, 4);
SetLength(W, L);
Read(F, @W[1], L * 2);
Mit abschließender #0 (also PWideChar):
Delphi-Quellcode:
Write(F, @W[1], L * 2 + 2);

// irgendwie bis zur nächsten #0 einlesen
// z.B.
W := '';
While not EoF(F);
  Read(F, @C, 2);
  If C = #0 Then Break;
  L := Length(W) + 1;
  SetLength(W, L);
  @W[L] := C;
End;

Das Write/WriteLn/Read/ReadLn für TextFile nimmt zwar auch WideStrings an, allerdings wird das intern nur in ANSI umgewandelt und auch als AnsiString gelesen/geschrieben.

Es ist allerdings auch möglich den WideString in ein ANSI-verträgliches Format umzuwandeln ... z.B. UTF8 und dieses dann als ANSI zu speichern (ohne einen Informationsverlust, wie bei der einfachen Umwandlung von Wide nach Ansi).
Delphi-Quellcode:
WideToUTF8(W, A);
WriteLn(T, A);

ReadLn(T, A);
UTF8ToWide(A, W);
Im Endefekt wird das mit dem Umweg über UTF8 erstmal am Praktischsten sein.


Ansonsten bastele ich (wenn ich mal wieder Zeit dafür hab) an meiner eigenen Dateiklasse weiter (diese kann bis jetzt AnsiString und WideString (BigEndian), wird aber noch um WideString (LE), sowie LongString (LE+BE) und eine bessere Verbindung zwischen diesen Typen erweitert)

[OT] Was ich jedem empfehlen kann ... Konsolen-, oder von mir aus auch NonVCL-Anwendungen mit Notepad erstellen und sich dann bei Gelegenheit mal überraschen zu lassen, was der Compiler zu dem File sagt ... macht echt Spaß
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#2

Re: Unicode in Textfiles...

  Alt 21. Feb 2006, 16:17
danke himitsu, wirklich selbstlos von dir, dass du dir die zeit für mich genommen hast!

das problem is, ich schreibe in eine datei vom typ record. also praktisch mit diesen parametern:

Delphi-Quellcode:
type Vocable = record
      Vlinks,Vrechts: string[255];
end;
bei der variante mit der zeigerspielerei hab ich nicht verstanden, warum die länge mit 2 multipliziert werden muss. und des weiteren müssen mehrere widestrings darin gespeichert werden, quasi anfang und ende eines jeden strings müssen irgendwie klar sein. vielleicht könnte man immer grundsätzlich eine feste länge der zeichenkette schreiben und den rest ggf. mit leerzeichen auffüllen?


bei der 2. möglichkeit hab ich mal geguckt und musste feststellen, dass ich die funktion widetoutf8 nicht habe. es gibt aber konvertierungsfunktionen zwischen ansi und utf8, und unicode (is das nich widestring?) und utf8. das hat aber nich hingehauen und bei unicodetoutf8 seh ich nicht durch.
aber theoretisch sollte das funktionieren, wenn ich widetoansi anwende? also wenn ich kyrillische buchstaben in der tntkomponente habe und diese konvertiere, in datei speichere und sie wieder auslese und zurücklade in die komponente (vorher wieder ansitowide), dann steht dort exakt das selbe wie zuvor?

dankeschön für deine hilfe!



PAX
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#3

Re: Unicode in Textfiles...

  Alt 22. Feb 2006, 13:19
ich hab gerade keine befehlsliste zur hand, aber das dritte argument bei write is doch die anzahl der zu schreibenden zeichen, gell? warum muss hier mal 2 multipliziert werden?
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#4

Re: Unicode in Textfiles...

  Alt 22. Feb 2006, 15:10
Zitat von PAX:
das problem is, ich schreibe in eine datei vom typ record. also praktisch mit diesen parametern:

Delphi-Quellcode:
type Vocable = record
      Vlinks,Vrechts: string[255];
end;
Den ShortString / String[...] gib es ja nur für SingleByteStrings (Ansi und Co.)

Bei WideString könnte man höchstens einen Array verwenden.
(diese Variante hatte ich ja oben auch noch vergessen -.-'')
Delphi-Quellcode:
type Vocable = record
    Vlinks, Vrechts: array[1..255] of WideChar;
  end;
Und dort dann muß man dann nur die Strings rein-/rauskopieren
Ob der Compiler auch bei WindeStrings eine automatische Konvertierung vornimmt, weiß ich jetzt garnicht, also ob Nachfolgendes gleich möglich ist:
Delphi-Quellcode:
Var V: Vocable;
  S: WideString;

V.Vlinks := S;
S := V.Vlinks;
Wenn nicht, dann muß man es halt selber machen.
z.B. zum reinkopieren:
Delphi-Quellcode:
MemCopy(@V.Vlinks[1], S[1], Length(S) * 2 + 2);
// natürlich nur, wenn der String (nach der obrigen Definition von Vocable) nicht länger als 254 Zeichen ist

Zitat von PAX:
bei der variante mit der zeigerspielerei hab ich nicht verstanden, warum die länge mit 2 multipliziert werden muss. und des weiteren müssen mehrere widestrings darin gespeichert werden, quasi anfang und ende eines jeden strings müssen irgendwie klar sein. vielleicht könnte man immer grundsätzlich eine feste länge der zeichenkette schreiben und den rest ggf. mit leerzeichen auffüllen?
Also bei den obrigen Beispielen (außer bei der Variante "nur ein String in der Datei") ist ja überall die Länge vorgegeben ... entweder wird die Längenangabe mit gespeichert, oder der String ist per #0 abgeschlossen.

Zitat von PAX:
bei der 2. möglichkeit hab ich mal geguckt und musste feststellen, dass ich die funktion widetoutf8 nicht habe. es gibt aber konvertierungsfunktionen zwischen ansi und utf8, und unicode (is das nich widestring?) und utf8. das hat aber nich hingehauen und bei unicodetoutf8 seh ich nicht durch.
Unicode ist in diesem Fall WideString (oder besser gesagt wohl eher PWideChar).

Eigendlich steht Unicode ja für das Gesamte Zeichensystem, also für die 1-, 2- und 4-ByteZeichen, aber oftmals wird der Name halt nur für die 2-Byte-Zeichen/-Strings verwendet -.-''

Also UnicodeToUtf8 / Utf8ToUnicode sind die Richtigen, für meine obrigen Beispiele.

Als Umsetzung wäre z.B. folgendes möglich:
(Ich hoffe mal es funktioniert so, ansonsten muß sich mal hier wer zu Wort melden, der die Definitionen der Befehle kennt ... konnte auf die Schnelle nur die Parameterliste bekommen und hab mir den Rest vor mir bekannten Funktionen zusammengereimt)
Delphi-Quellcode:
WideToUTF8(W, A);

i := UnicodeToUtf8(nil, @W[1], MaxInt);
SetLength(A, i);
UnicodeToUtf8(@A[1], @W[1], i);
Delphi-Quellcode:
UTF8ToWide(A, W);

i := Utf8ToUnicode(nil, @A[1], MaxInt);
SetLength(W, i);
Utf8ToUnicode(@W[1], @A[1], i);
Zitat von PAX:
aber theoretisch sollte das funktionieren, wenn ich widetoansi anwende? also wenn ich kyrillische buchstaben in der tntkomponente habe und diese konvertiere, in datei speichere und sie wieder auslese und zurücklade in die komponente (vorher wieder ansitowide), dann steht dort exakt das selbe wie zuvor?
Bei WideToAnsi werden die 2-Byte-Zeichen direkt in 1-Byte-Zeichen umgewandelt, wodurch also ein Informationsverlust eintritt - alle Zeichen (Wide), welche sich nicht mit nur einem Byte (Ansi, oder jehr nach verwendetem Zeichensatz) darstellen lassen, werden durch eine Ersatzzeichen (oftmals das Fragezeichen, wobei es ja eigentlich das #$A1 und für LongToWide das #$FFFD gibt) ersetzt.

Zitat von PAX:
ich hab gerade keine befehlsliste zur hand, aber das dritte argument bei write is doch die anzahl der zu schreibenden zeichen, gell? warum muss hier mal 2 multipliziert werden?
Wie gesagt, sie das mal nicht ganz als richtige Befehle an, denn man kann das Ganze ja auf verschiedene Weise lösen (so z.B. auch per Streams)
Code:
Operation(Datei-Handle/-Variable, Zeiger auf Speicherbereich, zu bearbeitente Bytes);
Und die Multiplication mit 2 kommt dfaher, weil hier ja je Zeichen 2 Byte vorliegen, also
Byte = Zeichen * 2.
Zitat von PAX:
bei der 2. möglichkeit hab ich mal geguckt und musste feststellen, dass ich die funktion widetoutf8 nicht habe.
Wie gesagt, das sind sozusagen nur Pseudonamen, sie sollen also nir vermitteln, was gemacht werden muß (hab ja derzeit kein Delphi und auch nicht unbedingt die Zeit im Netz nach den genauen Bezeichnungen zu suchen)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:44 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz