[Deplhi]Porównywanie plików i wydzielanie różnicy.

0

Chciałbym żeby ktoś mnie nakierował lub może wskazał jakieś gotowe funkcję. Mam plik i jego nową wersję, w którym wprowadzone są jakieś zmiany. Teraz chcę je porównać i to co się różni wprowadzić do pliku pierwotnego. Czyli takie patchowanie. Wiem, że jest aplikacja do robienia takich patchy. Ale chciałbym napisać coś takiego sam bo jest to ciekawie. Czy jest to trudne do zrealizowania?

0

Ogolnie jest to cala rodzina algorytmow, ogolnie zwanych jako "diff": im lepiej wydzielajace roznice, tym bardziej skomplikowane. Najczesciej za kryterium jakosci przyjmuje sie stosunek ilosci nowych danych do rozmiaru pliku bazowego: im mniej nowych danych wymaganych do aktualizacji tym lepiej.

Najbardziej popularny algorytm: http://www.mathertel.de/Diff/

0

Na forum ktoś napisał taki kod:

function Porownaj: boolean;
var F1,F2:file;
      buf: array [0..4095] of byte;
      buf2: array [0..4095] of byte;
begin
     AssignFile(F1, 'plika.xyz');
     AssignFile(F2, 'plikb.xyz');
     Reset(F1,1);
     Reset(F2,1);
     Result:=True;
     if FileSize(F1)<>FileSize(F2) then
        begin
            Result:=False;
            Exit;  {jeżeli wielkości są różne, to nie ma sensu pracować, tylko od razu wywalić wynik FALSE}
        end;
     while not EOF(F1) do
      begin
          FillChar(buf,SizeOf(buf),0); {Aby żadne śmiecie nie zostały w razie odczytania <4kB}
          FillChar(buf2,SizeOf(buf2),0); {j.w}
          BlockRead(F1,buf,SizeOf(buf));
          BlockRead(F2,buf2,SizeOf(buf2));
          if buf<>buf2 then begin
             Result:=False;
             Exit; {Porażka, bufory są różne}
          end;
      end;
end;

Kod niby ma porównywać dwa pliki czy są takie same pobierając porcje. Tyle, że ten kto go napisał stwierdził, że nie wie czy działa bo pisał bez kompilatora. No i nie działa bo nie można robić tak

 if buf<>buf2 then begin  

próbowałem to rozwiązać w sposób buf[c]<>buf2[c] c:=c+1

 ale zawsze wywalało mi błąd ze próba odczytu po za plikiem.(dla testu wziąłem dwa identyczne pliki) Może ktoś mi pomóc poprawić ten kod by działał?
0

Poczytałem o tym algorytmie diff ale chyba mi nie o to chodzi. Ja mam dziki plik. JAKIŚ RAW o nie wiadomej zawartości. I mam jego kopie w, której "coś" zmodyfikowało część zawartości. I teraz chcę zamienić ten plik pierwotny w taki jak ta kopia. Chcę wydzielić różnicę i wprowadzić do pliku pierwotnego: Wymyśliłem na swój sposób łopatologicznie skonstruowany algorytm. Jestem początkującym programistą. Nie wiem czy dobrze rozumiem pojęcie bajta i nie wiem czy dobrze rozumiem operacje na plikach w delphi ale wydaje mi się, że to jest możliwe do wykonania.

Te numery z przodu 1,2,3,4... to numery kolejnej porcji. Porcje mają ten sam rozmiar np: bajt, a każdy bajt ma przypisany swoje jak by ID. Plik "STARA_WERSJA.dat" ma ustaloną sumę kontrolną. Jeżeli coś go zmodyfikuje to patch nie zadziała (więc diff mi nie potrzebne). Patchowany plik musi być plikiem o sumie kontrolnej 
pliku pierwotnego "STARA_WERSJA.dat". 

"STARA_WERSJA.dat"

1 10010010010111000110101
2 10001010000111001110101
3 10110010000111000110101
4 10000011111111000110101
5 10000010000111000110101



"NOWA_WERSJA.dat"

1 10010010010111000110101
2 10001010000111001110101
3 10000110000111111110101
4 10000011111111000110101
5 10000010000111000110101


Porównanie:


1 10010010010111000110101 "STARA_WERSJA.dat"
1 10010010010111000110101 "NOWA_WERSJA.dat"
OK

2 10001010000111001110101 "STARA_WERSJA.dat"
2 10001010000111001110101 "NOWA_WERSJA.dat"
OK

3 10110010000111000110101 "STARA_WERSJA.dat"
3 10000110000111111110101 "NOWA_WERSJA.dat" ->>>>>>wysylamy dotrzeciego pliku(PATCH.ptch)--->3 10000010000111000110101
FAIL

4 10000011111111000110101 "STARA_WERSJA.dat"
4 10000011111111000110101 "NOWA_WERSJA.dat"
OK

5 10000010000111000110101 "STARA_WERSJA.dat"
5 10000010000111000110101 "NOWA_WERSJA.dat"
OK


Wynikiem jest plik "PATCH.ptch">

3 10000010000111000110101

A teraz samo patchowanie. Sprawdzenie sumy kontrolnej pliku  "STARA_WERSJA.dat"  by się upewnić, że to na prawde on
i załadowanie pliku:

"STARA_WERSJA.dat"      

1 10010010010111000110101
2 10001010000111001110101
3 10110010000111000110101 <-patchowanie czlyli znalezienie porcji 3 wyciecie i wstawienie-> 3 10000010000111000110101
4 10000011111111000110101
5 10000010000111000110101

Wynik: "SPACZOWANY.dat"

1 10010010010111000110101
2 10001010000111001110101
3 10000010000111000110101 
4 10000011111111000110101
5 10000010000111000110101

           =
      
      "NOWA_WERSJA.dat"
1 10010010010111000110101
2 10001010000111001110101
3 10000110000111111110101
4 10000011111111000110101
5 10000010000111000110101


PATCHOWANIE UDANE!!!!



  
0

Z tego co widze, diff jest dokladnie tym, czego szukasz. Tyle tylko, ze ty robisz tylko porownanie przyrostowe: jesli w pliku oryginalnym o rozmiarze 1023 bajty na poczatku dodano 1 bajt i tak uzyskano plik bazowy, a porownujesz blokami po 4 bajty, wszystkie bloki beda rozne (przesuniete o jeden bajt) i patch bedzie mial minimum (!) 1024 bajty.

Kryterim jakosci:
patch / plik bazowy >= 1024 / 1024 = 1 (czyli najgorszy z mozliwych, bo zamiast patch dostarczasz po prostu nowa wersje)

W przypadku idealnym patch powinien miec minimum owy jeden bajt plus informacje, gdzie go dac, zalezne od algorytmu i jego kryterium jakosci wyniesie:
patch / plik bazowy >= 1/ 1024

Widzisz, po co diff jest przydatny? Aby stwierdzic, ze pliki roznia sie tylko jednym dodanym bajtem, a nie tym, ze na kazdej pozycji jest teraz bajt o innej wartosci.

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