AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi [TStringList] Problem mit einer Datei (Lädt nicht)
Thema durchsuchen
Ansicht
Themen-Optionen

[TStringList] Problem mit einer Datei (Lädt nicht)

Ein Thema von xZise · begonnen am 2. Okt 2006 · letzter Beitrag vom 28. Okt 2006
Antwort Antwort
Seite 2 von 2     12   
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#11

Re: [TStringList] Problem mit einer Datei (Lädt nicht)

  Alt 28. Okt 2006, 10:25
Guten Morgen,

auch die Methoden SaveToFile() und LoadFromFile() von TStrings arbeiten mit Textdateien - und mit dem Zeilentrenner CR/LF für solche Dateien. Du möchtest beliebige Zeichen (#0..#255) in deiner Datei speichern, wie man auch an deiner Musterdatei sehen kann. Kritisch sind dabei solche Zeichen wie #0 (NULL) #13 (CR) #10 (LF) und gelegentlich #26 (EOF), weil sie bei der Verarbeitung von Text als Steuerzeichen interpretiert werden.

Das Schlüsselwort PACKED kannst du mit strukturierten (record) und wiederholten (array) Feldern benutzen um die Ausrichtung einzelner Felder an Doppelwortgrenzen zu verhindern, was zwar das Laufzeitverhalten günstig beeinflusst, aber den Speicherverbrauch stark erhöht. Mir ist eine kompakte Speicherung wichtig, da ich die Matrix als Speicherblock behandeln möchte.

Wenn die Dimensionen deiner drei-dimensionalen Matrix nicht feststehen, dann musst du sie mit in die Datei schreiben, vorzugsweise als Header davor:

Delphi-Quellcode:
const
  LEVELS = 4;
  ROWS = 12;
  COLS = 12;

type
  TDimArray = array [0..3] of Byte;
  TMatrix = packed array of array of array of Byte;

procedure RedimMatrix(var m: TMatrix; dim: array of Byte);
begin
  SetLength(m, LEVELS, ROWS, COLS);
end;

procedure SaveMatrix(m: TMatrix; fn: TFileName);
var
  dwDim, dwSize: Cardinal;
begin
  dwDim := (Length(m) shl 8 + Length(m[0])) shl 8 + Length(m[0, 0]);
  dwSize := Length(m) * Length(m[0]) * Length(m[0, 0]);
  with TFileStream.Create(fn, fmCreate) do
  try
    Write(dwDim, SizeOf(dwDim));
    Write(m[0], dwSize); // korrigiert
  finally
    Free;
  end;
end;

procedure LoadMatrix(var m: TMatrix; fn: TFileName);
var
  dwDim, dwSize: Cardinal;
  dim: TDimArray absolute dwDim;
begin
  with TFileStream.Create(fn, fmOpenRead or fmShareDenyWrite) do
  try
    Read(dwDim, SizeOf(dwDim));
    // SetLength(m, Hi(dwDim), Lo(dwDim) shr 8, dwDim and $FF); // fehlerhaft
    SetLength(m, dim[2], dim[1], dim[0]);
    dwSize := Length(m) * Length(m[0]) * Length(m[0, 0]);
    Read(m[0], dwSize); // korrigiert
  finally
    Free;
  end;
end;

{
procedure TestMatrix; 
const
  FN = 'c:\daten\dp\map.f2m';
var
  m: TMatrix;
  iLevel, iRow, iCol: Integer;
begin
  RedimMatrix(m, [LEVELS, ROWS, COLS]);
  for iLevel := Low(m) to High(m) do
    for iRow := Low(m[0]) to High(m[0]) do
      for iCol := Low(m[0, 0]) to High(m[0, 0]) do
        m[iLevel, iRow, iCol] := 48 + iLevel * 4 + iRow * iCol mod 10;
  SaveMatrix(m, fn);
  FillChar(m, SizeOf(m), 0);
  LoadMatrix(m, fn);
end;
}


procedure TestMatrix;
const
  FN = 'c:\daten\dp\map.f2m';
var
  m: TMatrix;
  iLevel, iRow, iCol: Integer;
  dwSize: Cardinal;
  okay: Boolean;
begin
  RedimMatrix(m, [LEVELS, ROWS, COLS]);
  dwSize := LEVELS * ROWS * COLS;
  for iLevel := Low(m) to High(m) do
    for iRow := Low(m[0]) to High(m[0]) do
      for iCol := Low(m[0, 0]) to High(m[0, 0]) do
        m[iLevel, iRow, iCol] := 48 + iLevel * 4 + iRow * iCol mod 10;
  SaveMatrix(m, fn);
  FillChar(m[0], dwSize, 0);
  LoadMatrix(m, fn);
  okay := True;
  for iLevel := Low(m) to High(m) do
    for iRow := Low(m[0]) to High(m[0]) do
      for iCol := Low(m[0, 0]) to High(m[0, 0]) do
        if m[iLevel, iRow, iCol] <> 48 + iLevel * 4 + iRow * iCol mod 10 then
          okay := False;
  WriteLn(IfThen(okay, 'fine', 'rats'));
end;
Freundliche Grüße
  Mit Zitat antworten Zitat
Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#12

Re: [TStringList] Problem mit einer Datei (Lädt nicht)

  Alt 28. Okt 2006, 11:19
Zitat von marabu:
Guten Morgen,

auch die Methoden SaveToFile() und LoadFromFile() von TStrings arbeiten mit Textdateien - und mit dem Zeilentrenner CR/LF für solche Dateien. Du möchtest beliebige Zeichen (#0..#255) in deiner Datei speichern, wie man auch an deiner Musterdatei sehen kann. Kritisch sind dabei solche Zeichen wie #0 (NULL) #13 (CR) #10 (LF) und gelegentlich #26 (EOF), weil sie bei der Verarbeitung von Text als Steuerzeichen interpretiert werden.
Achso ... Okay...

Zitat von marabu:
Das Schlüsselwort PACKED kannst du mit strukturierten (record) und wiederholten (array) Feldern benutzen um die Ausrichtung einzelner Felder an Doppelwortgrenzen zu verhindern, was zwar das Laufzeitverhalten günstig beeinflusst, aber den Speicherverbrauch stark erhöht. Mir ist eine kompakte Speicherung wichtig, da ich die Matrix als Speicherblock behandeln möchte.
Verstehe ich noch net ganz

Zitat von marabu:
Wenn die Dimensionen deiner drei-dimensionalen Matrix nicht feststehen, dann musst du sie mit in die Datei schreiben, vorzugsweise als Header davor:
Indirekt weiß ich die Größe, da die Breite der Datei, die Breite der Map sein wird, und die Höhe der Datei, die Höhe der Map durch 4...

Also müsste ich nichts im Header schreiben Obwohl ich dann das Problem bei #10 und #13 hätte, da die ja ein Zeilenumbruch verursachen... Also doch Header

Zitat von marabu:
Delphi-Quellcode:
const
  LEVELS = 4;
  ROWS = 12;
  COLS = 12;

type
  TMatrix = packed array of array of array of Byte;

procedure RedimMatrix(var m: TMatrix; dim: array of Byte);
begin
  SetLength(m, LEVELS, ROWS, COLS);
end;
Das ist verstanden

Zitat von marabu:
Delphi-Quellcode:
procedure SaveMatrix(m: TMatrix; fn: TFileName);
var
  dwDim, dwSize: Cardinal;
begin
  dwDim := (Length(m) shl 8 + Length(m[0])) shl 8 + Length(m[0, 0]);
  dwSize := Length(m) * Length(m[0]) * Length(m[0, 0]);
  with TFileStream.Create(fn, fmCreate) do
  try
    Write(dwDim, SizeOf(dwDim));
    Write(m, dwSize);
  finally
    Free;
  end;
end;
Ähm...
1. Was ist shl?
2. Soll dwDim der Header sein?
3. Was ist "SizeOf"? Soetwas wie "Length"?

Zitat von marabu:
Delphi-Quellcode:
procedure LoadMatrix(var m: TMatrix; fn: TFileName);
var
  dwDim, dwSize: Cardinal;
begin
  with TFileStream.Create(fn, fmOpenRead or fmShareDenyWrite) do
  try
    Read(dwDim, SizeOf(dwDim));
    SetLength(m, Hi(dwDim), Lo(dwDim) shr 8, dwDim and $FF);
    dwSize := Length(m) * Length(m[0]) * Length(m[0, 0]);
    Read(m, dwSize);
  finally
    Free;
  end;
end;
Also das stößt schon auf weitere Verständnisprobleme:
1. dwDim hat ja noch keine Größe, aber warum funktioniert dann SizeOf?
2. Hi = High? Lo = Low? Oder was für Funktionen sind das?

Zitat von marabu:
Delphi-Quellcode:
procedure TestMatrix;
const
  FN = 'c:\daten\dp\map.f2m';
var
  m: TMatrix;
  iLevel, iRow, iCol: Integer;
begin
  RedimMatrix(m, [LEVELS, ROWS, COLS]);
  for iLevel := Low(m) to High(m) do
    for iRow := Low(m[0]) to High(m[0]) do
      for iCol := Low(m[0, 0]) to High(m[0, 0]) do
        m[iLevel, iRow, iCol] := 48 + iLevel * 4 + iRow * iCol mod 10;
  SaveMatrix(m, fn);
  FillChar(m, SizeOf(m), 0);
  LoadMatrix(m, fn);
end;
Das ist wieder logisch! Danke erstmal dafür
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#13

Re: [TStringList] Problem mit einer Datei (Lädt nicht)

  Alt 28. Okt 2006, 12:01
Hallo Fabian,

für die gängigen Mikro-Prozessoren sind Zugriffe auf Speicheradressen vorteilhaft, die ein Vielfaches der Registerbreite darstellen. Mit PACKED wird die vom Delphi-Compiler aus Performanzgründen (eventuell) vorgenommene Spreizung der einzelnen Felder eines strukturierten Datentyps verhindert.

Wenn die Dimensionen feststehen, dann musst du nicht mit einem dynamischen Array arbeiten. Den Header mit den Dimensionen würde ich wohl auch dann schreiben, aber die Redimensionierung in der Routine LoadMatrix() würde ich durch eine Dimensionsprüfung ersetzen.

Probleme mit #13 und #10 hast du immer - wenn du an der Textdatei festhalten willst.

"n SHL 8" ist das gleiche wie "n * 256" - oder auch "n * 2 hoch 8". Die Online-Hilfe von Delphi beschreibt die Operatoren SHL und SHR ganz gut.

dwDIM ist tatsächlich der Header - ein Vier-Byte-Wert, bei dem wegen deiner drei Dimensionen ein Byte nicht genutzt wird.

SizeOf(m) gibt den von m belegten Nettospeicher in Bytes an. Length(m) würde dir Größe der ersten Dimension des Arrays liefern.

SizeOf(dwSize) funktioniert also immer und liefert 4 - wie auch SizeOf(Integer).

Hi() und Lo() sind in meinem Code fehlerhaft angewendet, ich habe die Zeile geändert.


Grüße
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#14

Re: [TStringList] Problem mit einer Datei (Lädt nicht)

  Alt 28. Okt 2006, 12:23
Hallo marabu,

hast du übersehen, daß bei dynamischen Arrays nur ein Zeiger auf die Verwaltungsinformationen in der Referenzvariablen abgelegt wird? SizeOf(m) liefert also tatsächlich nur den Wert 4 - die Größe eines Pointers. Beim Aufruf von FileStream.Read, TFileStream.Write und FillChar muß also die Adresse des ersten Feldelements übergeben werden. Bei FillChar ist zusätzlich der zweite Parameter anzupassen.

Gruß Hawkeye
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#15

Re: [TStringList] Problem mit einer Datei (Lädt nicht)

  Alt 28. Okt 2006, 12:46
Hallo Hawkeye,

zwar habe ich nach der Umstellung meines Codes von statischem auf dynamisches Array die Routine SaveMatrix() angepasst, aber offensichtlich einige Stellen übersehen.

Freundliche Grüße

PS: Habe (hoffentlich) alle notwendigen Änderungen nachgetragen.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:50 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