![]() |
Umlaute in Windows
Hi Leute,
ich habe hier einen alten Datenbestand, den will ich in eine DB importieren. Es ist aber eine reine ASCII Datei mit deutschen Umlauten. Letztere werden in Windows falsch dargestellt. Soll ich versuchen die Ascii - Datei, so umzubauen, daß Windows damit klar kommt, oder sie lieber so lassen wie sie ist und beim Importieren zusehen, daß es richtig ankommt. Wobei ich weder weiß, wie das erste gehen würde noch das zweite. :mrgreen: Gruß Hansa |
Moin Hansa,
versuch's mal mit OemToChar bzw. CharToOem. (für den ersten Fall). Wenn Du Dir ganz sicher bist, dass es sich nur um ä,ö,ü,Ä,Ö,Ü und ß handelt und nicht vielleicht noch französische, spanische .... Zeichen enthalten sind, käme vielleicht noch eine selbstgestrickte Funktion in Frage. Aber versuch's erst einmal mit den genannten Funktionen. |
Hi,
vielleicht bringt Dich das auf neue Gedanken... ![]() Grüsse, Daniel :hi: |
Hallo Chris,
Zitat:
Wo ist das OemToChar usw. ? Hab ich noch gar nicht gesehen. Gruß Hansa |
Moin Hansa,
mach mal eine Konsole auf, und starte dort mal Edit (also den DOS Editor, wichtig!) Jetzt die sieben deutschen Sonderzeichen eingeben, und als c:\oemtest.txt speichern. Wenn Du jetzt
Code:
mal probierst, wirst Du die Wirkung von OemToChar sehen können.
[b]procedure[/b] TForm1.Button1Click(Sender: TObject);
[b]var[/b] fsWork : TFileStream; sWork : [b]string[/b]; [b]begin[/b] fsWork := TFileStream.Create('c:\oemtest.txt',fmOpenRead); [b]try[/b] sWork := StringOfChar(#00,fsWork.Size); fsWork.Read(sWork[1],fsWork.Size); [b]finally[/b] FreeAndNil(fsWork); [b]end[/b]; ShowMessage(sWork); OemToChar(@sWork[1],@sWork[1]); ShowMessage(sWork); [b]end[/b]; |
Danke Daniel,
das müsste das gesuchte sein, werde es mal einbauen. Wußte ja sowieso schon wie es geht, aber nicht wie. :mrgreen: Das hier war mal eine Funktion, die ich gemacht habe, um so etwas ähnliches zu bereinigen:
Code:
Sieht fast genauso aus, oder?
FUNCTION gross (inp : string) : string; (* Achtung : UpCase klappt *)
VAR i : integer; (* nicht bei 'a.ö,ü' *) BEGIN FOR i := 0 TO length(inp) DO BEGIN gross[i] := UpCase(inp[i]); IF ord(inp[i]) > 122 THEN BEGIN (* 122 = 'z' *) CASE inp[i] OF 'ä' : gross[i] := 'Ä'; 'ö' : gross[i] := 'Ö'; 'ü' : gross[i] := 'Ü'; END; END; END; END; Gruß Hansa |
Hallo Christian,
Auch Danke für die Antwort. Aber es handelt sich ja um einen einmaligen Vorgang. Sollte es so gehen, wie Daniel schreibt (ich meine das im Link), um so besser. Das verstehen dann auch noch andere hier, die so etwas dann im Fall der Fälle durchziehen könnten. Gruß Hansa |
Moin Hansa,
das hättest Du mit AnsiUpperCase aber einfacher haben können ;-) Die Funktion erledigt das mit einem Aufruf. Bevor ich OemToChar kannte hab' ich's, im Prinzip, mal so gelöst:
Code:
Absolut nicht ideal, aber tut's.
[b]function[/b] DosToWin([b]const[/b] p_sLine : [b]string[/b]) : [b]string[/b];
[b]begin[/b] Result := StringReplace(p_sLine,chr($84),'ä',[rfReplaceAll]); Result := StringReplace(p_sLine,chr($94),'ö',[rfReplaceAll]); Result := StringReplace(p_sLine,chr($81),'ü',[rfReplaceAll]); Result := StringReplace(p_sLine,chr($8E),'Ä',[rfReplaceAll]); Result := StringReplace(p_sLine,chr($99),'Ö',[rfReplaceAll]); Result := StringReplace(p_sLine,chr($9A),'Ü',[rfReplaceAll]); Result := StringReplace(p_sLine,chr($E1),'ß',[rfReplaceAll]); [b]end[/b]; Leider kostet der Komfort bei der Stringverarbeitung in Delphi ziemlich viel Zeit. Deshalb bin ich inzwischen mehr auf Pointer bzw. Assembler ausgewichen, wenn es um umfangreichen Stringverarbeitung geht. Das spart Laufzeit ohne Ende. |
Moin Hansa,
das was in Daniel's Link zu sehen ist, finde ich allerdings etwas aufwändiger, als eine Zeile OemToChar ;-) Mein Beispiel sollte Dir nur zeigen, wie's vor und nach dem Aufruf aussieht. Du kannst Du Ascii Datei ja auch in einem Rutsch in einen Filestream einlesen, mit OemToChar umwandeln, und wieder zurückschreiben. Die Länge ändert sich ja nicht. Da auch im Deutschen, z.B. Namen, französische Zeichen enthalten können, halte ich die Beschränkung auf deutsche Umlaute jedenfalls für gefährlich. So wäre es allgemein brauchbar (ausser für Unicode):
Code:
[b]procedure[/b] TForm1.Button1Click(Sender: TObject);
[b]var[/b] fsWork : TFileStream; sWork : [b]string[/b]; [b]begin[/b] [b]if[/b] OpenDialog1.Execute [b]then[/b] [b]begin[/b] fsWork := TFileStream.Create(OpenDialog1.FileName,fmOpenRead); [b]try[/b] sWork := StringOfChar(#00,fsWork.Size); fsWork.Read(sWork[1],fsWork.Size); [b]finally[/b] FreeAndNil(fsWork); [b]end[/b]; OemToChar(@sWork[1],@sWork[1]); fsWork := TFileStream.Create(OpenDialog1.FileName+'.conv',fmCreate); [b]try[/b] fsWork.Write(sWork[1],Length(sWork)); [b]finally[/b] FreeAndNil(fsWork); [b]end[/b]; [b]end[/b]; [b]end[/b]; |
Hi Chris,
Zitat:
Das ganze hat auch nur indirekt mit Delphi zu tun. Ich kriege eine Ascii - Datei geliefert, die soll in eine Interbase-DB rein (mit EXTERNAL FILE usw.). Das natürlich möglichst schön, vielleicht auch mit franz. Zeichen, aber viele sind das nicht. In Interbase zeigt er mir halt im Moment die Umlaute falsch an. Später mit dem Delphi-Programm juckt mich das ganze dann nicht mehr, sofern die Umlaute dann wieder stimmen. Jetzt kommt mein alter Ansatz wieder ins Spiel: notfalls Zeichen für Zeichen lesen und mittels CASE und Daniels Tip einzelne Zeichen umwandeln und in eine zweite Datei schreiben. Diese würde ich dann mit Interbase importieren und das wärs dann. Gruß Hansa [/quote] |
Moin Hansa,
eine Konvertierungsroutine hab' ich Dir ja jetzt komplett geliefert ;-) (letztes Posting) Du brauchst jetzt nur noch ein Formular, einen OpenDialog und einen Button. Das AnsiUpperCase einen Bug hat ist mir allerdings neu, und mangels intensiver Nutzung, auch noch nicht aufgefallen. Da AnsiUpperCase auf der API CharUpperBuff (User32.dll) basiert, könnte man aus auch noch einmal mit der API CharUpper versuchen. Natürlich steht zu befürchten, dass die auch fehlerhaft arbeitet. |
Hi Chris,
tja, weiß auch nicht so recht. Manchmal sind Fehler da, obwohl angeblich keiner sie sieht oder es nicht zugibt. Bis ich bei Borland anrief habe ich lange in meinem Programm gesucht. Wäre heute noch dran. :D Da ich ein Freund möglichst einfacher Dinge bin, ich meine jetzt beim Programmieren :oops:, habe ich erst mal die Spur von Daniel bis zum Ende verfolgt. Dein Spezialgebiet und auch das von Luckie ist mir ein Greuel. :mrgreen: Vorweg : das klappt so schon einwandfrei. Aber auch in Daniels Code sind zwei kleine Fehler. :P Die erkläre ich zum Schluß, weil sie vor allem Anfänger womöglich tagelang aufhalten. Muß ja nicht sein. Hier nochmal der (modifizierte) Code :
Code:
Der erste Fehler ist mit bloßem Auge zu erkennen : Die Variable Result war in dem alten Code nicht innerhalb der Funktion deklariert. Wer die beiden Fu. also benutzt kriegt hoffentlich einen Compiler-Fehler. Nicht schlimm, aber wenn dieser Fehler NICHT kommt, dann ist die Var. globaler deklariert und da ihr ein Wert INNERHALB der Funktion zugewiesen wird, wird dieser somit "verbogen". Da ist Gefahr im Verzug.
function AnsiToIBMAscii(s: string): string;
var i: integer; Result : string; begin Result := ''; for i := 1 to Length(s) do begin case s[ii] of #196: Result := Result + #142; (* Ä *) #214: Result := Result + #153; (* Ö *) #220: Result := Result + #154; (* Ü *) #228: Result := Result + #132; (* ä *) #246: Result := Result + #148; (* ö *) #252: Result := Result + #129; (* ü *) #223: Result := Result + #225; (* ß *) else Result := Result + s[i]; end; end; AnsiToIBMAscii := Result; end; function IBMAsciiToAnsi(s: string): string; var i: integer; Result : string; begin Result := ''; for i := 1 to Length(s) do begin case s[ii] of #142: Result := Result + #196; (* Ä *) #153: Result := Result + #214; (* Ö *) #154: Result := Result + #220; (* Ü *) #132: Result := Result + #228; (* ä *) #148: Result := Result + #246; (* ö *) #129: Result := Result + #252; (* ü *) #225: Result := Result + #223; (* ß *) else Result := Result + s[i]; end; end; IBMAsciiToAnsi := Result; end; Der zweite Fehler liegt in der FOR-Schleife. Die soll vom ERSTEN bis zum letzten Buchstaben des strings laufen. In der Ursprungsfassung fing sie aber bei 0 schon an. Dadurch wurde in meiner DB bei jedem string-Feld ein komisches 1. Zeichen eingefügt, das auch noch gleich war und das letzte wurde abgeschnitten (Platz für 30 Zeichen nicht 31 !). Das war das Längenbyte in s [0]. Das braucht man aber nicht mitzuschleppen, Da Result := '' am Anfang steht. Direkt darauf zugreifen sollte man sowieso nicht. Gruß Hansa |
Hallo Hansa,
Deine Bemerkung zur Variablen "Result" stimmt nicht ganz. Diese wird bei Funktionen von ObjectPascal implizit deklariert und wird als Rückgabewert einer Funktion genutzt: Zitat:
|
Hi,
hast ja Recht. :D Aber nur theoretisch. :mrgreen: Durch sowas wird man schnell aufs Glatteis geführt und dann Gute Nacht! Ich jedenfalls versuche tunlichst solchen Sachen aus dem Wege zu gehen. Und dann noch so ein Allerweltswort!! Siehste, jetzt hab ich selber nicht daran gedacht. Gruß Hansa |
Moin Hansa,
also Deiner letzen Ausführung vermag ich irgendwie nicht so recht zu folgen. Könntest Du das bitte mal näher erklären? |
Hi,
das mit dem Result, ich meinte, dann kann man ja gleich BEGIN oder END als Resultat zurückliefern. :bounce2: War das gemeint ? :shock: Gruß Hansa |
Moin Hansa,
alles in allem hab' ich nicht verstanden, was Du bei Result für Probleme siehst. Wie Daniel schon sagte ist diese Variable ja bei Funktionen automatisch vorhanden, und kann innerhalb der Funktion beliebig genutzt werden. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:11 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz