Zapis tablicy z elementami heksadecymalnymi do pliku

0

Witam, mam mały problem, aby zapisać tablicę to pliku z rozszerzeniem .bin.
Tyle, że problemem nie jest sam zapis, czy odczyt tej tablicy za pomocą samego delphi, ale za pośrednictwem innego programu.
np. przy użyciu Total Commander, odczytując zapisany plik i zmieniając na odczyt Heksadecymalny, wyświetla mi się około 3000 linijek (gdzie powinno być ich 217).
Więc pytanie/prośba do was, czy da się coś z tym zrobić?

 

program dzielenie;

{$APPTYPE CONSOLE}
uses
SysUtils;

var
F: File of byte;
a,b,x,i,wynik:integer;
tab:array[0..217] of string;



//PROGRAM GLOWNY//
begin
x:=0;
  for a:=0 to 63 do                       //max wartosc 6bitowa
      for b:= 1 to 15 do                  //max wartosc 4bitowa, brak dzielenia przez 0
        begin
          if (a mod b) = 0 then           //tylko dla tych, ktore dziela sie bez reszty
              begin
                wynik:=(a div b);
                tab[x]:= pchar(inttohex(wynik, 6));  //przypisywanie do tablicy wyniku dzielenia
                x:=x+1;
              end;
        end;

//ZAPIS DO PLIKU//
          AssignFile(F, 'plik.bin');
          Rewrite(F);
          for x := Low(Tab) to High(Tab) do
            BlockWrite(F, Tab[x], SizeOf(Tab));
          CloseFile(F);


//ODCZYT I WYSWIETLENIE PLIKU//
  AssignFile(F, 'plik.bin');
  Reset(F);
  for I := Low(Tab) to High(Tab) do
    begin
      BlockRead(F, Tab[I], SizeOf(Tab));
      writeln(tab[I]);
    end;
    CloseFile(F);
    readln;

end.

1

Błąd jest w tych linijkach:

BlockWrite(F, Tab[x], SizeOf(Tab));
BlockRead(F, Tab[I], SizeOf(Tab));

Tablica Tab posiada łańcuchy, których długości nie możesz odczytywać za pomocą funkcji SizeOf; Zamień tę funkcję na Length przy zapisie, a przy odczycie podawaj sztywne 6 znaków, a nie SizeOf(Tab); A najlepiej to zadeklaruj sobie stałą, przechowującą ilość znaków przypadających na pojedynczą liczbę (u Ciebie jest to 6) i używaj jej zarówno podczas zapisy, jak i odczytu;

BTW: SizeOf(Tab) to rozmiar całej tablicy, a nie pojedynczego itema; Rozmiar pojedynczego elementu to SizeOf(Tab[Index]), który i tak zwróci rozmiar pointera na łańcuch (np. 4 liczone w bajtach), a nie długość łańcucha;

Poza tym nie wiem po jaką cholerę Ci liczby heksadecymalne w pliku binarnym... Po to stosuje się pliki binarne, aby ukryć strukturę danych w nich zapisanych; Co innego, gdybyś te liczby trzymał w pliku tekstowym (np. INI czy XML), to wtedy konwersja i dekonwersja jest konieczna; A tak to tylko utrudniasz sobie robotę i marnujesz czas procesora na konwertowanie liczb i łańcuchów; Lepiej by było trzymać w pamięci i w pliku normalne liczby, a jedynie przy ich wyświetlaniu konwertować na szesnastkowe.

0

Dzięki za pomoc.

Wywaliłem te funkcji SizeOf i length, wstawiłem samą cyfrę 6 (gdy przy zapisie użyłem funkcji

Lenght

., oraz przy odczycie 6, to wywalało mi konsole, jedynie dla takich samych wartości szło dalej).
Wstawiłem również funkcje do konwertowania wyniku na zapis binarny (bez zapisu hexa).

Tylko dalej nie jestem pewien, czy na pewno ten zapis do pliku jest poprawny (w takim sensie, że teraz, przy użyciu TCommandera wyskakuje mi 51 wierszy).

