Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   ListView - Mache ich was Falsch? (https://www.delphipraxis.net/184609-listview-mache-ich-falsch.html)

milos 9. Apr 2015 15:16


ListView - Mache ich was Falsch?
 
Liste der Anhänge anzeigen (Anzahl: 1)
edit: bild hinzugefügt

Hallo,

ich muss zum testen mehrere Personen aus zufallsnamen generieren und diese dann darstellen.
Ich habe 2 Funktionen.
Die 1. zum generieren und die 2. zum Laden.

Beim Generieren wird die Liste richtig dargestellt, aber beim Laden werden fälschlicherweise immer die vorherigen Werte aus der Liste übernommen.

Meine Frage ist, mache ich hier was falsch und sehe es nach 10 minuten immer noch nicht oder muss das Problem in der TBinObject klasse liegen?
Delphi-Quellcode:
procedure TForm1.btn2Click(Sender: TObject);
var
  bin : TBinObject;
  c: Integer;

  LListItem : TListItem;

  LBinItem : TBinItem;
  x: Integer;

  StartTime : TDateTime;
begin
  bin := TBinObject.Create;
  bin.LoadFromFile('personen.txt');
  lv1.Clear;

  StartTime := Now;
  for c := 0 to bin.Count-1 do
  begin
    LBinItem := bin[c];

    LListItem := lv1.Items.Add;
    LListItem.Caption := ByteListToString(LBinItem[0]);

    for x := 1 to LBinItem.Count-1 do
    begin
      LListItem.SubItems.Add(ByteListToString(bin[c][x]))
    end;
  end;

  lbl2.Caption := FloatToStr(MilliSecondsBetween(now,starttime)/1000)+'s';
end;
Im vergleich dazu, das generieren.

Delphi-Quellcode:
procedure TForm1.btn1Click(Sender: TObject);
var
  c: Integer;
  x: Integer;
  StartTime : TDateTime;
  Bin : TBinObject;

  AListItem : TListItem;

  LVorname, LNachname : string;
begin
  Bin := TBinObject.Create;
  StartTime := Now;
  lv1.Clear;
  for c := 0 to StrToInt(lbledt1.Text)-1 do
  begin
    LVorname := mmo1.Lines[Random(mmo1.Lines.Count)];
    LNachname := mmo2.Lines[Random(mmo2.Lines.Count)];


    Bin.Add(TBinItem.Create);

    Bin[c].Add(StringToByteList(c.ToString()));
    Bin[c].Add(StringToByteList(LVorname));
    Bin[c].Add(StringToByteList(LNachname));


    AListItem := lv1.Items.Add;
    AListItem.Caption := c.ToString();
    AListItem.SubItems.Add(LVorname);
    AListItem.SubItems.Add(LNachname);

    Caption := c.ToString();
  end;

  Bin.SaveToFile('personen.txt');


  lbl2.Caption := FloatToStr(MilliSecondsBetween(now,starttime)/1000)+'s';
end;
Einzelne Werte funktionieren ohne probleme und ich wüsste wirklich nicht mehr wo suchen.

Freundliche Grüsse

TBx 9. Apr 2015 15:26

AW: ListView - Mache ich was Falsch?
 
Um da überhaupt etwas zu sagen zu können, solltest Du die Deklaration von TBinObject und TBinItem zur Verfügung stellen. Vorher kann man da nur mit :glaskugel: arbeiten.

DeddyH 9. Apr 2015 15:27

AW: ListView - Mache ich was Falsch?
 
Lass Dir doch ByteListToString(LBinItem[0]) mal ausgeben, dann siehst Du, ob das schon nicht stimmt. Ohne die Klasse zu kennen kann man aber nicht mehr sagen.

himitsu 9. Apr 2015 15:39

AW: ListView - Mache ich was Falsch?
 
Man könnte fast denken jemand hab bei ByteListToString vergessen das Result zu initialisieren,
aber da diese Funktion streng geheim ist, wird da keiner helfen können. :stupid:

Jumpy 9. Apr 2015 15:41

AW: ListView - Mache ich was Falsch?
 
Müsste das:
Delphi-Quellcode:
LListItem.SubItems.Add(ByteListToString(bin[c][x]))
nicht so
Delphi-Quellcode:
LListItem.SubItems.Add(ByteListToString(LBinItem[x]))
sein? Oder ist es egal?

Und beim generieren zum Testen mal ersetzen:
Delphi-Quellcode:
AListItem.Caption := c.ToString();
AListItem.SubItems.Add(LVorname);
AListItem.SubItems.Add(LNachname);

//durch

AListItem.Caption := ByteListToString(bin[c][0]);
AListItem.SubItems.Add(ByteListToString(bin[c][1]));
AListItem.SubItems.Add(ByteListToString(bin[c][2]));

DeddyH 9. Apr 2015 15:42

AW: ListView - Mache ich was Falsch?
 
Zitat:

Delphi-Quellcode:
LBinItem := bin[c];

Frage beantwortet? ;)

