Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   AnsiString zu String zuweisen ohne Konvertierung? (https://www.delphipraxis.net/202776-ansistring-zu-string-zuweisen-ohne-konvertierung.html)

Rolf Frei 7. Dez 2019 11:25

Delphi-Version: 10.3 Rio

AnsiString zu String zuweisen ohne Konvertierung?
 
Wie kann ich in 10.3 Rio einen AnsiString einem String zuweisen, ohne dass der String über die Codepage konvertiert wird? Siehe folgendes Beispiel:

Delphi-Quellcode:
var
  a: AnsiString;
  s: String;
begin
  a := #$33#$95#$34;
  s := a;
end;
Nach der Zuweisung s := a hat s die Zeichenwerte #$0033 #$2022 #$0034. Ich müsste nun aber anstatt #$2022 den Wert #$0095 haben. Wie kann ich das bewerkstelligen, dass da bei der Zuweisung keine Codepagekonvertierung stattfindet? Auch die {$HIGHCHARUNICODE OFF} Direktive bringt keine Lösung.

scrat1979 7. Dez 2019 12:36

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Ich kann dir keine direkte Lösung sagen, aber die Suche auf Google Bei Google suchendelphi ansistring to string ergibt etliche Teffer. Vielleicht findest du da schnell eine Lösung :)

Rolf Frei 7. Dez 2019 12:56

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Habe schon Stunden lange gesucht und zu dem was ich hier suche finde ich nichts.

Das nächste Problem steht auch schon an: TIniFile/TMemeIniFile. Delphi liest hier nun Unicodestrings obwohl ein INI-File immer Ansi-Daten enthält. Nun habe ich da wieder das selbe Problem, dass ich da nun in Unicode umgewandelte Strings geliefert bekomme, die Zeichenwerte > 255 enhalten. Die Daten im INI sind aber als ANSI gespeichert und ich muss diese auch wieder in der selben Art lesen können, also nur mit Zeichewerten <=255. Ist im Prinzip genau ds selbe Problem, dass da beim Einlesen eine Konvertierung in Unicode passiert, was nicht sein darf! Ich brauche da die Ansi Strings so wie sie in Delphi 7 gespeichert wurden. Gibt es irgendwo ein Ansi kompatibles TIniFile?

hoika 7. Dez 2019 15:30

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Hallo,
schau mal hier, Stichwort Encoding
http://docs.embarcadero.com/products...TEncoding.html

TurboMagic 7. Dez 2019 15:47

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Eventl. statt AnsiString RawByteString benutzen, der "hat keine Codepage".

Grüße

TurboMagic

Rolf Frei 7. Dez 2019 15:49

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Das ist mir alles bekannt nützt mir hier nur nichts oder ich verstehe nicht wie man das richtig anwendet. Man müsste ja beim Unicodestring "s" sagen, dass er nichts umwandeln soll. Hast du mir eventuell ien Beispal anhandn meins Beispiels? Bei meinen Tests kam da nie das gewünschte heraus, wenn ich mit Tencoder herumgespielt habe.

Wenn ich "a" and "s" nicht direkt zuweise, sondern sowas hier mache..

Delphi-Quellcode:
 
  for i := 1 to Length(a) do
    s := s + Char(Ord(a[i]));
... bekomme ich das was ich will, aber das kann nicht der richtige Weg sein.

@TurboMagic
Das habe ich auch schon versucht macht aber keinen Unterschied. S hat danach immer den Unicodewert (2022) aus dem ANSI Zeichen 95 erhalten. Auch eine SetCodepage hat keinen Unterschied gemacht. Es müsste ja der Varibale S mitgetielt werden, das sie keine Uniccodekonvertierung machen soll. Das Encoding ist ja eher für das umgekehrte vom String in ein Ansi.

Dennis07 7. Dez 2019 18:20

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Mit
Delphi-Quellcode:
String
bzw.
Delphi-Quellcode:
UnicodeString
geht das so leider nicht, weil hier eine Konvertierung IMMER automatisch stattfindet (Deshalb sind
Delphi-Quellcode:
String
-Objekte auf der Linken Seite auch immer ReadOnly).
Das ist wegen der Referenzzählung notwendig, damit du keine Speicherlöcher bekommst. Allerdings gibt es hier ein paar möglichkeiten, das zu umgehen.
Der einfachste Weg wäre es, Statt
Delphi-Quellcode:
String
bzw.
Delphi-Quellcode:
UnicodeString
einen anderen Typ für die Zuweisung zu verwenden.
Ich würde einen Zeigertypen wie
Delphi-Quellcode:
PAnsiChar
oder alternativ
Delphi-Quellcode:
PByte
empfehlen.