EDIT///
Zapisując dziesiętne wygląda to w pliku o wiele lepiej. Zapisując binarnie, mija się to z celem.

program dzielenie;

{$APPTYPE CONSOLE}
uses
SysUtils;

var
F: File of byte;
a,b,x,i,wynik: integer;
tab:array[0..217] of string;
const po2:array[0..5] of byte=(1,2,4,8,16,32);
bin:array[false..true] of char='01';

///FUNKCJA INT TO BIN////
function inttobin(by:byte):string;
var s:string;
i:byte;
begin
s:='';
for i:=5 downto 0 do
  s:=s+bin[(po2[i] and by=po2[i])];
  inttobin:=s;
end;


//PROGRAM GLOWNY//
begin
x:=0;
  for a:=0 to 63 do
      for b:= 1 to 15 do
        begin
          if (a mod b) = 0 then
              begin
                wynik:=(a div b);
                tab[x]:= inttobin(wynik);
                x:=x+1;
              end;
        end;

//ZAPIS DO PLIKU//
          AssignFile(F, 'plik.bin');
          Rewrite(F);
          for x := Low(Tab) to High(Tab) do
            BlockWrite(F, Tab[x], 6);
          CloseFile(F);

//ODCZYT I WYSWIETLENIE PLIKU//
  AssignFile(F, 'plik.bin');
  Reset(F);
  for  x:= Low(Tab) to High(Tab) do
    begin
      BlockRead(F, Tab[x], 6);
      writeln(tab[x]);
    end;
    CloseFile(F);
    readln;

end.

 
0

Jak na razie co chcesz osiągać pozostaje dla mnie tajemnicą?
Chcesz mieć plik tekstowy?
Zliczasz ile znalazłeś tych liczb, po czym wywalasz tą wartość w błoto i zapisujesz wszystkie 217 przewidzianych wartości?
Nic nie rozumiem, ani z kodu ani z opisu.

1

Tylko dalej nie jestem pewien, czy na pewno ten zapis do pliku jest poprawny (w takim sensie, że teraz, przy użyciu TCommandera wyskakuje mi 51 wierszy).

A powiedz - od kiedy rozmiar plików binarnych wyraża się w liniach? Pliki tekstowe można opisywać ilością linii, ale to i tak marna miara, bo linie mogą mieć dowolną (teoretycznie) długość;

Jeżeli chcesz wiedzieć, czy Twój algorytm działa właściwie, to oblicz sobie ile bajtów danych powinno być zapisane do pliku, po czym odpal program, zakończ go i sprawdź w HexEdytorze lub nawet w oknie eksploratora faktyczny rozmiar zapisanych danych; Wtedy będziesz wiedział, czy ilość danych zapisanych do pliku jest prawidłowa, czy coś przy zapisie poszło nie tak jak trzeba;

Przy zapisie dziesiętnym (bez inttobin) zapis w pliku bin wydaję się być na oko poprawny, jednak, czy da się zapisać ale binarnie do pliku? Gdzieś na jakimś forum przeczytałem, że w delphi nie idzie zapisać binarnie do pliku.

Co to znaczy "zapisać binarne dane do pliku" w Twoim rozumieniu? Wszystkie dane zapisywane do plików dyskowych to dane binarne, bez względu na format - odróżnia je jedynie sposób interpretacji przez aplikacje;

Chyba że masz na myśli zestaw funkcji konwertujących liczby na łańcuchy znaków w binarnej reprezentacji - są takie funkcje w bibliotece standardowej FPC, ale nie wiem jak w Delphi; W kazdym razie Delphi7 takich funkcji nie posiada.

0
_13th_Dragon napisał(a):

