Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi tReader-Objekt unter 10.4.1 (https://www.delphipraxis.net/205682-treader-objekt-unter-10-4-1-a.html)

michaelg 5. Okt 2020 16:27

tReader-Objekt unter 10.4.1
 
Moin zusammen,

ich habe bei der Umstellung von 10.3.3 auf 10.4.1 ein Problem mit Umlauten erkannt. Es geht um das Einlesen eines Streams mit Benutzung von tReader. In System.Classes.pas steht in der 10.3.3 für den Typ "vaString" folgendes:

Code:
   
    vaString:
      begin
        Read(L, SizeOf(Byte));
        SetLength(LResult, L);
        Read(LResult, L);
        Result := TEncoding.Default.GetString(LResult);
      end;
In 10.4.1 steht folgendes für diesen Typ:

Code:
   vaString:
      begin
        Read(S[0], SizeOf(Byte));
        Read(S[1], NativeInt(S[0]));
        Result := UTF8IdentToString(@S);
      end;
Die Variable "S" ist dort als ShortString definiert und ein Umlaut wie "ä" (hex E4) kommt so nicht mehr korrekt an. Die Dateien behaupten, sie wären als ANSI gespeichert. Und ReadValue gibt für die Strings "vaString" an.

Ich möchte nicht in der System.Classes rumrühren, gibts einen Workaround oder irgendeine globale Definition, die das korrigiert? Ich meine jetzt nicht den String Byte für Byte durchgehen und die Umlaute hartcodiert umzustellen auf einen anderen Wert.

Weiß jemand, warum das umgestellt wurde?

Grüße
Michael

himitsu 5. Okt 2020 17:11

AW: tReader-Objekt unter 10.4.1
 
Da hat wohl jemand Mist gebaut und nicht bedacht, dass diese Streams auch von anderen benutzt werden können. (wie z.B. von dir oder uns ... zum Glück bin ich noch nicht so weit, mit der Umstellung auf 10.4)

Auch bei "älteren" DFMs, welche noch binär gespeichert sind oder noch nicht umgestellt wurden (nicht als Text-DFM), wird es somit Probleme geben.
In der EXE-Ressource sind die zwar binär hinterlegt, aber da dort mit der selben TReader/TWriter-Verion gelesen wird, wie der Compiler es abspeicherte, ist das wohl noch niemandem ausgefallen.


Da kannst du nur an den Hersteller wenden, dass die das gefälligst beheben.
Bisher, und das muß eigentlich auch so bleiben, war vaString ein ShortString mit ANSI.

Per se ist es gut das ANSI aus DFMs (diesen Streams) zu verbannen, denn in einem deutschen Windows kompiliert und in einem anderem Windows gestartet, z.B. in französisch/englisch/russisch/chinesisch/..., da hatte man schon immer Spaß.
Aber das darf nicht das Lesen "alter" Streams beeinflussen.
Beim neu Speichern darf in vaString einfach nur ausschließlich ASCII [#0..#127] rein und der Rest muß in vaUTF8String. Und vaString ist und bleibt ANSI, beim Lesen.



Wobei ich mir fast sicher bin, dass ich unsere Streams nur als Text speichere und somit hoffentlich vielleicht keine Probleme bekomme,
falls ich auch beim FastReport da nichts übersehn hab.

TurboMagic 5. Okt 2020 19:22

AW: tReader-Objekt unter 10.4.1
 
Ist dieser Fehler schon in QP erfasst? Falls nicht bitte zügig tun und die Report Nummer hier melden.

michaelg 5. Okt 2020 21:08

AW: tReader-Objekt unter 10.4.1
 
Habe es gemeldet unter RSP-31215:

https://quality.embarcadero.com/browse/RSP-31215

michaelg 8. Okt 2020 11:35

AW: tReader-Objekt unter 10.4.1
 
Da ich nicht warten wollte, bis Embarcardero soweit ist, habe ich einen kleinen Workaround gebaut. Ich benutze dann nicht tReader, sondern tMGReader zum Auslesen der Stringvalues.

Vielleicht kann es ja übergangsweise noch jemand gebrauchen.


Code:
//**********************************************************************************************
// MGReader.pas
//
// Unit für den Workaround des bei Embacadero gemeldeten Fehlers RSP-31215
// Mit dem tMGReader werden die Umlaute wieder korrekt gelesen
//
// Link zum Fehler: https://quality.embarcadero.com/browse/RSP-31215
//
// Autor: Michael Groß
// Stand: 08.10.2020
//
//***************************************************************************************

unit MGReader;

interface

uses
  System.Classes, System.SysUtils, System.RTLConsts;

type
  tMGReader=class(tReader)
    private
    public
      function ReadString:String; reintroduce;
  end;

implementation

procedure ReadError(Ident: PResStringRec); overload;
  begin
    raise EReadError.CreateRes(Ident) at ReturnAddress;
  end;

procedure PropValueError;
  begin
    ReadError(@SInvalidPropertyValue);
  end;

function TMGReader.ReadString:String;
  var
    L: Integer;
    LResult: TBytes;
  //  S: ShortString;
  begin
    L := 0;
    case ReadValue of
      vaWString:
        begin
          Read(L, SizeOf(Integer));
          SetLength(LResult, L*sizeof(WideChar));
          Read(LResult, L*sizeof(WideChar));
          Result := TEncoding.Unicode.GetString(LResult);
        end;
      vaUTF8String:
        begin
          Read(L, SizeOf(Integer));
          SetLength(LResult, L);
          Read(LResult, L);
          Result := TEncoding.UTF8.GetString(LResult);
        end;
      (*
      das war Original bei 10.4.1
      vaString:
        begin
          Read(S[0], SizeOf(Byte));
          Read(S[1], NativeInt(S[0]));
          Result := UTF8IdentToString(@S);
        end;
      *)
      vaString: //übernommen aus 10.3.3, damit funktionieren die Umlaute wieder
        begin
          Read(L, SizeOf(Byte));
          SetLength(LResult, L);
          Read(LResult, L);
          Result := TEncoding.Default.GetString(LResult);
        end;
      vaLString:
        begin
          Read(L, SizeOf(Integer));
          SetLength(LResult, L);
          Read(LResult, L);
          Result := TEncoding.Default.GetString(LResult);
        end;
      else
        PropValueError;
    end;
  end;

end.

michaelg 25. Feb 2021 19:39

AW: tReader-Objekt unter 10.4.1
 
Kurzes Update:

Der Bug ist als gefixed gemeldet in 10.4.2 .


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