Delphi-Quellcode:
var
  a: AnsiString;
  s: String;
begin
  a := #$95;
//  s := a;
  PAnsiChar(s) := PAnsiChar(a);
  ShowMessage((Ord(s[1]).ToHexString)); // Gibt $95 zurück
Allerdings bekommst du so für das zweite, dritte, vierte, ... Zeichen der Zeichenkette nur Salat heraus, da die Zeichen ja andere Bytegrößen haben. Das kannst du durch eine einfache Zuweisung nicht beheben, da du jedes Zeichen auf Unicode erweitern musst.

KLEINE ERGÄNZUNG: So könntest du es Implementieren, falls du die Werte Kopieren willst:
Delphi-Quellcode:
var
  a: AnsiString;
  s: String;
  pa: PAnsiChar;
  ps: PChar;
begin
  a := #$95#22;
  SetLength(s, length(a));
  pa := PAnsiChar(a);
  ps := PChar(s);
  while pa^ <> #0 do
  begin
    PAnsiChar(ps)^ := pa^;
    Inc(pa);
    Inc(ps);
  end;
  ShowMessage((Ord(s[2]).ToHexString)); // Gibt $16 zurück
end;

Uwe Raabe 7. Dez 2019 23:46

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Hast du schon mal daran gedacht, anstatt der Unicodestrings besser TBytes zu verwenden? Dann kann dir das Encoding nämlich völlig egal sein.

Wenn du deinen konkreten Anwendungsfall beschreiben könntest, und nicht nur das Symptom, dann könnte man vielleicht eine Lösung formulieren.

Dennis07 8. Dez 2019 01:37

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1452941)
Hast du schon mal daran gedacht, anstatt der Unicodestrings besser TBytes zu verwenden? Dann kann dir das Encoding nämlich völlig egal sein.

Ist ja quasi was ich geschrieben habe. Nur wirst du mit TBytes das selbe Problem haben wie mit PAnsiChar@UnicodeString, nämlich, dass du nicht richtig darauf zugreifen kannst, wenn du die Anpassung der Byte-Offsets nicht vornimmst. Es gibt sicher auch eine Funktion dafür, die mir allerdings zum jetzigen Zeitpunkt nicht bekannt ist.

Rolf Frei 8. Dez 2019 03:13

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
@Dennis07
Herzlichen Dank für deine Erklärung. Dann gibt es also keine Möglichkeit das ohne "Aufwand" zu lösen. Meine for-Schlauefe würde dann ja auch das mache was ich will und wäre viel einfacher, als dein Code. Vermutlich aber auch etwas langsamer. Das wäre hier aber keine Problem, da diese Routine nur sehr vereinzelt aufgerufen wird.

Ich mache nun sowas in der Art:
Delphi-Quellcode:
var
  a: AnsiString;
  s: String;
begin
  a := #$33#$95#$34;
  SetLength(s, Length(a));
  for i := 1 to Length(a) do
    s[i] := Char(Ord(a[i]));
end;
Damit kann ich leben und sollte für meine Zwecke auch schnell genug sein.

@Uwe Raabe
Ja an TBytes habe ich schon gedacht, aber das dann auch recht schnell wieder verworfen, das das sonst zu umständlich wäre, diese Funktion in der ich das so brauche, aufzurufen. Müsste ja dann von extern in ein TBytes umgewandelt werden. Ich möchte der Funktion aber ein String übergeben, damit das nicht bei jedem Aufruf der Funktion so umständlich wird.

Was mir aber immer noch Probleme macht, ist das TIniFile, das mir die ANSI Werte falsch liefert. Kann da zwar TMemIniFile mit Angabe einer Encoding verwenden, das hat aber meines erachtens zu viel Overhead, da damit immer das ganze File verabeitet wird. Wenn ich nur einen einzlnen Wert schreiben/lesen will, ist das nicht gerade optimal. Da müsste auch ein Read-/WriteAnsiString existieren um das Problem zu lösen. Dass es das nicht gibt empfinde ich schon als grober Fehler in der TIniFile Implementation, da es so nicht möglich ist einen sauberen AnsiString zu erhalten. Da beim Einlsenen der Werte diese in einen Unicodestring umgewandelt werden, werden diverse Zeichen in einen Wert > 255 umgewandelt und mit diesen kann ich nicht weiter arbeiten, da meine Routine verlangt, dass da nur 1-Byte Zeichen (Werte 0-255) kommen.

