Autor Beitrag
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2274
Erhaltene Danke: 419

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 22.01.19 00:39 
Hallo Forum

Problemstellung:
Was genau bewirken die Methoden .seekp() und .seekg() aus der Klasse fstream, oder noch besseer, worin unterscheiden sie sich?
Sie scheinen sich doch etwas vom Delphi-internen TStream.Seek zu unterscheiden, zumindest komme ich dabei auf keinen gemeinsamen Nenner.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 3978
Erhaltene Danke: 813

Win7
C++, C# (VS 2015/17)
BeitragVerfasst: Di 22.01.19 11:34 
Hallo,

ein fstream ist sowohl lesend als auch schreibend (im Gegensatz zu jeweils ifstream und ofstream), so daß es für die Lese- und die Schreibposition 2 verschiedene Werte gibt (g und p stehen für get und put - keine tollen Namen m.E. ;- ).

Beim TStream gibt es wohl nur eine Position für beide: TStream.Position.

Für diesen Beitrag haben gedankt: Frühlingsrolle
Frühlingsrolle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2274
Erhaltene Danke: 419

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 22.01.19 14:17 
Vielen Dank, Th69!

Ist damit dann folgendes gemeint?

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
// c++
stream.seekg(pos);
stream.seekp(pos);
// delphi
pos := stream.Position;
stream.Position := pos;

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 3978
Erhaltene Danke: 813

Win7
C++, C# (VS 2015/17)
BeitragVerfasst: Di 22.01.19 15:15 
Nicht direkt, sondern einfach nur
ausblenden Delphi-Quelltext
1:
2:
// delphi
stream.Position := pos;

(d.h. es gibt nur genau 1 Lese- und Schreibposition in Delphi).

Zum Auslesen in C++ gibt es die beiden Funktionen tellg und tellp, d.h. dies entspricht dann
ausblenden Delphi-Quelltext
1:
2:
// delphi
pos := stream.Position;

Wenn du C++ Code hast, der unterschiedliche Lese- und Schreibpositionen benutzt, dann müßtest du das selber in Delphi nachhalten.

Für diesen Beitrag haben gedankt: Frühlingsrolle
Frühlingsrolle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2274
Erhaltene Danke: 419

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 22.01.19 15:50 
So komme ich mit dem TStream nicht weiter. Vielleicht wären dann TWriter und TReader sinnvoller in der Anwendung. Dafür müsste ich aber verstehen, wie folgendes fstream-Beispiel aussehen würde, wenn man stattdessen ifstream und ofstream anwenden würde:

ausblenden C++-Quelltext
1:
2:
3:
4:
5:
fstreamVar.seekg(pos);
fstreamVar.read((char)*dummy, dummySize);
// ...
fstreamVar.seekp(pos);
fstreamVar.write((char)*dummy, dummySize);

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 3978
Erhaltene Danke: 813

Win7
C++, C# (VS 2015/17)
BeitragVerfasst: Di 22.01.19 17:33 
Wenn es jeweils die gleiche Variable beim Lesen und Schreiben ist, dann kannst du doch TStream benutzen, und mußt nur jeweils vor jedem Lesen und Schreiben die Position setzen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
stream.Position := pos;
stream.Read(...);

stream.Position := pos;
stream.Write(...);


PS: Drücke ich mich zu unverständlich aus?
Frühlingsrolle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2274
Erhaltene Danke: 419

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 22.01.19 18:23 
Dich verstehe ich, nur Delphi verstehe ich im Moment nicht so ganz.

In einem internen Topic habe ich diesen Beitrag verlinkt.
Er behandelt eine Dateiverschlüsselung mittels XTEA.
Aus Neugier habe ich ihn im C++ Builder übernommen, kleinere Änderungen vorgenommen, und da funktioniert das Beispiel.
Jetzt habe ich es nach Delphi übersetzt und da bekomme ich nur Datenmüll zusammen.
Im Debugger habe ich mir die Werte angesehen und verglichen, konnte keine Abweichung nachvollziehen.
Also bin ich der Meinung, dass es an den besagten (c++) Methoden scheitert.

