Szukanie rekordów w pliku typowanym

0

Witam serdecznie po długiej nieobecności. Kiedyś (Delphi 4 + BDE) bawiłem się dla własnych potrzeb bazami danych. Teraz wróciłem do tematu, ale
czas biegnie do przodu. Mam RAD Delphi 10.4 Community Edition, w którym nie ma BDE. Nowoczesne silniki baz danych są dla mnie niepotrzebne a przyznam się trochę trudne. Zdecydowałem oprzeć się na plikach typowanych. Dopisanie danych działa bardzo dobrze. Listowanie pliku w ListView też działa, ale problem pojawia się gdy chcę wyszukać wszystkie rekordy spełniające trzy zadane parametry : Kategoria1, Kategoria2 i Kategoria3. Pojedyńczy parametr wyświetla tylko jeden rekord. A w pliku jest ich więcej. Dodanie drugiego parametru wiesza aplikację.
Mam nadzieję, że dobrze przedstawiłem swój problem i ktoś mi podpowie rozwiązanie.
PS. A może ma ktoś podpowiedź na uzyskanie BDE dla wersji Community.

1

Pojedyńczy parametr wyświetla tylko jeden rekord. A w pliku jest ich więcej. Dodanie drugiego parametru wiesza aplikację.

W takim razie ze sporą dozą pewności mogę powiedzieć, że problem jest w kodzie - sugeruję jego natychmiastową naprawę :-P

Bez kodu nie da się powiedzieć nic więcej - równie dobrze to wyszukiwanie może być napisane prawidłowo, ale dodawanie źle 🙃

0

Dziękuję za szybką reakcję.
Moja procedura:

procedure TForm6.Button1Click(Sender: TObject);
    var
    F : TRejestrFile;
    Rec : TRejestr;
    ListItem : TListItem;
    p : Boolean;
  begin
    AssignFile(F, 'Rejestr.dat');
    Reset(F);
      while not eof(F) do
      begin
         p := True;
           Read(F, Rec);
         if (ComboBox1.Text <> '') and (ComboBox1.Text <> Rec.Kategoria1) then
             p := False;
//         if (ComboBox2.Text <> '') and (ComboBox2.Text <> Rec.Kategoria2) then
//             p := False;
//         if (ComboBox3.Text <> '') and (ComboBox3.Text <> Rec.Kategoria3) then
//             p := False;
         if p then
           begin
             ListItem := Fotolista.Items.Add;
             ListItem.Caption := Rec.Kategoria1;
             ListItem.SubItems.Add(Rec.Kategoria2);
             ListItem.SubItems.Add(Rec.Kategoria3);
             ListItem.SubItems.Add(Rec.Nazwa);
             ListItem.SubItems.Add(Rec.Rok);
             ListItem.SubItems.Add(Rec.Płyta);
             ListItem.SubItems.Add(Rec.Mce);
             ListItem.SubItems.Add(Rec.ID);
             ListItem.SubItems.Add(Rec.Opis);
           end;
      end;
    CloseFile(F);
  end;

roszę oocenę i wskazanie ewentualnych blędów.

1

Mógłbyś jeszcze podrzucić TRejestr oraz w jaki sposób wrzucasz dane do tego pliku?

Ach, no i standardowo: skoro program się wiesza, to co mówi debugger? :-) Środowiska Delphi mają AFAIR jakiś swój wbudowany, więc znalezienie przyczyny błędu powinno być stosunkowo proste.

0

Dodanie nowego wpisu:

procedure TForm3.WriteDate;
var
  VFile : TVideoFile;                // zmienna wskazuje na nowy typ plikow
  VRec : TVideoRec;                  // zmianna wskazuje na rekord
  FSize : Integer;                   // ilosc danych znajdujacych sie w pliku...

begin

  AssignFile(VFile, FileName);       // skojarz nazwe pliku ze zmienna...
  if not FileExists(FileName) then   // jezeli plik nie istnieje...
    Rewrite(VFile)
  else              //... stworz go, a jezeli istnieje...
    Reset(VFile);                    //... tylko otworz

  try
    FSize := FileSize(VFile);        // pobierz rozmiar ( ilosc danych )
    if FSize > 0 then                // Czy plik nie jest pusty?
      Seek(VFile, FSize);            // ustaw na samym koncu pliku

           { Dodaj do rekordu dane wziete z kontrolek tekstowych znajdujacych
             sie na formie.}

    with VRec do

    begin
      Nazwa :=      Edit1.Text;
      Rok :=        Edit2.Text;
      Płyta :=      Edit3.Text;
      Mce :=        Edit4.Text;
      Kat1 :=       ComboBox1.Text;
      Kat2 :=       ComboBox2.Text;
      Kat3 :=       ComboBox3.Text;
      Opis :=       Memo1.Lines.Text;
      Obraz :=      ' DYSK ';
      Dir :=        Edit5.Text;
    end;
    Write(VFile, VRec);              // zapisz rekord do pliku

  finally
    CloseFile(VFile);               // zamknij plik
    Dopisz_1;
    Dopisz_2;
    Dopisz_3;

    ShowMessage ('Dopisano rekord do pliku.');
    RefreshRec;                      // wywolaj procedure ( patrz: linia 126 )
        Edit1.Text := '';
        Edit2.Text := '';
        Edit3.Text := '';
        Edit4.Text := '';
        Edit6.Text := '';
        Edit7.Text := '';
        Edit8.Text := '';
        ComboBox1.Text := '';
        ComboBox2.Text := '';
        ComboBox3.Text := '';
        Memo1.Lines.Text := '';
        Form3.Visible := False;

  end;