ringli 9. Apr 2015 15:44

AW: ListView - Mache ich was Falsch?
 
Delphi-Quellcode:
bin.LoadFromFile('personen.txt');
bzw.
Delphi-Quellcode:
Bin.SaveToFile('personen.txt');

Bist du sicher das immer das richtige Verzeichnis beim Laden bzw. Speichern der Datei verwendet wird? Ich würde hier mal den vollständigen Pfad verwenden z.B. unter zuhilfenahme von
Delphi-Quellcode:
ExtractFilePath(ParamStr(0)) + 'personen.txt');
oder ähnlichen Funktionen da ich jetzt nicht weiß wo deine Textdatei später liegen soll.

[EDIT]
Ausserdem wird in beiden Prozeduren
Delphi-Quellcode:
Bin := TBinObject.Create;
aufgerufen, aber nie wieder freigegeben. Keine Ahnung was das für Auswirkungen in deinem Projekt haben könnte.

Jumpy 9. Apr 2015 16:05

AW: ListView - Mache ich was Falsch?
 
Zitat:

Zitat von DeddyH (Beitrag 1296935)
Zitat:

Delphi-Quellcode:
LBinItem := bin[c];

Frage beantwortet? ;)

War mir ja eigentlich klar, dass das für den Fehler wahrsch. irrelevant ist. Ich wollte nur drauf hinaus, das man entweder LBinItem komplett weg lassen kann und immer bin[c] nimmt, oder wenn man schon LBinItem als Zwischenvariable nutzt immer damit arbeitet.

milos 9. Apr 2015 18:12

AW: ListView - Mache ich was Falsch?
 
Zitat:

Zitat von himitsu (Beitrag 1296933)
Man könnte fast denken jemand hab bei ByteListToString vergessen das Result zu initialisieren,...

Oups, genau das war es vielen dank :D

Und nein, die Klasse ist natürlich nicht geheim, nur bisschen Quick & Dirty, war mir aber fast sicher, dass der Fehler in der Form Klasse steckt :oops:

Hier der Code für die interessierten.
Es handelt sich dabei um eine unit um Binärdateien im folgenden format auszulesen und zu schreiben.
STX Wert ETX Wert ETX Wert ETX ... EOT

STX: Start of Text - Startet einen neuen Datensatz Bytewert: 0x02
ETX: End of Text - Beendet den Datensatzpunkt Bytewert: 0x03
EOT: End of Transmission - Beendet den Datensatz Bytewert: 0x04

Delphi-Quellcode:
unit BinObject;

interface

uses
  Classes,
  Generics.Collections,
  SysUtils;

type
  TBinItem = class
  private
    FSubItems : TList<TList<Byte>>;
    function FGetBytes(AIndex : integer) : TList<Byte>;
    function FGetCount : integer;
  public
    procedure Add(ABytes : TList<Byte>);
    constructor Create();
    property Count : Integer read FGetCount;
    property Item[AIndex : integer] : TList<Byte> read FGetBytes; default;
  end;

  TBinObject = class
  private
    FBinaryReader : TBinaryReader;
    FBinaryWriter : TBinaryWriter;
    FItems : TList<TBinItem>;
    function FGetCount : integer;
    function FGetItem(AIndex : integer) : TBinItem;
  public
    constructor Create();
    procedure SaveToFile(AFileName : string);
    procedure LoadFromFile(AFileName : string);
    procedure Add(ABinItem : TBinItem);
    property Count : Integer read FGetCount;
    property Item[AIndex : integer] : TBinItem read FGetItem; default;
  end;


  function StringToByteList(AString : string) : TList<Byte>;
  function ByteListToString(AByteList : TList<Byte>) : string;