Zum Vergleich, einmal in C++:

ausblenden volle Höhe C++-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
#include <fstream>

typedef unsigned int        uint32_t;
typedef unsigned int    UINT;
typedef unsigned char       BYTE;

#define BLOCK_SIZE 8

UINT key[4] = { 0xACED0xBABE0xDEAF0xFACE };

void encipher(UINT num_rounds, uint32_t v[2], uint32_t const key[4])
{
  uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
  for (UINT i = 0; i < num_rounds; i++)
  {
    v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    sum += delta;
    v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
  }
  v[0] = v0; v[1] = v1;
}

void decipher(UINT num_rounds, uint32_t v[2], uint32_t const key[4])
{
  uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
  for (UINT i = 0; i < num_rounds; i++)
  {
    v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
    sum -= delta;
    v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
  }
  v[0] = v0; v[1] = v1;
}

void FileCrypt(char filePath[], bool encrypt)
{
  fstream file(filePath, ios::in | ios::out | ios::binary);

  if (file)
  {
    file.seekg(0, ios::end);
    UINT fileSize = file.tellg();
    file.seekg(ios::beg);
    file.clear();

    UINT nBlocks = fileSize / BLOCK_SIZE;
    if (fileSize % BLOCK_SIZE != 0)
      nBlocks++;

    BYTE fileData[BLOCK_SIZE];
    UINT filePos = file.tellg();

    for (UINT i = 0; i < nBlocks; i++)
    {
      file.seekg(filePos);
      file.read((char*)fileData, BLOCK_SIZE);

      if (encrypt)
        encipher(32, (uint32_t*)fileData, key);
      else
        decipher(32, (uint32_t*)fileData, key);

      file.seekp(filePos);
      file.write((char*)fileData, BLOCK_SIZE);

      memset(fileData, 0, BLOCK_SIZE);
      filePos += BLOCK_SIZE;
    }
  }
    file.close();
}

// Aufruf
char file[] = "C:/Users/---/Desktop/Dummy.cs";
FileCrypt(file, CheckBox1->Checked);

