![]() |
Console: OEM nach ANSI
Hey,
ich lese die Ausgabe einer Konsolenanwendung mit Pipes aus und sende ebenso Eingaben an das Programm. Jetzt muss ich die ausgelesenen Daten von OEM nach ANSI konvertieren, damit Umlaute wie öäüß richtig dargestellt werden können. Momentan versuche ich das folgendermaßen:
Delphi-Quellcode:
Leider hat die Funktion, wie es scheint, einfach komplett keine Wirkung auf meinen ausgelesenen AnsiString. :x
function OEM2Ansi(OEMString: AnsiString): AnsiString;
begin OEMString := OEMString + #0; OemToChar(PAnsiChar(OEMString), @OEMString[1]); Delete(OEMString, Length(OEMString), 1); Result := OEMString; end; Das hier ist zum Beispiel einer der Problemkandidaten: Zitat:
Kennt jemand eine Lösung für dieses Problem? Viele Grüße Zacherl |
AW: Console: OEM nach ANSI
Unter Delphi 2007 funktioniert das hier:
Delphi-Quellcode:
function OEM2ANSI(const aStr: AnsiString): AnsiString;
begin Result := aStr; OEMToChar(PAnsiChar(Result),PAnsiChar(Result)); end; |
AW: Console: OEM nach ANSI
Leider ebenfalls kein Effekt. Ich verstehe das nicht. Ich lese die Daten von der Pipe direkt in einen AnsiString aus. Da sollte es ja auch keine Probleme durch das Unicode Delphi geben.
|
AW: Console: OEM nach ANSI
Wie ließt du denn die Daten genau aus? (also kompletter Code)
Seit Delphi 2009 wird blöder Weise oftmals im String direkt die CodePage gespeichert, welches Probleme bereiten kann, wenn man selber die CodePage ändert und dieses nicht anpaßt. z.B. dieses reagiert seit D2009 nicht mehr so wie ich es mir denke (es wird kein UTF-8-kodierter Text angezeigt :wall: )
Delphi-Quellcode:
var
A: AnsiString; S: String; A := UTF8Encode('äöü'); S := A; ShowMessage(S); |
AW: Console: OEM nach ANSI
Delphi-Quellcode:
Wie man sieht landen die Daten direkt in einem ByteArray. Wenn ich die Daten an OEM2ANSI übergebe, wird das Teil halt zwangsweise kurzzeitig in einen AnsiString konvertiert.
function ShellReadThread(lpParam: Pointer): Cardinal;
var ExitCode: Cardinal; BytesRead: DWord; Buffer: array[0..1024 * 8 - 1] of AnsiChar; begin while (not Terminated) do begin GetExitCodeProcess(FProcessInfo.hProcess, ExitCode); if (ExitCode <> STILL_ACTIVE) then begin Terminate; Break; end; if (ReadFile(hoRead, Buffer[0], Length(Buffer), BytesRead, nil)) and (BytesRead > 0) then begin SendPriorityCommand(ParentThread.IDTPWriter, CMDS_SHELLOUTPUT, @Buffer[0], BytesRead, true); end; Sleep(50); end; Result := 0; end; |
AW: Console: OEM nach ANSI
Okay fail :| Ich hatte das ByteArray zu Testzwecken in ein array of AnsiChar geändert. Daran lags wohl, auch wenn ich nicht verstehe warum. Allerdings gibt es nun ein weiteres Problem:
Delphi-Quellcode:
Die Umlaute werden nun korrekt umgewandelt, aber als "netter" Nebeneffekt werden alle enthaltenen Zeilenumbrüche (#13#10) in irgendeinen Quatsch konvertiert :wall:
function OEM2Ansi(Value: AnsiString): String;
begin Result := Value; OEMToChar(PAnsiChar(Value), PChar(Result)); end; Zitat:
|
AW: Console: OEM nach ANSI
Also ich habe das so gelöst...
Delphi-Quellcode:
Und ab Delphi2009...
function Oem2Ansi(AText:AnsiString):AnsiString;
const cMaxLength = 255; var PText : PAnsiChar; begin Result:=''; PText:=AnsiStrAlloc(cMaxLength); while AText <> '' do begin StrPCopy(PText, copy(AText, 1, cMaxLength-1)); OemToAnsi(PText, PText); Result:=Result + StrPas(PText); delete(AText, 1, cMaxLength-1); end; StrDispose(PText); end;
Delphi-Quellcode:
function Convert(Data:AnsiString):string;
begin Data:=Oem2Ansi(Data); {$WARNINGS OFF} Result:=AnsiToUtf8(Data); {$WARNINGS ON} end; |
AW: Console: OEM nach ANSI
Du könntest statt dem CharToOem einfach mal SetFileApisToOEM versuchen.
> ![]() ![]() ![]() Meckert dein Delphi 2009+ eigentlich nicht über den Ansi-Unicode-Mischmasch? Für AnsiString mußt du OemToCharA verwenden.
Delphi-Quellcode:
oder mal so versuchen:
function OEM2Ansi(const OEMString: AnsiString): AnsiString;
begin Result := OEMString; if Result <> '' then OemToCharA(PAnsiChar(Result), PAnsiChar(Result)); end;
Delphi-Quellcode:
function OEM2Ansi(const OEMString: AnsiString): AnsiString;
begin Result := OEMString; if Result = '' then Exit; OemToCharA(PAnsiChar(Result), PAnsiChar(Result)); PWord(Integer(Result) - 12)^ := 0; end; PS
Delphi-Quellcode:
type
PStrRec = ^StrRec; StrRec = packed record codePage: Word; elemSize: Word; refCnt: Longint; length: Longint; end; OEMString = type AnsiString(CP_OEMCP); procedure TForm5.FormCreate(Sender: TObject); var A: AnsiString; begin A := UTF8Encode('äöü'); ShowMessage(A); {$IF CompilerVersion >= 20.0} if A <> '' then PStrRec(Integer(A) - SizeOf(StrRec)).codePage := CP_NONE; ShowMessage(A); {$IFEND} A := 'äöü'; UniqueString(A); // Konstante in Variable umwandeln CharToOemA(PAnsiChar(A), PAnsiChar(A)); {$IF CompilerVersion >= 20.0} //if A <> '' then PStrRec(Integer(A) - SizeOf(StrRec)).codePage := CP_NONE; ShowMessage(A); if A <> '' then PStrRec(Integer(A) - SizeOf(StrRec)).codePage := CP_OEMCP; {$IFEND} ShowMessage(A); end;
Delphi-Quellcode:
var S: AnsiString;
SetString(S, P, BytesRead); // von PAnsiChar //SetString(S, @Buf[0], BytesRead); // von AnsiChar-Array if S <> '' then PWord(Integer(S) - 12)^ := CP_OEMCP; // und schon wandelt Delphi automatisch die Codepage um ShowMessage(A);
Delphi-Quellcode:
und schon wandelt Delphi automatisch die Codepage um, wenn dieser AnsiString z.B. an einen String/UnicodeString übergeben wird.
var S: AnsiString;
SetString(S, P, BytesRead); // von PAnsiChar //SetString(S, @Buf[0], BytesRead); // von AnsiChar-Array if S <> '' then PWord(Integer(S) - 12)^ := CP_OEMCP; ShowMessage(A); (also ab Delphi 2009) |
AW: Console: OEM nach ANSI
Argh in der ganzen Hektik habe ich tatsächlich nicht bemerkt, dass ich die Unicode Funktion aufgerufen habe. Der Compiler hat lustigerweise auch nicht gemeckert :mrgreen: Jetzt klappt aber alles. Vielen Dank :thumb:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:58 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