Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Diverse Probleme mit Strings, SetLength und SizeOf (https://www.delphipraxis.net/192567-diverse-probleme-mit-strings-setlength-und-sizeof.html)

a.def 1. Mai 2017 15:37

Diverse Probleme mit Strings, SetLength und SizeOf
 
In einem anderen Thread habe ich es nun endlich geschafft mein Vorhaben zu verwirklichen.
Dazu verwende ich, wie empfohlen, TFileStream und füge einer Datei am Ende 32 Zeichen hinzu.

Ich lese sie dann so wieder aus
Delphi-Quellcode:
  aFileStream.Position := 0;
  SetLength(s, aFileStream.Size - (32 * SizeOf(Char)));
  aFileStream.Read(s[1], Length(s));
Die auszulesende Zeichenkette ist 32 Zeichen lang. SizeOf(Char) gibt aber 2 und 2*32 ist 64. Wieso funktioniert das trotzdem?
Wenn ich 16*SizeOf(Char) verwende funktioniert es nicht mehr und es kommt Chinesisch als Ergebnis.

Mein Zweites Problem besteht darin, dass ich gerne alle X Zeichen ein neues Zeichen in meinen String einfügen möchte. Wie geht man das am besten an?

nahpets 1. Mai 2017 15:51

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Hingedaddelt:
Delphi-Quellcode:
function InsertZeichen(sZeichenfolge : String; chZeichen : Char; iPosition : Integer) : String;
var
  i : Integer;
begin
  Result := '';
  for i := 1 to Length(sZeichenfolge) do begin
    if i mod iPosition = 0 then Result := Result + chZeichen;
    Result := Result + Copy(sZeichenfolge,i,1);
    // oder
    Result := Result + sZeichenFolge[i];
  end;
end;

a.def 1. Mai 2017 15:58

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
An mod hab ich noch gar nicht gedacht, auch eine gute Idee Danke :thumb:

Eine letzte Frage bestünde darin, warum mein TFileStream.Write denn eigentlich nach jedem Zeichen ein NUL-Zeichen speichert
Delphi-Quellcode:
s := '7215EE9C7D9DC229D2921A40E899EC5F';
aFileStream.Position := aFileStream.Size;
aFileStream.Write(s[1], Length(s) * SizeOf(Char));

Olli73 1. Mai 2017 16:01

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Zitat:

Zitat von a.def (Beitrag 1369627)
Eine letzte Frage bestünde darin, warum mein TFileStream.Write denn eigentlich nach jedem Zeichen ein NUL-Zeichen speichert

Unicode?

a.def 1. Mai 2017 16:03

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Ich kenne mich mit dem Hin und Her in der Zeichenwelt leider kein bisschen aus.
Kannst du bitte erklären was du meinst?

nahpets 1. Mai 2017 16:08

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Ein Char ist (wie Du feststelltest) zwei Byte groß.

Die 0 plus eine Wert in der Größe von einem Byte.

Im Unicode belegt jedes Zeichen halt zwei Byte.

Bei Ansi und Ascii ist ein Char ein Byte groß.

Wühl dich mal durch diese Seite: Unicode-Tabelle

Dort kannst Du sehen, wann ein Char 'ne 0 plus ein Zeichen ist und wann zwei Zeichen.

bepe 1. Mai 2017 16:12

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Zitat:

Zitat von a.def (Beitrag 1369622)
Die auszulesende Zeichenkette ist 32 Zeichen lang. SizeOf(Char) gibt aber 2 und 2*32 ist 64. Wieso funktioniert das trotzdem?
Wenn ich 16*SizeOf(Char) verwende funktioniert es nicht mehr und es kommt Chinesisch als Ergebnis.

Zitat:

Zitat von a.def (Beitrag 1369627)
Eine letzte Frage bestünde darin, warum mein TFileStream.Write denn eigentlich nach jedem Zeichen ein NUL-Zeichen speichert

Der Standardstring ist UTF16 codiert. Also pro Zeichen 2 Byte, bei 32 Zeichen sind das 64 Byte. Da du keine "Sonderzeichen" verwendest, wird das zweite Byte nicht benötigt (daher NUL).

Du hast zwei Möglichkeiten:

- Arbeite dich ins Thema ein, sonst hast du keine Freude beim Lesen und Schreiben von Texten.
- Verzichte auf Unicode. Benutze nur AnsiString und AnsiChar und hoffe auf das Beste.

Wegen dem roten Kasten:
Bei Unicode kann ein Zeichen zwei Byte belegen, muss aber nicht. Das ist abhängig von der Kodierung.

a.def 1. Mai 2017 16:16

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Mhh in etwa so?

Delphi-Quellcode:
var
 s: AnsiString;
begin
 s := AnsiString(MachWas(Trim(String(s))));
 aFileStream.Write(s[1], Length(s) * SizeOf(Byte));
und
Delphi-Quellcode:
var
 s: AnsiString;
begin
 SetLength(s, aFileStream.Size - (32 * SizeOf(Byte)));
 aFileStream.Read(s[1], Length(s));
 s := AnsiString(MachWas(Trim(String(s))));
Ist dieses wilde rum-gecaste erlaubt, um die blöden Compiler-Warnungen wegzubekommen? Gespeichert und geladen wird korrekt.

Bernhard Geyer 1. Mai 2017 16:17

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Oder mach es wie empfohlen: Verwende keine Strings. Du hast Binärdaten. Hier sollte man nicht versuchen diese in irgendwelchen String-Variablen zu speichern um damit irgendwelche binären Operationen zu machen.

a.def 1. Mai 2017 16:20

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Zitat:

Verwende keine Strings.
Was sollte man denn sonst verwenden wenn keine Strings?

Ganz am Ende der Geschichte vergleiche ich dann aber trotzdem 2 Strings.

Bernhard Geyer 1. Mai 2017 16:26

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Zitat:

Zitat von a.def (Beitrag 1369637)
Zitat:

Verwende keine Strings.
Was sollte man denn sonst verwenden wenn keine Strings?

Kommt auf die Anforderung drauf an. z.B. ein festes Array (of Bytes) wäre eine Möglichkeit wenn (wie hier) du eh einen 32-Byte Hashwert vergleichen willst.

Zitat:

Zitat von a.def (Beitrag 1369637)
Ganz am Ende der Geschichte vergleiche ich dann aber trotzdem 2 Strings.

Und wieso? Du kannst genauso Streams/Array oder ähnliches Vergleichen z.B. mit CompareMem

a.def 1. Mai 2017 16:27

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Zitat:

Und wieso?
Weil es am einfachsten ist und ich das andere nicht kenne.

Ich schaffe es ja noch nicht einmal die Funktion von nahpets oben "rückgängig" zu machen. Also statt Zeichen X an Stelle N einfügen, entfernen.
Dann darf man mir nicht mit Speicheroperationen ankommen :P

bepe 1. Mai 2017 16:34

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Grundsätzlich hat Bernhard recht. Wenn du gar nicht mit Texten arbeitest sondern mit (binär) Daten, dann wären TBytes/Array of Byte vorzuziehen/richtiger.

Die Variante mit dem AnsiString ist nur dann OK, wenn das Ergebnis stimmt. Und du damit leben kannst früher oder später vielleicht noch einmal nachbessern zu müssen, weil dir doch etwas auf die Füße gefallen ist.

Das musst du entscheiden: Dich in das Thema einarbeiten oder mit einem Restrisiko leben.

nahpets 1. Mai 2017 16:40

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Meinst Du sowas?
Ebenfalls nur hingedaddelt:
Delphi-Quellcode:
function DeleteZeichen(sZeichenfolge : String; chZeichen : Char; iPosition : Integer) : String;
var
  i : Integer;
begin
  Result := '';
  for i := 1 to Length(sZeichenfolge) do begin
    if (i mod iPosition = 0)
    and (Copy(sZeichenfolge,i,1) = chZeichen) then
    else Result := Result + Copy(sZeichenfolge,i,1);
  end;
end;
iPosition muss hierbei um eins größer sein als bei InsertZeichen.

Oder:

Delphi-Quellcode:
function DeleteZeichen(sZeichenfolge : String; chZeichen : Char; iPosition : Integer) : String;
var
  i : Integer;
  iPos : Integer;
begin
  iPos := iPosition + 1;
  Result := '';
  for i := 1 to Length(sZeichenfolge) do begin
    if not (i mod iPos = 0) then begin
      Result := Result + Copy(sZeichenfolge,i,1);
    end;
  end;
end;
iPosition muss mit dem von InsertZeichen übereinstimmen.
chZeichen wird nicht benötigt, man könnte aber bei der Positionsabfrage noch prüfen, ob dort auch dieses Zeichen gefunden wird. Wenn nein, hat man einen Zeichenfolge, die eher ungeeignet für die Verarbeitung ist, da (vermutlich) das gesuchte Zeichen nicht per InsertZeichen eingefügt wurde.

Bernhard Geyer 1. Mai 2017 16:41

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Zitat:

Zitat von a.def (Beitrag 1369644)
Weil es am einfachsten ist und ich das andere nicht kenne.

Da es nicht funktioniert kann du nicht davon sprechen das es einfach ist.

Zitat:

Zitat von a.def (Beitrag 1369644)
Ich schaffe es ja noch nicht einmal die Funktion von nahpets oben "rückgängig" zu machen. Also statt Zeichen X an Stelle N einfügen, entfernen.
Dann darf man mir nicht mit Speicheroperationen ankommen :P

Die Frage ist wieso das du das überhaupt benötigst? Hat das mit dem eigentlichen Problem zu tun? Falls nein mach dafür einen eigenen Thread auf.

Zu deinem Eigentlichen Problem habe ich noch was gefunden:
http://www.delphidabbler.com/articles?article=7

Ich würde mir aber überlegen ob ich wirklich einfach so ein paar bytes an eine Exe hängen kann/will.
Es gibt ein definiertes Format (https://de.wikipedia.org/wiki/Portable_Executable) welches du mit solchen angehängten Daten störst (bin jetzt kein PE-Experte, evtl. darf man das ja auch).
Evtl. genügt es diese Info in eine weiter Datei als Salted Hash abzulegen.

a.def 1. Mai 2017 16:43

AW: Diverse Probleme mit Strings, SetLength und SizeOf
 
Es funktioniert jetzt wie ich will. Mit strings. Das andere ist mir zu kompliziert.

Zitat:

Die Variante mit dem AnsiString ist nur dann OK, wenn das Ergebnis stimmt.
Das Ergebnis stimmt. Also ist TBytes oder was auch immer hier meiner Meinung nach überflüssig.


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