Und die Übersetzung nach Delphi:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
type
// "stdint.h"
// typedef unsigned int                uint32_t;
  uint32_t = UINT;

  UInts2 = array[0..1of uint32_t;
  UInts4 = array[0..3of uint32_t;

procedure encipher(num_rounds: UINT; var v: UInts2; key: UInts4);
var
  i: UINT;
  v0, v1, sum, delta: uint32_t;
begin
  v0 := v[0];
  v1 := v[1];
  sum := 0;
  delta := $9E3779B9;

  for i := 0 to num_rounds - 1 do
  begin
    v0 := v0 + (((v1 shl 4xor (v1 shr 5)) + v1) xor (sum + key[sum and 3]);
    sum := sum + delta;
    v1 := v1 + (((v0 shl 4xor (v0 shr 5)) + v0) xor (sum + key[(sum shr 11and 3]);
  end;

  v[0] := v0;
  v[1] := v1;
end;

procedure decipher(num_rounds: UINT; var v: UInts2; key: UInts4);
var
  i: UINT;
  v0, v1, sum, delta: uint32_t;
begin
  v0 := v[0];
  v1 := v[1];
  delta := $9E3779B9;
  sum := delta * num_rounds;

  for i := 0 to num_rounds - 1 do
  begin
    v1 := v1 - (((v0 shl 4xor (v0 shr 5)) + v0) xor (sum + key[(sum shr 11and 3]);
    sum := sum - delta;
    v0 := v0 - (((v1 shl 4xor (v1 shr 5)) + v1) xor (sum + key[sum and 3]);
  end;

  v[0] := v0;
  v[1] := v1;
end;

procedure FileCrypt(FileName: string; Encrypt: Boolean);
const
  BLOCK_SIZE = 8;
  KEYS: UInts4 = ( $ACED$BABE$DEAF$FACE );
var
  fileStream: TFileStream;
  streamSize, streamPos, nBlocks: UINT;
  i: Integer;
  data: array[0..BLOCK_SIZE - 1of Byte;
begin
  fileStream := TFileStream.Create(FileName, fmOpenReadWrite);
  try
    fileStream.Seek(0, soEnd);  // bzw. fileStream.Position := fileStream.Size;
    streamSize := fileStream.Size;
    fileStream.Seek(0, soBeginning); // bzw. fileStream.Position := 0;

    nBlocks := streamSize div BLOCK_SIZE;
    if streamSize mod BLOCK_SIZE <> 0 then
      nBlocks := nBlocks + 1;

    ZeroMemory(@data, SizeOf(data));
    streamPos := fileStream.Position;

    for i := 0 to nBlocks - 1 do
    begin
      fileStream.Position := streamPos;
      fileStream.Read(data[0], BLOCK_SIZE);

      if Encrypt then
        encipher(32, Uints2(data), KEYS) else
        decipher(32, UInts2(data), KEYS);

      fileStream.Position := streamPos;
      fileStream.Write(data[0], BLOCK_SIZE);

      ZeroMemory(@data, SizeOf(data));
      streamPos := streamPos + BLOCK_SIZE;
    end;
  finally
    fileStream.Free;
  end;
end;

// Aufruf
var
  s: string;
begin
  s := 'C:\Users\---\Desktop\Dummy.cs';
  FileCrypt(s, CheckBox1.Checked);
end;

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 3978
Erhaltene Danke: 813

Win7
C++, C# (VS 2015/17)
BeitragVerfasst: Di 22.01.19 21:05 
Müsste es nicht eher fileStream.Read(data, BLOCK_SIZE) heißen?
Oder gibt man in Delphi bei einem Array den ersten Index an?
Oder werte mal den Rückgabewert von Read aus, ob wirklich die Anzahl Zeichen BLOCK_SIZE gelesen wurden.

Werden denn ohne encipher bzw. decipher die Daten korrekt gelesen und wieder zurückgeschrieben? Evtl. ist ja sonst ein Fehler in diesen Prozeduren.

Für diesen Beitrag haben gedankt: Frühlingsrolle
Frühlingsrolle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2274
Erhaltene Danke: 419

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 22.01.19 22:32 
Zitat:
Müsste es nicht eher fileStream.Read(data, BLOCK_SIZE) heißen?

Da bin ich mir unsicher. Die Methode nimmt beides an (data, data[0]) und liefert in beiden Fällen ein korrektes Ergebnis.

Die Delphi-Methoden encipher() und decipher() sind das Problem, denn sie liefern komplett andere Werte, im Vergleich zum C++ Beispiel.
Ich bin die Übersetzung nun 4 Mal rauf und runter durchgegangen. Optisch sieht es richtig aus, doch woran es liegt, da bin ich überfragt. :?
Der Debugger muss Abhilfe schaffen.

Nachtrag

Es haben Klammern gefehlt :autsch: :D
U.a. hier:

ausblenden C++-Quelltext
1:
2:
3:
4:
5:
6:
void encipher(UINT num_rounds, uint32_t v[2], uint32_t const key[4])
{
  // ...
  v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);  // richtig
  // ...
}

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure encipher(num_rounds: UINT; var v: UInts2; key: UInts4);
begin
  // ...
  v0 := v0 + (((v1 shl 4xor (v1 shr 5)) + v1) xor (sum + key[sum and 3]);  // falsch
  v0 := v0 + ((((v1 shl 4xor (v1 shr 5)) + v1) xor (sum + key[sum and 3]));
  // ...
end;

Bei so vielen Klammern verliert man auch den Überblick.

Das Thema hat sich erledigt !!!

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)