p80286 8. Dez 2019 07:22

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von Rolf Frei (Beitrag 1452948)
Da beim Einlsenen der Werte diese in einen Unicodestring umgewandelt werden, werden diverse Zeichen in einen Wert > 255 umgewandelt und mit diesen kann ich nicht weiter arbeiten, da meine Routine verlangt, dass da nur 1-Byte Zeichen (Werte 0-255) kommen.

Etwas anders formuliert:
TIniFile liefert nur 16Bit-Werte und Deine Routine kann nur 8Bit-Werte verarbeiten. Da bleibn letztlich zwei Möglichkeiten, schreib TIniFile neu oder deine Routine. Wobei ich Dir empfehle Deine Routine zu überarbeiten Da sie augenscheinlich mit binären werten arbeitet und mit Zeichen gefüttert wird. Das ist schon immer eine ungute Mischung gewesen.

Gruß
K-H

Gausi 8. Dez 2019 08:15

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Nun, da wird ja korrekt umgewandelt. In Windows-1252 ist das Zeichen #95 ein Punkt. In der Unicode-Nummerierung steht da jedoch ein nicht-druckbares Zeichen. Die 95 wird dann korrekt auf #2022 gemappt, siehe auch https://de.wikipedia.org/wiki/Windows-1252

Wenn du das nicht gebrauchen kannst, dann musst du konsequent mit AnsiStrings arbeiten, oder auf Byte-Ebene runter und von der Interpretation als "String" (d.h. die angezeigten Buchstaben und Zeichen). Oder du versucht es mit Codepages, wo die #95 eben dieses nicht-druckbare Zeichen ist. Aber was das für Nebenwirkungen bei der Anzeige und Delphi-internen Stringverarbeitung haben kann, weiß ich nicht ... :pale:

Sinnvoller wäre sicherlich die Verarbeitungsmethode anzupassen, wie p80286 auch schon schrieb.

Uwe Raabe 8. Dez 2019 09:47

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Ich vermisse immer noch eine Erklärung für die Anforderung, daß ein #95 eines AnsiStrings gerade nicht als #2022 eines UnicodeStrings wiedergegeben werden soll. Für mich sieht das so aus, als ob die die Strings (Ansi oder Unicode) nicht wirklich als Strings verwendest, sondern als Byte-Speicher.

himitsu 8. Dez 2019 17:14

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1452952)
Für mich sieht das so aus, als ob die die Strings (Ansi oder Unicode) nicht wirklich als Strings verwendest, sondern als Byte-Speicher.

Das (dafür sollte er mindestens gesteinigt werden) oder er hat im AnsiString eine andere Codierung und vergessen das dem AnsiString mitzuteilen.


Zitat:

255 umgewandelt und mit diesen kann ich nicht weiter arbeiten, da meine Routine verlangt, dass da nur 1-Byte Zeichen (Werte 0-255) kommen.
Und warum konvertierst du das dann nicht wieder zurück in einen AnsiString?

