Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Stringkonvertierung (https://www.delphipraxis.net/180970-stringkonvertierung.html)

HPB 4. Jul 2014 08:52

Stringkonvertierung
 
Guten Tag Delphianer,
ich habe folgendes Problem bei der Konvertierung von Strings:
in einer Datei (DATANORM) steht folgende Zeile:

Dyckerhoff Zement CEM II 32,5 R, 25 kg;(Achtung Farb„nderung)

wenn ich die Datei mit dem TotelCommander öffne (Lister) steht folgendes:
Dyckerhoff Zement CEM II 32,5 R, 25 kg;(Achtung Farbänderung)

also die korrekte Umsetzung.

Der TotalCommander benutzt die ASCII-Codierung (ANSI/DOS (lokale Codeseite (1), wie feststellen konnte.
Stelle ich die Codierung im TotalCommander zu Testzwecken um, werden für die Umlaute wieder andere Zeichen dargestellt.

Aber wie kann ich die korrekte Darstellung, Umwandlung erreichen?
Mit welchem Befehl, Funktion kann die Umwandlung gelingen?
Die Umwandlung mit UTF8..., OEMTo... habe ich alles versucht. War aber nicht mit Erfolg gekrönt.
Vielen Dank für Eure Mühen.
Gruß
HPB

mkinzler 4. Jul 2014 09:00

AW: Stringkonvertierung
 
Wie lädst du die Datei in Delphi?

DeddyH 4. Jul 2014 09:01

AW: Stringkonvertierung
 
Delphi-Quellcode:
const
  Test = 'Achtung Farb„nderung';
var
  s: string;
begin
  SetLength(s, Length(Test));
  OEMToCharBuff(PAnsiChar(Test), PChar(s), Length(Test));
  ShowMessage(s);
end;
Sah gut aus.

HPB 4. Jul 2014 09:02

AW: Stringkonvertierung
 
Zitat:

Zitat von mkinzler (Beitrag 1264386)
Wie lädst du die Datei in Delphi?

Delphi-Quellcode:
  AssignFile(fDatei, aDatei);
{$I-}Reset(fDatei);
{$I+ }
und dann mit while not Eof(fDatei) jede Zeile lesen

Blup 4. Jul 2014 09:08

AW: Stringkonvertierung
 
Für den einfachsten Fall sollte das genügen:
Delphi-Quellcode:
function AnsiToOem(const AValue: AnsiString): AnsiString;
begin
  Result := AValue;
  if Length(Result) <> 0 then
    CharToOem(PAnsiChar(Result), PAnsiChar(Result));
end;

function OemToAnsi(const AValue: AnsiString): AnsiString;
begin
  Result := AValue;
  if Length(Result) <> 0 then
    OemToChar(PAnsiChar(Result), PAnsiChar(Result));
end;

var
  sl: TStringList;
begin
  sl.LoadFromFile('Oem.txt');
  sl.Text := OemToAnsi(sl.Text);
  {...}
Wer arbeitet eigentlich noch mit Readln?

HPB 4. Jul 2014 09:10

AW: Stringkonvertierung
 
Zitat:

Zitat von DeddyH (Beitrag 1264387)
Delphi-Quellcode:
const
  Test = 'Achtung Farb„nderung';
var
  s: string;
begin
  SetLength(s, Length(Test));
  OEMToCharBuff(PAnsiChar(Test), PChar(s), Length(Test));
  ShowMessage(s);
end;
Sah gut aus.

Habe ich gerade ausprobiert. Die Umlaute sind nicht vorhanden.

DeddyH 4. Jul 2014 09:12

AW: Stringkonvertierung
 
Komisch, bei mir schon.

[edit] @Blup: Lies mal die Bemerkungen zu OEMToChar/CharToOEM, Dein Code wird unter Delphi > 2007 knallen. Außerdem rät Microsoft selbst von der Verwendung ab.[/edit]
[edit2] Sry, ich hab übersehen, dass Du alles als AnsiStrings deklariert hast. Damit bleibt nur noch Punkt 2. [/edit2]

HPB 4. Jul 2014 09:18

AW: Stringkonvertierung
 
Zitat:

Zitat von Blup (Beitrag 1264392)
Für den einfachsten Fall sollte das genügen:
[delphi]
Wer arbeitet eigentlich noch mit Readln?

Ich. Alter Mann (immerhin 69 Jahre), altes Programm, altes Wissen. Passt doch alles zusammen.
Bin gerade dabei ein uralt Programm umzuschreiben. Es wird nicht gleich alles neu gemacht.
Erst einmal die korrekten Daten bekommen, dann alles weitere.
Gruß HPB

Jumpy 4. Jul 2014 09:20

AW: Stringkonvertierung
 
Vllt. was zur Codierung, könnte helfen:

Zitat:

Die DATANORM-Schnittstelle ist auf eine minimale Hardware-Konfiguration zugeschnitten und erlaubt somit den weitreichenden Einsatz. Alle Datensätze bestehen aus reinem ASCII-Text, wobei jeder Satz exakt 128 Zeichen lang und durch eine Zeichenschaltung (Carriage return/0DH 0AH) abgeschlossen ist.

Der erlaubte Zeichenvorrat lehnt sich an den IBM-Zeichensatz an, wobei jedoch nur die unteren 128 Zeichen erlaubt sind. Lediglich die deutschen Sonderzeichen bilden hier eine Ausnahme und tragen weiterhin die Positionscodes des erweiterten ASCII-Zeichensatzes.
Quelle:
http://www.textarchiv.alojado.de/tex...en-ap1387.html

Blup 4. Jul 2014 10:15

AW: Stringkonvertierung
 
Dann stimmt vermutlich die im Windows eingestellte OEM-Code-Page nicht.
Stell mal in den Ländereinstellungen auf Englisch(USA) und speichern.
Danach wieder auf Deutschland(Deutsch), speichern und Windows neu starten.

Zitat:

[edit] @Blup: Lies mal die Bemerkungen zu OEMToChar/CharToOEM, Dein Code wird unter Delphi > 2007 knallen. Außerdem rät Microsoft selbst von der Verwendung ab.[/edit]
Zitat:

Security Considerations

Using this function incorrectly can compromise the security of your application.
Ich hab nicht vor diese Funktion inkorrekt zu benutzen. Deshalb auch schön in eigene Funktionen gekapselt die mit AnsiString und PAnsiChar arbeiten.
Das sollte auch nach Delphi 2007 keine Probleme verursachen.

In neueren Delphi-Versionen könnte man auch das mal versuchen, kann ich aber grad nicht testen:
Delphi-Quellcode:
function ConvertCodePage(const S: _RawByteStr; AFromCodePage, AToCodepage: Word): _RawByteStr;
begin
  Result := S;
  SetCodePage(Result, AFromCodePage, False); // Codepage der Ausgangsdaten nur festlegen
  SetCodePage(Result, AToCodepage, True);   // Codepage umstellen und Daten konvertieren
end;

sl.Text := ConvertCodePage(sl.Text, 437, 850);

DeddyH 4. Jul 2014 10:27

AW: Stringkonvertierung
 
Ich hatte ja noch einmal editiert. Trotzdem: wenn der Hersteller schon schreibt
Zitat:

Warning Do not use.
dann nehme ich das ernst.

p80286 4. Jul 2014 10:30

AW: Stringkonvertierung
 
Nun wenn Du die Daten nicht mehr zurück liefern mußt, dann laß doch gleich alles durch eine Übersetzungstabelle laufen:
Delphi-Quellcode:
for i:=1 to length(mystring) do
  mystring[i]:=asciitab[mystring[i]];
Die kannst Du anpassen wie Du es gerne hättest.
(diesen OEmtoAnsi's traue ich nur so weit wie ich sie selbst geschrieben habe)

Gruß
K-H

DeddyH 4. Jul 2014 10:42

AW: Stringkonvertierung
 
Zitat:

Zitat von Blup (Beitrag 1264410)
Zitat:

Security Considerations

Using this function incorrectly can compromise the security of your application.
Ich hab nicht vor diese Funktion inkorrekt zu benutzen.

Nach genauerer Betrachtung tust Du das aber. Die Deklaration als AnsiString/PAnsiChar bewirkt ja nicht, dass da nun CharToOEMA/OEMToCharA aufgerufen wird, das muss man schon explizit tun. Deshalb gilt
Zitat:

If the OemToChar function is being used as an ANSI function, the string can be translated in place by setting the lpszDst parameter to the same address as the lpszSrc parameter. This cannot be done if OemToChar is being used as a wide-character function.
auch weiterhin, zumindest ab Delphi 2009.

Uwe Raabe 4. Jul 2014 11:05

AW: Stringkonvertierung
 
Zitat:

Zitat von HPB (Beitrag 1264389)
Delphi-Quellcode:
  AssignFile(fDatei, aDatei);
{$I-}Reset(fDatei);
{$I+ }
und dann mit while not Eof(fDatei) jede Zeile lesen

Du kannst doch bei AssignFile als dritten Parameter die Codepage mitgeben.

Delphi-Quellcode:
AssignFile(fDatei, aDatei, 1);

himitsu 4. Jul 2014 11:24

AW: Stringkonvertierung
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1264430)
Du kannst doch bei AssignFile als dritten Parameter die Codepage mitgeben.

Delphi-Quellcode:
AssignFile(fDatei, aDatei, 1);

War das nicht die Rect-Größe?
[edit] Halt, RecSize wurde beim Reset/Rewrite angegeben. :gruebel:

Aber dem AnsiString-Read/ReadLn kann man die CodePage mitgeben. (laut dem QuellCode der XE-System.pas)

Blup 4. Jul 2014 16:04

AW: Stringkonvertierung
 
Zitat:

Zitat von DeddyH (Beitrag 1264419)
Nach genauerer Betrachtung tust Du das aber. Die Deklaration als AnsiString/PAnsiChar bewirkt ja nicht, dass da nun CharToOEMA/OEMToCharA aufgerufen wird, das muss man schon explizit tun. Deshalb gilt
Zitat:

If the OemToChar function is being used as an ANSI function, the string can be translated in place by setting the lpszDst parameter to the same address as the lpszSrc parameter. This cannot be done if OemToChar is being used as a wide-character function.
auch weiterhin, zumindest ab Delphi 2009.

Wenn ich das richtig verstehe ruft die Funktion OemToChar
bis Delphi 2007 -> OemToCharA
ab Delphi 2009 -> OemToCharW auf.
Ok, dann häng ich da gleich noch ein A dran...

himitsu 4. Jul 2014 17:01

AW: Stringkonvertierung
 
Eigentlich sollte OemToCharA ja OemCP_to_AnsiCP heißen, womit dann auch klarer wird, warum da keiner an Unicode gedacht hat.
Außerden ist OEM nunmal eine ANSI-CodePage und hat damit auch garnichts in einem UnicodeString zu suchen.
Also wenn, dann sollte man es doch besser richtig machen, also via MultiByteToWideChar von CP_OEMCP nach Unicode.

Und warum MS von dessen Verwendung abrät, liegt daran, daß viele es verwenden, um InSpace die einzelnen "SingleByte"-Zeichen der OEM-CP in die Ansi-CP umzuwandeln.
Da aber je nach Ansi-CP das eben auch mal eine MultyByte-CodePage sein kann und fast kein Schwein das beachtet, gibt es da ein Problem mit der Puffergröße und es endet zu oft in einem Buffer-Overflow.
z.B. Deutsch und Englisch sind ja SingleByte ... drum merken es viele Programmierer garnicht, daß sie totalen Mist verzapft haben.
So sind also auch alle hier gezeigten Lösungsvorschläge nicht unbedingt "sicher" oder zumindestens funktionieren nicht immer richtig (siehe #12). :angel:

Darum ist das Dateisystem nun eben auch immer englisch und wird lokalisiert, genausio wie das Systemlaufwerk auch fast immer nur noch C: ist, da zuviele Idioten mit hardgecodeten Pfaden arbeiten.

Sir Rufo 4. Jul 2014 18:09

AW: Stringkonvertierung
 
Ich würde das ja noch komplizierter machen :mrgreen:

Nein, ich bin faul:
Delphi-Quellcode:
function ReadDataNormFile( const ADataNormFilename : string ) : string;
var
  LText : TStrings;
begin
  LText := TStringList.Create;
  try
    LText.LoadFromFile( ADataNormFilename, {System.SysUtils} TEncoding.GetEncoding( {Winapi.Windows} CP_OEMCP ) );
    Result := LText.Text;
  finally
    LText.Free;
  end;
end;
Dieses ganze Oem/Ansi Hin-und-Her macht doch nur schwindelig im Kopf ;)

himitsu 4. Jul 2014 18:21

AW: Stringkonvertierung
 
Delphi-Quellcode:
type
  OemString = type AnsiString(CP_OEMCP);

var
  F: TextFile;
  S: OEMString;
begin
  ReadLn(F, S);
Delphi-Quellcode:
var
  F: TextFile;
  S: AnsiString;
begin
  ReadLn(F, S);
  SetCodePage(S, CP_OEMCP, False);
:angel:

himitsu 4. Jul 2014 18:30

AW: Stringkonvertierung
 
Zitat:

Zitat von Sir Rufo (Beitrag 1264489)
Nein, ich bin faul:

Delphi-Quellcode:
Result := TFile.ReadAllText(ADataNormFilename, TEncoding.GetEncoding(CP_OEMCP)); // Wobei man doch die TEncoding-Instanz eigentlich auch wieder greigeben müsste?

Du bist noch nicht faul genug. :lol:

Sir Rufo 4. Jul 2014 18:49

AW: Stringkonvertierung
 
Zitat:

Zitat von himitsu (Beitrag 1264493)
Zitat:

Zitat von Sir Rufo (Beitrag 1264489)
Nein, ich bin faul:

Delphi-Quellcode:
Result := TFile.ReadAllText(ADataNormFilename, TEncoding.GetEncoding(CP_OEMCP)); // Wobei man doch die TEncoding-Instanz eigentlich auch wieder greigeben müsste?

Du bist noch nicht faul genug. :lol:

Der TE hat XE2 und dem Kontext war es ausreichend faul

Huch, das kennt das ja doch schon :) ok

HPB 6. Jul 2014 10:03

AW: Stringkonvertierung
 
Guten Tag Delphianer,
vielen Dank an allen die bei der Lösung des Problems geholfen haben.
Letztendlich hab ich den Vorschlag von Uwe Raabe genommen:

Zitat:

Du kannst doch bei AssignFile als dritten Parameter die Codepage mitgeben.

Delphi-Quellcode:
AssignFile(fDatei, aDatei, 1);

Dies schien mir zum jetzigen Zeitpunkt die einfachste Lösung zu sein.
Jetzt kann ich auch weiter an die Erneuerung des Quellcodes gehen.
Das Thema kann nun geschlossen werden.
Mit besten Gruß
HPB


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:28 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