var
  LastResult : string;
  LastRead : string;
implementation

const
  IndexPrefix = 310;

function ByteListToString(AByteList : TList<Byte>) : string;
var
  c: Integer;
begin
  Result := '';

  for c := 0 to AByteList.Count-1 do
  begin
    Result := Result + (Ansichar(AByteList[c] - IndexPrefix));
  end;
end;

function StringToByteList(AString : string) : TList<Byte>;
var
  c: Integer;
begin
  Result := TList<Byte>.Create;
  for c := 1 to Length(Astring) do
  begin
    Result.Add(Ord(AString[c]) + IndexPrefix);
  end;
end;


{ TBinData }

procedure TBinItem.Add(ABytes: TList<Byte>);
begin
  FSubItems.Add(ABytes);
end;

constructor TBinItem.Create;
begin
  FSubItems := TList<TList<Byte>>.Create;
end;

function TBinItem.FGetBytes(AIndex: integer): TList<Byte>;
begin
  Result := FSubItems[AIndex];
end;

function TBinItem.FGetCount: integer;
begin
  Result := FSubItems.Count;
end;

{ TBinObject }

procedure TBinObject.Add(ABinItem: TBinItem);
begin
  FItems.Add(ABinItem);
end;

constructor TBinObject.Create;
begin
  FItems := TList<TBinItem>.Create;
end;

function TBinObject.FGetCount: integer;
begin
  Result := FItems.Count;
end;

function TBinObject.FGetItem(AIndex: integer): TBinItem;
begin
  Result := FItems[AIndex];
end;

procedure TBinObject.LoadFromFile(AFileName: string);
var
  TransmissionStarted : boolean;
  InValue : Boolean;
  Finished : Boolean;

  LBinItem : TBinItem;
  LByteBuffer : TList<Byte>;
  LStringBuffer : string;
  TeBuffer : TList<Byte>;
  LByte : byte;
begin
  FItems := TList<TBinItem>.Create;
  TransmissionStarted := false;
  InValue := false;
  Finished := false;
  LByteBuffer := TList<Byte>.Create;
  LBinItem := TBinItem.Create;
  LStringBuffer := '';

  FBinaryReader := TBinaryReader.Create(AFileName);

  repeat
    try
      LByte := FBinaryReader.ReadByte;

      if not(TransmissionStarted) then
      begin
        if LByte = $02  then
        begin
          TransmissionStarted := true;
          InValue := true;
          Continue
        end
        else
          raise Exception.Create('Row started wrong.');

        Exit;
      end
      else
      begin
        if InValue then
        begin

          if LByte = $04 then
          begin
            TransmissionStarted := false;

            Add(LBinItem);
            LBinItem := TBinItem.Create;

            Continue;
          end;

          if LByte = $03 then
          begin
            LBinItem.Add(StringToByteList(LStringBuffer));
            LStringBuffer := '';
            Continue;
          end;

          LByteBuffer.Add(LByte);
          LStringBuffer := LStringBuffer + AnsiChar(LByte - IndexPrefix);
        end
      end;

    except
      Finished := true;
    end;
  until (Finished);

  FBinaryReader.Close;
end;

procedure TBinObject.SaveToFile(AFileName: string);
var
  ItemIndex: Integer;
  LBinItem : TBinItem;
  SubItemIndex: Integer;
  LSubItem : TList<byte>;
  LByte : byte;
  ByteIndex: Integer;
begin
  FBinaryWriter := TBinaryWriter.Create(AFileName);

  LastResult := '';
  for ItemIndex := 0 to Count-1 do
  begin
    FBinaryWriter.Write($2);
    LastResult := LastResult+'2 ';

    LBinItem := Item[ItemIndex];
    for SubItemIndex := 0 to LBinItem.Count-1 do
    begin
      LSubItem := LBinItem.Item[SubItemIndex];
      for ByteIndex := 0 to LSubItem.Count -1 do
      begin
        LByte := LSubItem[ByteIndex];
        FBinaryWriter.Write(LByte);
        LastResult := LastResult+char(LByte);

      end;
        FBinaryWriter.Write($3);
    LastResult := LastResult+' 3 ';
    end;
    FBinaryWriter.Write($4);
    LastResult := LastResult+' 4';
  end;

  FBinaryWriter.Close;
end;

end.


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