Nja, ansonsten bleibt dir nur noch die INI direkt auszulesen (als ANSI) und den Inhalt selbst zuparsen,
oder du könntest auch die ANSI-Version der INI-API benutzen (in Delphi ist seit 2009 nur noch die Unicode-API als Klasse implementiert (bis Delphi 2006/2007 die AnsiAPI).
GetPrivateProfileStringA (MSDN-Library durchsuchenGetPrivateProfileString)

PS: Delphi-Referenz durchsuchenRawByteString

himitsu 8. Dez 2019 17:18

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
[deleted] weil doppelpost

p80286 8. Dez 2019 22:10

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von himitsu (Beitrag 1452968)
Zitat:

Zitat von Uwe Raabe (Beitrag 1452952)
Für mich sieht das so aus, als ob die die Strings (Ansi oder Unicode) nicht wirklich als Strings verwendest, sondern als Byte-Speicher.

Das (dafür sollte er mindestens gesteinigt werden) ...

Steinigen halte ich für übertrieben. Er verwendet wohl eine Technik die viele Jahre lang (bis zur Einführung von 16Bit Zeichensätzen) gut funktioniert hat, Wenn er aus der C-Ecke kommt "Zum Speichern eines Zeichens (sowie von kleinen Zahlen) verwendet man in C üblicherweise den Datentyp Character, geschrieben als char." ist das auch verständlich.
Zitat:

Wenn du deinen konkreten Anwendungsfall beschreiben könntest, und nicht nur das Symptom, dann könnte man vielleicht eine Lösung formulieren
#8
Eigentlich ist dem nichts hinzu zu fügen.

Gruß
K-H

himitsu 9. Dez 2019 01:54

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Joar, was aber nicht bedeutet, das es jemals "richtig" war.
Tja, wenn er weiterhin AnsiString statt String/UnicodeString verwendet hätte, dann wäre es zwar immernoch nicht ganz richtig, aber naja.

PS: hier ist es nur #$95, aber es gibt noch massig andere Sprachen im Windows.
Ihr wollt nicht wissen was dann alles bei Russisch, Chinesisch usw. passiert.

Aber ByteArrays gibt es schon lange und wie gesagt Delphi-Referenz durchsuchenRawByteString, Delphi-Referenz durchsuchenSetCodePage usw.
Allergings ist RawByteString auch ein AnsiString, so wie der UTF8String, welcher mit Einführungen von NextGen leider am Aussterben ist.

Seit 2009 ist im AnsiString/UnicodeString neben neben Length und RefCount auch die Codepage und CharSize gespeichert, was man auch gut nutzen kann.

Rolf Frei 9. Dez 2019 12:21

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von himitsu (Beitrag 1452968)
Und warum konvertierst du das dann nicht wieder zurück in einen AnsiString?

Weil das nicht geht und ich dann ? Zeichen erhalte. Das $95 ist im Ansi ein Kontrollzeichen und wird bei der Umwandlung dann zu einem ?.

In D7 war das problemlos möglich ein Inifile mit beliebigen Zeichen zu füttern. In Rio muss ich diese Daten auch lesen können, da diese so exisitieren und ich diese verarbeiten muss. Es handelt sich dabei um verschlüsselte Daten die ich entschlüsseln muss und dafür kann ich keine verfälschten Daten brauchen. TIniFile soll doch bitte eine Möglichkeit bieten, dass ich gleich an die Daten rankomme wie bisher, also das ich Ansi Daten aus einem Ansi INI-File auch als solche erhalten kann. Da fehlt einen Funktion zum Lesen reiner Ansidaten ohene Konvertierung, da ein zurückwandelt in ein Ansi String dann ? enthalten könnte und somit die ganze Daten wertlos sind.

Rawbyte hilft mir hier nicht weiter, habe das schon alles x-fach getestet und es macht keinen Unterschied ob ich da RawByteString oder AnsiString nutze. Das TIniFile liefert einen Unicodesrting retour, obwohl das INI-File ein Ansi File ist und das ist schlicht falsch.

@Gausi
Wir reden hier von $95 (HEX) und nicht 95 Dezimal.


Hier mal ein Beispiel eines INI-File Werteintrages wie er aktuell besteht und den ich nun unter Rio verarbeiten muss:
Code:
Password2=«&#339;¨¥&#8249;&#8216;ÓÆÁý   

Beispiel ist so nicht richtig, da ich keine Unicodezeichen im Original habe! Die Forumsoftware hat das leider umgewandelt. Aber mein Problem dahinter versteht ihr vieleicht nun besser.

Klaus01 9. Dez 2019 12:39

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
.. seit Delphi 2009 ist der String ein Unicode String.
Somit gibt TiniFile.ReadString auch einen Unicode String zurück.

Könntest Du es nicht mit einem Class-Helper für TiniFile
die Methode ReadString:AnsiSring überschreiben?

Ein Beispiel für einen Helper mit TIniFile findest Du hier.
Sehe gerade das man mitHelper keine Methode überschreiben kann.
Du könntest eine eigene Methode einführen.

Oder TIniFile ableiten und ReadString überschreiben.


Grüße
Klaus

Bbommel 9. Dez 2019 12:56

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Hast du es mal mit TMemIniFile anstelle von TIniFile versucht? Hier kannst du eine Encoding mitgeben, die die Quelle haben soll. Zumindest beim Lesen der ini in die Stringlist wird diese Encoding dann auch beachtet. Müsstest du mal testen, ob dir das hilft - ich habe hier kein passendes Beispiel, um das auf die Schnelle herauszubekommen.

Uwe Raabe 9. Dez 2019 13:18

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von Rolf Frei (Beitrag 1453034)
Es handelt sich dabei um verschlüsselte Daten die ich entschlüsseln muss und dafür kann ich keine verfälschten Daten brauchen.

Also doch Byte-Sequenzen, die fälschlicherweise als Ansi-Char deklariert wurden. Du wirst mit Strings und TStringlist in dem Fall nicht glücklich werden (zumindest nicht bei Delphi-Versionen > D2007).

Rolf Frei 9. Dez 2019 13:26

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Schau dir bitte nochmals die letzte Nachricht an. Habe da noch Ergänzungen mit einem Beispiel gemacht.

Das sind nur Daten die so in einem INI File abgelegt sind und die ich beim Einlesen/Schreiben Ent/Verschlüssle. Als Resultat bekomme ich dann ganz normalen Text und nichts Binäres.

Und ja das würde ich heute nicht mehr so machen, aber das ist vor 20 Jahren so entstanden und hat nun gute 20 Jahre problemlos funktioniert. Werde auch im Zuge der Portierung des D7 Programms auf Rio diesen Teil überarbeiten und die Daten anders ablegen. Die bestehenden Daten muss ich aber dennoch verabreiten können.

Bbommel 9. Dez 2019 13:52

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Hallo Rolf,

ich habe mal ein kleines Testprogramm gebastelt und bekomme die Zeichen hier mit Hilfe eines RawByteString und mit TmemIniFile korrekt, wenn ich deine Anforderung richtig verstanden habe:

Delphi-Quellcode:
program readansiini;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  IniFiles;

var
  myIni: TMemIniFile;
  rawStr: RawByteString;
  uniStr: string;
  i: integer;

begin
  try
    { TODO -oUser -cConsole Main : Code hier einfügen }
    myIni:=TMemIniFile.Create('test.ini',TEncoding.ANSI);
    rawStr:=rawByteString(myIni.ReadString('test1','password',''));
    write('Raw: ');
    for I := 1 to Length(rawStr) do
      write(ord(rawStr[i]).ToString+' -- ');
    Writeln(rawStr);
    Write('Unicode: ');
    uniStr:=myIni.ReadString('test1','password','');
    for I := 1 to Length(uniStr) do
      write(ord(unistr[i]).ToString+' -- ');
    writeln(uniStr);
    readln;
    myIni.Free;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
In der Datei test.ini steht an der zweiten Stelle das von dir erwähnte Zeichen Hex 96 (also Dec 150). Im rawByateString bleibt es auch korrekt erhalten, im Unicode-String wird es, wie von dir beschrieben, umgewandelt. Die Ausgabe vom Programm ist hier also (wichtig ist die zweite Zahl):

Code:
Raw: 116 -- 150 -- 116 -- 252 -- 116 -- 228 -- t-tütä
Unicode: 116 -- 8211 -- 116 -- 252 -- 116 -- 228 -- t-tütä
Das heißt: damit müsstest du deine bisherigen Daten doch ohne for-Schleife und ähnliches lesen und konvertieren können?

TiGü 9. Dez 2019 14:12

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Verstehe nicht, warum du dir nicht einfach TIniFile rauskopierst und die Aufrufe entsprechend anpasst:
GetPrivateProfileString -> GetPrivateProfileStringA
WritePrivateProfileString -> WritePrivateProfileStringA
MarshaledString -> MarshaledAString

Das ist doch eine Sache von zwei Minuten.
Du programmierst mindestens seit dem Jahre 2006 in Delphi, das ist doch kein Hexenwerk?!?!

Rolf Frei 9. Dez 2019 14:30

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
@Bbommel
Danke für deine Bemühungen, aber das habe ich ja schon erwähnt, dass es mit einem TMemIniFile klappen würde. Das habe ich bereits in einem Post erwähnt und auch erklärt, wieso mir das nicht so recht gefällt. Dass da immer das ganze INI File geladen und geschrieben wird ist nicht ideal. Brauche es aber nun dennoch, weil so das Problem vorerst behoben ist.

@TiGü
Natürlich könnte ich das so machen, aber das wäre der absolut letzte Ausweg, wenn nichts anderes gehen würde. Ich kann das Problem mit einem TMemIniFile lösen, nur gefällt mir das eben nicht so gut, weil das das ganze File bearbeitet und nicht nur einen einzelnen Eintrag. Es hat also einen unnötig grossen Overhead.


Das Thema ist also hiermit für mich gelöst und somit abgeschlossen. Danke für all eure Tips und Ratschläge.

Bbommel 9. Dez 2019 14:32

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von Rolf Frei (Beitrag 1453049)
@Bbommel
Danke für deine Bemühungen, aber das habe ich ja schon erwähnt, dass es mit einem TMemIniFile klappen würde. Das habe ich bereits in einem Post erwähnt und auch erklärt, wieso mir das nicht so recht gefällt. Dass da immer das ganze INI File geladen und geschrieben wird ist nicht ideal. Brauche es aber nun dennoch, weil so das Problem vorerst behoben ist.

Ach, Mist, dann hatte ich genau den Post dazu übersehen. Sorry für den Hinweis auf etwas, was du schon wusstest. Aber wenigstens funktioniert es. :-)

