![]() |
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:
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.
var
a: AnsiString; s: String; begin a := #$33#$95#$34; s := a; end; |
AW: AnsiString zu String zuweisen ohne Konvertierung?
Ich kann dir keine direkte Lösung sagen, aber die Suche auf Google
![]() |
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? |
AW: AnsiString zu String zuweisen ohne Konvertierung?
|
AW: AnsiString zu String zuweisen ohne Konvertierung?
Eventl. statt AnsiString RawByteString benutzen, der "hat keine Codepage".
Grüße TurboMagic |
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:
... bekomme ich das was ich will, aber das kann nicht der richtige Weg sein.for i := 1 to Length(a) do s := s + Char(Ord(a[i])); @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. |
AW: AnsiString zu String zuweisen ohne Konvertierung?
Mit
Delphi-Quellcode:
bzw.
String
Delphi-Quellcode:
geht das so leider nicht, weil hier eine Konvertierung IMMER automatisch stattfindet (Deshalb sind
UnicodeString
Delphi-Quellcode:
-Objekte auf der Linken Seite auch immer ReadOnly).
String
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:
bzw.
String
Delphi-Quellcode:
einen anderen Typ für die Zuweisung zu verwenden.
UnicodeString
Ich würde einen Zeigertypen wie
Delphi-Quellcode:
oder alternativ
PAnsiChar
Delphi-Quellcode:
empfehlen.
PByte
Delphi-Quellcode:
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.
var
a: AnsiString; s: String; begin a := #$95; // s := a; PAnsiChar(s) := PAnsiChar(a); ShowMessage((Ord(s[1]).ToHexString)); // Gibt $95 zurück 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; |
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. |
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
|
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:
Damit kann ich leben und sollte für meine Zwecke auch schnell genug sein.
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; @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. |
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
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 |
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
![]() 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. |
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.
|
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
Zitat:
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 ( ![]() PS: ![]() |
AW: AnsiString zu String zuweisen ohne Konvertierung?
[deleted] weil doppelpost
|
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
Zitat:
Eigentlich ist dem nichts hinzu zu fügen. Gruß K-H |
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 ![]() ![]() 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. |
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
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=«œ¨¥‹‘ÓÆÁý
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. |
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 ![]() 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 |
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.
|
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
|
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. |
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:
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):
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.
Code:
Das heißt: damit müsstest du deine bisherigen Daten doch ohne for-Schleife und ähnliches lesen und konvertieren können?
Raw: 116 -- 150 -- 116 -- 252 -- 116 -- 228 -- t-tütä
Unicode: 116 -- 8211 -- 116 -- 252 -- 116 -- 228 -- t-tütä |
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?!?! |
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. |
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
|
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. |
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: ![]() |
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:
Ich habe jetzt gerade kein Beispiel mit TInifile, aber mit
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;
Delphi-Quellcode:
sollte das ebenso funktionieren.
LoadFromFile(<filename>, TEncoding.Ansi)
|
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
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:
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. |
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
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. |
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
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. |
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).
|
AW: AnsiString zu String zuweisen ohne Konvertierung?
Vermutlich ist es nicht die INI, sondern je eine INI bei 1000 Anwendern ...
|
AW: AnsiString zu String zuweisen ohne Konvertierung?
Zitat:
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 12:40 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