end;
//--------------------------------------------------------------------------------------------------

 TRejestr = packed record
  ID :         String[10];
  Nazwa :      String[30];
  Rok :        String[5];
  Płyta :      String[3];
  Mce :        String[3];
  Kategoria1 : String[20];
  Kategoria2 : String[20];
  Kategoria3 : String[20];
  Opis :       String[50];
  Obraz :      String[50];
  end;

plik rejestr.

0

W sprawie BDE to po prostu zainstaluj Zeoslib

0

Strasznie chaotyczny ten kod ale dobra wiemy czym jest TRejestr, TRejestrFile to zapewne TRejestrFile = file of TRejestr ale dlaczego przy zapisie używasz TVideoRec i TVideoFile zamiast jednej deklaracji?

0

Typowany plik tak, jak się myśli o tym w pascalu, to archaiczna struktura danych.
To jest na tysiące prymitywnych obiektów jednego typu - emulacja taśmy magnetycznej z lat 1970tych

Jak nie mam nic przeciwko zapisom binarnym, ale wszystkie współczesne koncepcje zakładają plik ze ZRÓZNICOWNYMI "ramkami" czy "obiektami"

0
           Read(F, Rec);
           p
           :=
             (ComboBox1.Text <> '') and
             (
               (ComboBox1.Text = Rec.Kategoria1) or
               (ComboBox1.Text = Rec.Kategoria2) or
               (ComboBox1.Text = Rec.Kategoria3)
             );
           if p then
1

Jeśli ComboBox1.Text jest pusty, to otwieranie pliku i jego wertowanie jest bezcelowe, bo i tak przecież nie ma czego szukać. Zmienna p też sensu nie ma, bo jeśli jest dopasowanie, to można od razu dodać pozycję do kontrolki, zamiast ustawiać flage, a chwilę później ją testować.

Poza tym, bardzo dziwnie nazywasz rzeczy — w połowie po polsku, w połowie po angielsku. Do tego wiele z nich wydaje się nieodpowiednich, zupełnie źle opisujących to czym są i do czego służą (np. rejestr opisuje pojedynczą pozycję).

0

Dziękuję za Wasze opinie i porady. Spróbuję wyjaśnić niektóre elementy:

  • "Rejestr" to nazwa pliku, być może niefortunna, ale taka mi przyszła na myśl,
  • zróżnicowane nazewnictwo spowodowane jest wykorzystaniem gotowych procedur z mojego archiwum,
  • jestem na etapie roboczym i przed finałem, ujednolicę nazewnictwo i "uczeszę" aplikację.
  • ComboBox1 jest wyborem Kategorii1, ComboBox2 Kategorii2, ComboBox3 Kategorii3 więc w szukaniu muszą być spełnione te trzy warunki,
  • zdecydowałem się na plik typowany, ponieważ chcę ograniczyć do minimum instalację aplikacji na drugim komputerze. Zakładam wykorzystanie aplikacji w rodzinie,
    Czekam na porady, które rozwiążą mój problem.
1

Jeżeli pusty combo oznacza wszystkie to:

Read(F, Rec);
p
:=
    ((ComboBox1.Text='')or(ComboBox1.Text=Rec.Kategoria1))and
    ((ComboBox2.Text='')or(ComboBox2.Text=Rec.Kategoria2))and
    ((ComboBox3.Text='')or(ComboBox3.Text=Rec.Kategoria3))
;
if p then
1
WiktorS napisał(a):
  • zdecydowałem się na plik typowany, ponieważ chcę ograniczyć do minimum instalację aplikacji na drugim komputerze. Zakładam wykorzystanie aplikacji w rodzinie,

Chyba masz mały przegląd tego, co jest w branży dostępne.
"nie instalowanych" rozwiązań jest pewnie z 10.

1

Dziękuję za zainteresowanie i przemiłe komentarze. Dałem sobie radę.

Tutaj zmiana:

 AssignFile(F, 'Rejestr.dat');
  try
    Reset(F);
    for I := 0 to FileSize(F) -1 do
    begin
      Read(F, Rec);
      if (Rec.Kategoria1 = ComboBox1.Text)
      and (Rec.Kategoria2 = ComboBox2.Text)
      and (Rec.Kategoria3 = ComboBox3.Text) then

            begin
             ListItem := Fotolista.Items.Add;
             ListItem.Caption := Rec.Kategoria1;
             ListItem.SubItems.Add(Rec.Kategoria2);
             ListItem.SubItems.Add(Rec.Kategoria3);

A tak poza tematem. Jestem samoukiem od 1991r. Zaczynałem od Clippera, Potem Delphi4. Wszystko bazy danych.
Robię to z ciekawości i dla przyjemności, Jestem "późnym" emerytem, który bawi się w wolnym czasie.
Dziękuję za zainteresowanie i zamykam temat.

1 użytkowników online, w tym zalogowanych: 0, gości: 1