Moombas 9. Dez 2019 14:39

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Mal eine komplett andere, vielleicht bekloppte Frage: Warum speicherst du die Ini-Datei nicht einfach im entsprechenden Format (von Delphi)?
Also:
- Original Datei öffnen
- Neue Datei erstellen (leer) und im richtigen Format speichern
- Inhalt der Original-Datei in die neue kopieren und abspeichern
- Original-Datei ersetzen

Dann müsste lesen/schreiben doch problemlos funktionieren!?
Zumindest hat mir das bei Lazarus den A**** gerettet, ohne das ich groß rum programmieren musste.

TiGü 9. Dez 2019 14:54

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Ähm...dir ist schon klar, was genau unter der Motorhaube passiert, wenn man mit dem TIniFile und damit mit den oben erwähnten Windows-Funktionen arbeitet?

Da wird die Datei auch immer komplett geöffnet (CreateFileW, CloseHandle) und zwar für JEDEN einzelnen String, den man sich per TIniFile.ReadString holt.
TMemIniFile ist in der Hinsicht sogar effizienter, weil man viel viel weniger mit dem Dateisystem hantiert.

Ein Blick in die Sourcen vom Wine-Projekt sind an der Stelle ganz erhellend:
https://github.com/ValveSoftware/win...rofile.c#L1088

