Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi UTF-8 nach ASCII (die 1000ste) (https://www.delphipraxis.net/191804-utf-8-nach-ascii-die-1000ste.html)

ernschd 21. Feb 2017 09:40

Delphi-Version: XE8

UTF-8 nach ASCII (die 1000ste)
 
Hallo,

ich bin immer noch mit der Portierung einer Software von Delphi 2007 nach XE8 beschäftigt. Jetzt habe ich Probleme mit der Kodierung.
In der Anwendung werden viele ASCII-Dateien geschrieben (mit write bzw. writeln).
Der Quellstring kommt aus einer Sqlite-Datenbank in UTF-8, welcher in Delphi 2007 mit Utf8ToAnsi und dann mit CharToOemBuff in die benötigte Kodierung umgewandelt wird. In XE8 wollte ich OemToCharA statt CharToOemBuff verwenden, was leider nicht funktioniert.
Hat jemand einen Hinweis, wie ich das Problem lösen könnte, ohne meine Anwendung komplett über den Haufen zu werfen?

Neutral General 21. Feb 2017 09:42

AW: UTF-8 nach ASCII (die 1000ste)
 
Übergibst du OemToCharA denn auch einen AnsiString und keinen String?

ernschd 21. Feb 2017 09:51

AW: UTF-8 nach ASCII (die 1000ste)
 
Delphi-Quellcode:
function OEM2Ascii(const OEMString: AnsiString): AnsiString;
begin
  Result := OEMString;
  if Result <> '' then
    OemToCharA(PAnsiChar(Result), PAnsiChar(Result));
end;

Neutral General 21. Feb 2017 10:01

AW: UTF-8 nach ASCII (die 1000ste)
 
Aufruf?

ernschd 21. Feb 2017 10:08

AW: UTF-8 nach ASCII (die 1000ste)
 
Delphi-Quellcode:
function GetFieldByName(const FieldName: string): String;
var s: String;
begin
    s := Utf8ToAnsi(GetFields(self.GetFieldIndex(FieldName)));
    if FIsAscii then s := OEM2Ascii(S);
    Result := s;
end;
Der Rückgabewert der Methode GetFields liefert einen String.

himitsu 21. Feb 2017 10:37

AW: UTF-8 nach ASCII (die 1000ste)
 
Zitat:

was leider nicht funktioniert.
Und das bedeutet?




Zitat:

Delphi-Quellcode:
function GetFieldByName(const FieldName: string): String;
var s: String;
begin
    s := Utf8ToAnsi(GetFields(self.GetFieldIndex(FieldName)));
    if FIsAscii then s := OEM2Ascii(S);
    Result := s;
end;

Utf8ToAnsi und dann in den String macht daraus wieder Unicode, aber nachdem Utf8ToAnsi für Informationsverlust gesorgt hat.
Delphi-Referenz durchsuchenUTF8ToString
Und dann wird das Unicode nach ANSI umgewandelt und an OEM2Ascii übergeben.

Was gibt GetFields für einen Typ zurück?

ernschd 21. Feb 2017 10:53

AW: UTF-8 nach ASCII (die 1000ste)
 
Bedeutet, dass ich BšCHER (ASCII) benötige, aber entweder BÜCHER (ANSI/Unicode) oder B_CHER bekomme.

GetFields liefert einen String.

mikhal 21. Feb 2017 10:53

AW: UTF-8 nach ASCII (die 1000ste)
 
Kannst du deine Texte nicht einer TStringList unterbringen, und mit TEncoding.ASCII als zusätzlichem Parameter abspeichern?

Grüße
Mikhal

ernschd 21. Feb 2017 11:03

AW: UTF-8 nach ASCII (die 1000ste)
 
Das wäre natürlich das einfachste, aber dafür müsste ich recht viele alte Units ändern, in denen direkt in eine Datei geschrieben wird, und der Aufwand dafür ist dann doch zu hoch.

p80286 21. Feb 2017 11:21

AW: UTF-8 nach ASCII (die 1000ste)
 
Zitat:

Zitat von ernschd (Beitrag 1362205)
Delphi-Quellcode:
function OEM2Ascii(const OEMString: AnsiString): AnsiString;
begin
  Result := OEMString;
  if Result <> '' then
    OemToCharA(PAnsiChar(Result), PAnsiChar(Result));
end;

Das ist kein OEM to ASCII !
Zugegeben es gibt in dem Bereich so viele eierlegende Wollmilchsäue, daß da der Überblick verloren gehen kann, aber ein wenig Genauigkeit könnte da nicht schaden.
(das ist eher ASCIItoANSI)

Gruß
K-H

ernschd 21. Feb 2017 11:30

AW: UTF-8 nach ASCII (die 1000ste)
 
Deswegen frage ich ja hier nach :wink:

himitsu 21. Feb 2017 11:53

AW: UTF-8 nach ASCII (die 1000ste)
 
Nochmal.
Wie ist GetFields deklariert?


Wenn du selber Decodieren willst, dann müssen auch die richtigen Typen verwendet werden, sonst führt Delphi implizit eine Convertierung durch und zerstört somit die Daten.
und wenn der Debugger einen UTF8String oder einen AnsiString mit UTF-8 drin findet (StringToUTF8 setzt im AnsiString die CodePage richtig auf CP_UTF8), dann wird das im Debugger decodiert und als Unicode angezeigt.

ernschd 21. Feb 2017 11:57

AW: UTF-8 nach ASCII (die 1000ste)
 
Delphi-Quellcode:
function GetFields(I: cardinal): string;
Habe es ebenfalls versucht mit:
Delphi-Quellcode:
function GetFields(I: cardinal): AnsiString;

ernschd 21. Feb 2017 15:24

AW: UTF-8 nach ASCII (die 1000ste)
 
Kann mir denn sonst jemand einen Tipp geben, wie ich OEM2Ascii umsetzen kann?

freimatz 21. Feb 2017 15:45

AW: UTF-8 nach ASCII (die 1000ste)
 
Was denn nun? OEM2Ascii oder UTF-8 nach ASCII.
Und wie willst Du das Wort "Bücher" denn in ASCII haben?

ernschd 21. Feb 2017 16:18

AW: UTF-8 nach ASCII (die 1000ste)
 
UTF-8 nach ASCII, (BÜCHER -> BšCHER).

p80286 21. Feb 2017 16:23

AW: UTF-8 nach ASCII (die 1000ste)
 
Zitat:

Zitat von freimatz (Beitrag 1362252)
Was denn nun? OEM2Ascii oder UTF-8 nach ASCII.
Und wie willst Du das Wort "Bücher" denn in ASCII haben?

Wenn ich das richtig verstanden habe, dann hat er Daten die UTF-8 kodiert sind, und die will er in Dateien schreiben die OEM(ASCII) codiert sind. (sein sollen)
Letztlich benötigt er so etwas
Delphi-Quellcode:
OEMstring:=(UTF8toOEM(UTF8String);
bzw.
OEMString:=ANSItoOEM(UTF8toAnsi(UTF8String));
Da der Zeichenumpfang von UTF8 wesentlich größer ist als der von Ansi/OEM/ASCII, zusätzlich gibt es natürlich noch unterschiedliche Codepages für ANSI/ASCII/OEM, ist das erst einmal eine ganz heiße Nummer.
Da sollte/muß man im Vorfeld definieren was von dem was vorne hinein geht, auch hinten wieder heraus darf.

Gruß
K-H

xC3BC (UTF8) -> xFC (Ansi) -> x81(IBM ASCII)
ich vermute, das ist was Du willst.

freimatz 21. Feb 2017 16:32

AW: UTF-8 nach ASCII (die 1000ste)
 
Also ANSI/ASCII/OEM sind schon mal drei Paar Stiefel. Und was "š" sein soll ist mir noch unklar. Wenn ich es in Ultraedit kopiere zeigt das Hex den Wert #$9A an. Das ist aber kein ASCII.

ANSI: https://de.wikipedia.org/wiki/Americ...ards_Institute
ASCII: https://de.wikipedia.org/wiki/Americ...on_Interchange
OEM: https://de.wikipedia.org/wiki/Codepage_437

nahpets 21. Feb 2017 16:54

AW: UTF-8 nach ASCII (die 1000ste)
 
Verstehe ich das richtig?

Du hast aus 'ner SQLite-Datenbank UTF8.

Ausgeben möchtest Du per WriteLn ... OEM: https://de.wikipedia.org/wiki/Codepage_437

Also den unter DOS üblichen Zeichensatz?

Das wäre dann sowas in der Art:
Delphi-Quellcode:
function Ansi2OEM(AnsiString: string): string;
begin
  ANSIString := ANSIString + #0;
  CharToOEM(PChar(ANSIString), @ANSIString[1]);
  Delete(ANSIString, Length(ANSIString), 1);
  Result := ANSIString;
end;

function GetFieldByName(const FieldName: string): String;
var s: String;
begin
  s := Utf8ToAnsi(GetFields(self.GetFieldIndex(FieldName)));
  if FIsAscii then s := Ansi2OEM(s);
  Result := s;
end;
CharToOEM war zu Delphi 7-Zeiten in der Unit Windows zu finden.

ASCII https://de.wikipedia.org/wiki/Americ...on_Interchange ist aber (wie freimatz schon schrieb) <> OEM: https://de.wikipedia.org/wiki/Americ...on_Interchange

Da bei mehreren Post wiederholt Fragen auftraten, was genau das Ziel ist, beschreibe bitte noch einmal genau, von welchen Ausgangsdaten Du zu welchen Zieldaten gelangen möchtest.

Was ist genau das Quellsystem und was ist das Zielsystem? (Damit wir eine Vorstellung davon bekommen können, welche Ausgabe genau erforderlich ist.)

Was ergibt die Ausgabe von
Delphi-Quellcode:
Ord('š')
?
154 bzw. hexadezimal 9A? Das wäre dann aber in der Codepage 437 das große Ü. Das kleine ü wäre 129 bzw. hexadezimal 81.

Man müsste dann mal schauen, welcher Zeichensatz an der entsprechenden Stelle das kleine ü enthält.

HolgerX 21. Feb 2017 18:17

AW: UTF-8 nach ASCII (die 1000ste)
 
Hmm..

Irgendwo in den alten Sourcen gefunden:

Delphi-Quellcode:
function ANSI2ASCII(AText : AnsiString) : AnsiString;
var
  PText : PAnsiChar;
begin
  PText:=StrAlloc(length(AText)+1);
  StrPCopy(PText,AText);
  CharToOEMA(PText,PText);
  Result:=StrPas(PText);
  StrDispose(PText);
end;

jfheins 21. Feb 2017 20:33

AW: UTF-8 nach ASCII (die 1000ste)
 
Wäre es nicht eigentlich sinnvoll, wenn ein Encoding einen String entgegennimmt und ein byte-Array zurück gibt?
Wenn da wieder ein String rauskommt, ist das doch eigentlich wieder Interpretationssache, was da drin steht.

Also string + Zeichnsatz = Bytes
Und Bytes + Zeichensatz = String

p80286 21. Feb 2017 22:32

AW: UTF-8 nach ASCII (die 1000ste)
 
Zitat:

Zitat von jfheins (Beitrag 1362280)
Wäre es nicht eigentlich sinnvoll, wenn ein Encoding einen String entgegennimmt und ein byte-Array zurück gibt?
Wenn da wieder ein String rauskommt, ist das doch eigentlich wieder Interpretationssache, was da drin steht.

:thumb:

Es kommt darauf an welche Codierung die gewählte Schrift unterstützt.

Gruß
K-H

ernschd 22. Feb 2017 08:24

AW: UTF-8 nach ASCII (die 1000ste)
 
Um die ganzen Verwirrungen (hoffentlich) ein wenig aufzudecken:

Ich habe einen UTF-8 kodierten String, als Beispiel "BÜCHER". Dieser muss in einen DOS-Zeichensatz umgewandelt werden, damit ich für das große "Ü" in Codepage 437 das Hex Zeichen 9A bzw. (extendet) ASCII-Zeichen 154 bekomme.
Wenn man dieses in einem Editor als ANSI anzeigt, wird es als "š" dargestellt, in UTF-8 als "x9A".

Sherlock 22. Feb 2017 08:58

AW: UTF-8 nach ASCII (die 1000ste)
 
Als ich das letzte mal nachgesehen hatte (vor 1 Minute) war das große Ü ASCII 220 bzw xDC... auch in der Codepage 437.
In UTF-8 ist das U+00DC oder eben c39c.
Kurz: Keine Deiner Zahlen entspricht in den benannten Codetabellen dem Ü.

Da läuft etwas konzeptionell falsch.

Sherlock

ernschd 22. Feb 2017 09:16

AW: UTF-8 nach ASCII (die 1000ste)
 
Ich habe in der verlinkten Tabelle nachgesehen: https://de.wikipedia.org/wiki/Codepage_437, dort ist es 154 bzw. 9A. Laut der Beschreibung ist 00DC der Unicode-Wert.

Sherlock 22. Feb 2017 09:31

AW: UTF-8 nach ASCII (die 1000ste)
 
d'uh... hab die Tabelle falsch gelesen :stupid:

Ich habe auch mal UTF8 nach ASCII konvertieren müssen, bei mir sahen die Strings aber so aus: 'Gl\xC7\, cknerin' -> 'Glöcknerin' Das kann man dann mit Delphi-Referenz durchsuchenTJSONOBject.ParseJSONValue verwurschteln...hilft Dir jetzt aber nicht.

:gruebel:

Sherlock

p80286 22. Feb 2017 10:39

AW: UTF-8 nach ASCII (die 1000ste)
 
Zitat:

Zitat von ernschd (Beitrag 1362306)
Ich habe in der verlinkten Tabelle nachgesehen: https://de.wikipedia.org/wiki/Codepage_437, dort ist es 154 bzw. 9A. Laut der Beschreibung ist 00DC der Unicode-Wert.

Um Mißverständnissen vorzubeugen, wichtig ist, was in der Datei steht, wenn es korrekt ist.

Gruß
K-H

ernschd 22. Feb 2017 10:46

AW: UTF-8 nach ASCII (die 1000ste)
 
Das habe ich in diesem Post bereits geschrieben.

Fritzew 22. Feb 2017 10:48

AW: UTF-8 nach ASCII (die 1000ste)
 
Delphi liefert doch alles mit:

Declariere einen Stringtyp für die gewünschte Codepage:

Delphi-Quellcode:

 type
    oemString = type Ansistring(437) ;

   function StringtoOem(const Value : string) : oemString;
 begin
     result := Value;
 end;
einfach zugewiesen und glücklich sein.

Ergebnis :

OEM
Decimal
66 154 67 72 69 82

HEX
$42 $9A $43 $48 $45 $52

ANSI
Decimal
66 220 67 72 69 82

HEX
$42 $DC $43 $48 $45 $52

ernschd 22. Feb 2017 11:15

AW: UTF-8 nach ASCII (die 1000ste)
 
Wenn ich das ganze mit einem kleinen Testprogramm versuche, bekomme ich leider ein anderes Ergebnis (Hexadezimal DC statt 9A):

Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses System.SysUtils;

type oemString = type Ansistring(437) ;

var f: TextFile;
  ein: string;
  aus: oemString;

function StringtoOem(const Value : string) : oemString;
begin
    result := Value;
end;

begin
  AssignFile(f, 'c:\temp\kodier.txt');
  Rewrite(f);
  ein := 'Ü';
  aus := StringtoOem(ein);
  writeln(f, aus);
  CloseFile(f);
end.

p80286 22. Feb 2017 11:25

AW: UTF-8 nach ASCII (die 1000ste)
 
Delphi-Quellcode:
var
  tt : Array [0..255] of Byte;

for i:=0 to 255 do
  tt:=i;

{-- from xDC -> x9A --}
tt[$DC]:=$9A;

procedure Translate(var instr:ansistring);
begin
  for i:=1 to length(instr) do
    instr[i]:=ansichar(tt[byte(instr[i])]);
end;
So sollte es funktionieren und Du bist Herr des Verfahrens
(ich hoffe die Klammern stimmen)
(ich würde noch diese Char/Byte - Konvertierung weglassen und das gleich als Array of Byte behandeln)

Gruß
K-H

Fritzew 22. Feb 2017 11:36

AW: UTF-8 nach ASCII (die 1000ste)
 
Tja für das File musst Du natürlich noch festlegen was rausgeht:
Zitat:

Zitat von ernschd (Beitrag 1362324)
Wenn ich das ganze mit einem kleinen Testprogramm versuche, bekomme ich leider ein anderes Ergebnis (Hexadezimal DC statt 9A):

Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses System.SysUtils;

type oemString = type Ansistring(437) ;

var f: TextFile;
  ein: string;
  aus: oemString;

function StringtoOem(const Value : string) : oemString;
begin
    result := Value;
end;

begin
  AssignFile(f, 'c:\temp\kodier.txt');
(*   Festlegen der Codepage für das File.........  *)
  SetTextCodePage(f, 437);

  Rewrite(f);
  ein := 'Ü';
  aus := StringtoOem(ein);
  writeln(f, aus);
  CloseFile(f);
end.


Fritzew 22. Feb 2017 11:53

AW: UTF-8 nach ASCII (die 1000ste)
 
Habe gerade noch geschaut wie das in der System.pas tatsächlich gehandelt wird.

Wenn es Dir nur darum geht in ein Textfile mit Write und Writeln zu schreiben reicht es aus bei der Erzeugung des Files
die richtige codepage zu setzen.
Also

Delphi-Quellcode:
procedure StringtoFileTest(const Value : string) ;
 Var f : TextFile;
 begin
   AssignFile(f, 'D:\Test\test.txt');
   SetTextCodePage(f, 437);
   rewrite(f);
   writeln(f, StringtoOem(Value));
   writeln(f, Value);
   closefile(f);
 end;

StringtoFileTest('Bücher');
ergibt im erzeugten File:


Zitat:

BšCHER
BšCHER
Write und Writeln überprüfen die CodePage des Files und wandeln wenn notwendig um.

ernschd 22. Feb 2017 12:11

AW: UTF-8 nach ASCII (die 1000ste)
 
Perfekt! Jetzt habe ich gleich zwei funktionierende Methoden für die Umwandlung! :-D

Vielen Dank an alle!

Ydobon 22. Feb 2017 12:47

AW: UTF-8 nach ASCII (die 1000ste)
 
zu spät


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