Jak na razie co chcesz osiągać pozostaje dla mnie tajemnicą?
Chcesz mieć plik tekstowy?
Zliczasz ile znalazłeś tych liczb, po czym wywalasz tą wartość w błoto i zapisujesz wszystkie 217 przewidzianych wartości?
Nic nie rozumiem, ani z kodu ani z opisu.

  1. Zapisać wynik dzielenia liczb 6bitowych/4bitowe(tylko te które, dzielą się bez reszty) w pliku z rozszerzeniem *.bin
  2. Do pliku textowego zapisuję mi tak, jak wyświetla mi wynik w konsoli (czyli poprawnie), jednak nie dla pliku *.bin (mam tu na myśli, zapis gdy wynik jest w postaci binarnej)
  3. Writeln(high(tab)) zwróciło mi wartość, ilu elementowa jest tablica, czyli ile mam tych elementów tablicy z wynikami.
0

Co to znaczy "zapisać binarne dane do pliku" w Twoim rozumieniu? Wszystkie dane zapisywane do plików dyskowych to dane binarne, bez względu na format - odróżnia je jedynie sposób interpretacji przez aplikacje;

Miałem na myśli, że wynik jest w postaci binarnej.

Chyba że masz na myśli zestaw funkcji konwertujących liczby na łańcuchy znaków w binarnej reprezentacji - są takie funkcje w bibliotece standardowej FPC, ale nie wiem jak w Delphi; W kazdym razie Delphi7 takich funkcji nie posiada.

Akurat mam 7;/

1

Ad 1. Z powtórzeniami czy bez? Do pliku z rozszerzeniem bin da się wpisać cokolwiek poczynając od tekstu tego posta po program wykonywalny, w jakim formacie chcesz zapisać?
Ad 2. Pliki bin przeważnie trzeba odczytywać za pomocą HexEdytorów, w jaki sposób próbujesz to odczytywać?
Ad 3. Writeln(high(tab)) - wypisze ci dokładnie to co podałeś tu: tab:array[0..217] of string; po dwóch kropkach.

Wydaje mi się ze próbujesz wymodzić to:

program dzielenie;
 
{$APPTYPE CONSOLE}
uses SysUtils;
 
var F:File of byte;
var a,b,x:integer;
var tab:array[0..64*16] of byte;
begin
  x:=0;
  for a:=0 to 63 do
  begin
    for b:= 1 to 15 do
    begin
      if (a mod b)=0 then
      begin
        tab[x]:=(a div b);
        Inc(x);
      end;
    end;
  end;
 
  AssignFile(F, 'plik.bin');
  Rewrite(F);
  BlockWrite(F,tab[0],x);
  CloseFile(F);
  for a:=0 to x-1 do Write(tab[a],' ');
  WriteLn;
  for a:=0 to High(tab) do tab[a]:=0;
 
  AssignFile(F, 'plik.bin');
  Reset(F);
  BlockRead(F,tab[0],Length(tab),x);
  CloseFile(F);

  for a:=0 to x-1 do Write(tab[a],' ');
  WriteLn;
  ReadLn;
end.
0

Chyba że masz na myśli zestaw funkcji konwertujących liczby na łańcuchy znaków w binarnej reprezentacji - są takie funkcje w bibliotece standardowej FPC, ale nie wiem jak w Delphi; W kazdym razie Delphi7 takich funkcji nie posiada.

Akurat mam 7;/

No to trzeba sobie takie funkcje napisać :]

function ByteToBin(const AValue: Byte): AnsiString;
var
  intToken: Byte;
begin
  SetLength(Result, 8);

  for intToken := 0 to 7 do
    Result[8 - intToken] := Chr((AValue shr intToken) and 1 + 48);
end;

function BinToByte(const AValue: AnsiString): Byte;
var
  intToken: Byte;
begin
  Result := 0;

  for intToken := 8 downto 1 do
    if AValue[intToken] = '1' then
      Inc(Result, 1 shl (8 - intToken));
end;

To przykład dla konwersji pojedynczego bajtu - dla większych liczb (wielobajtowych) będzie analogicznie; Ale spróbuj coś sam wymodzić - tu masz zalążek takich funkcji konwertujących.

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