Uwe Raabe 9. Dez 2019 15:24

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Also hier funktioniert das tadellos mit den Bytes und UnicodeStrings und AnsiStrings. Du darfst nur nicht mit den UnicodeStrings das encode/decode machen. Dafür nimmst du dann die Bytes.
Delphi-Quellcode:
var
  a: AnsiString;
  b: TBytes;
  s: String;
begin
  a := #$33#$95#$34;
  s := a;
  { Der Inhalt von s interessiert hier nicht. Zur Verarbeitung wandeln wir das in Bytes um. }
  b := TEncoding.ANSI.GetBytes(s);
  Assert(b[0] = $33);
  Assert(b[1] = $95);
  Assert(b[2] = $34);
  a := s;
  Assert(a = #$33#$95#$34);
end;
Ich habe jetzt gerade kein Beispiel mit TInifile, aber mit
Delphi-Quellcode:
LoadFromFile(<filename>, TEncoding.Ansi)
sollte das ebenso funktionieren.

himitsu 9. Dez 2019 16:20

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von Bbommel (Beitrag 1453040)
Hast du es mal mit TMemIniFile anstelle von TIniFile versucht?

Hier keine Lösung.

Bei TIniFile geht der Zugriff direkt auf die Datei, also ein zusätzliches ReadAnsiString wäre möglich.
Bei der TMemIniFile wurde bereits alles in Unicode umgewandelt und der Originale String ist nicht mehr vorhanden, wenn er sich nicht zurückumwandeln lässt.

Falls man bei TMemIniFile die Codepage/TEncoding beim Laden angeben kann, dann dort eine passende Codepage verwenden (z.B. siehe


Zitat:

Weil das nicht geht und ich dann ? Zeichen erhalte.
? ist das falsche Standard-Ersatzzeichen von Windows (das Unicode Consortium hat eigentlich was anderes definiert, aber egal).
Grundsätzlich sollten sich auch nahezu alle Zeichen auch verlustlos zurückkonvertieren lassen.
ANSI->Unicode->ANSI, vorausgesetzt auf beiden Seiten ist die selbe Codepage vorhanden (Codepage -> UCS2 bzw. UTF16 -> gleiche Codepage)


Wie gesagt, entweder sowas nicht machen, oder die Daten in der INI passend codieren.
Oder die Datei mit ANSI-APIs auslesen.

Rolf Frei 9. Dez 2019 16:51

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1453059)
Also hier funktioniert das tadellos mit den Bytes und UnicodeStrings und AnsiStrings. Du darfst nur nicht mit den UnicodeStrings das encode/decode machen. Dafür nimmst du dann die Bytes.
Delphi-Quellcode:
var
  a: AnsiString;
  b: TBytes;
  s: String;
begin
  a := #$33#$95#$34;
  s := a;
  { Der Inhalt von s interessiert hier nicht. Zur Verarbeitung wandeln wir das in Bytes um. }
  b := TEncoding.ANSI.GetBytes(s);
  Assert(b[0] = $33);
  Assert(b[1] = $95);
  Assert(b[2] = $34);
  a := s;
  Assert(a = #$33#$95#$34);
end;
Ich habe jetzt gerade kein Beispiel mit TInifile, aber mit
Delphi-Quellcode:
LoadFromFile(<filename>, TEncoding.Ansi)
sollte das ebenso funktionieren.

Beim TIniFile gibt es kein LoadFromFile. Lesen/Schreiben von INI-Files funktioniert nicht auf Filebasis wie eine TStringList. Da wird kein File geladen, da ist das OS dafür zuständig. Da ist auch der Unterschied zum TMemIniFile. Sobald ich im TIniFile eine Wert schreibe ist dieser im File enthalten. Beim TMemIniFile wird das File erst beim Free gespeichert. Das lädt immer das ganze File in den Speicher und schreibt auch wieder das ganze File auf den Disk.

So kann man mit dem TIniFile aus mehreren Progammen gleichzeitig Werte in das Inifile schreiben, ohne dass da was überschieben würde. Beim TMemIniFile steht jeweils nur das drin, was das zuletzt gespeicherte Progamm gespeichert hat. In einer Multiuser Umgebung ist das also sehr ungünstig.

TIniFile schreibt nur die Key/Werte Paare die man will und liest auch nur die, die man will.

Danke nochmals für die Tips.

PS. @TiGü
Dass das OS da das File jeweils öffnet und schliest ist ja logisch. Aber der Unterschied ist halt, dass TIniFile Multiuser/Multiappfähig ist und TMemIniFile nicht.

himitsu 9. Dez 2019 18:31

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von Rolf Frei (Beitrag 1453075)
Beim TIniFile gibt es kein LoadFromFile.

Beim TMemIniFile gibt es die StringList,
aber wie schon erwähnt gibt es die WinAPI für INIs als ANSI und Unicode, und da jeder API-Aufruf ein "eigenständiger" Zugriff ist, lassen sich die APIs mischen.

Moombas 10. Dez 2019 07:03

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Ich würde immer noch eher die IN-Datei im richtigen Format ablegen und gut ist. Kein Programmieraufwand (maximal für das Schreiben dieser, falls überhaupt notwendig).

freimatz 10. Dez 2019 07:17

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Vermutlich ist es nicht die INI, sondern je eine INI bei 1000 Anwendern ...

TiGü 10. Dez 2019 08:25

AW: AnsiString zu String zuweisen ohne Konvertierung?
 
Zitat:

Zitat von Rolf Frei (Beitrag 1453075)
PS. @TiGü
Dass das OS da das File jeweils öffnet und schliest ist ja logisch. Aber der Unterschied ist halt, dass TIniFile Multiuser/Multiappfähig ist und TMemIniFile nicht.

DAAAAS...ist übrigens eine ganz ganz andere Anforderung, als was du ursprünglich gefragt hattest.

Davon abgesehen:
Was ist das denn? Da schreiben X Benutzer parallel auf einer einzelnen Datei? Wirklich?
Das muss dir doch schon drölfzigmal um die Ohren geflogen sein.

Oder ist es so, wie freimatz vermutet, und jeder Windows-Benutzer hat eine eigene INI-Datei (die hoffentlich in seinem Benutzer spezifischen Ordner liegen)?


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