Kodowanie i dekodowanie łańcuchów i plików tekstowych

0

Dysponuję Delphi RAD Studio 12 i pracuję z Windows 11.
Moje problemy związane są z kodowaniem i dekodowaniem łańcuchów i plików tekstowych.
W wyniku kodowania obiektu i jego dekodowania do innego obiektu powinienem otrzymać
identyczne pliki/łańcuchy, a tak nie jest. Nie mogę ustalić dlaczego tak się dzieje. Proszę o pomoc.
Obiektem kodowania jest plik direk.txt wygenerowany poprzez komendę dir>direk.txt dla możliwie dużego katalogu. W załączeniu podaję stosowne oprogramowanie.W nazwach plików.należy usunąć rozszerzenia .txt
Marek Detka

unit SezamMD2;

interface

uses
  System.SysUtils;

const
  CodeKey:array[1..5] of Byte=(2,3,5,7,11);

Function EncodeStr(S:String):String;
  (* Zwraca zakodowany ³añcuch S *)
{***************************************************************************}
Function DecodeStr(S:String):String;
  (* Zwraca odkodowany ³añcuch S *)
{***************************************************************************}
Procedure EncodeFile(Src,Dest:String);
  (* Tworzy zakodowany zbiór Dest *)
{***************************************************************************}
Procedure DecodeFile(Src,Dest:String);
   (* Tworzy odkodowany zbior Dest *)
{***************************************************************************}

implementation

{***************************************************************************}
Function EncodeStr(S:String):String;
var
  I,J:Word;
  Pom:String;
Begin
 if S='' then begin
    Result:='';
    Exit;
 end;
  Pom:='';
  J:=1;
  for I:=1 to Length(S) do begin
    Pom:=Pom+Chr(Ord(S[I])+CodeKey[J]);
    Inc(J);
    if J>5 then
      J:=1;
  end;{of for}
  Result:=Pom;
End;{of EncodeStr}
{***************************************************************************}
Function DecodeStr(S:String):String;
var
  I,J:Word;
  Pom:String;
Begin
  if S='' then begin
    Result:='';
    Exit;
  end;
  Pom:='';
  J:=1;
  for I:=1 to Length(S) do begin
    Pom:=Pom+Chr(Ord(S[I])-CodeKey[J]);
    Inc(J);
    if J>5 then
      J:=1;
  end;
  Result:=Pom;
End;{of DecodeStr}
{***************************************************************************}
Procedure EncodeFile(Src,Dest:String);
var
  We,Wy:TextFile;
  Linia:String;
Begin
  if not FileExists(Src) then begin
    Writeln('W bie¿¹cym katalogu brak jest zbioru '+Src,'');
    Writeln('Nacisnij klawisz ENTER');
    Readln;
    Writeln('OK');
    Sleep(1500);
    Exit;
  end;
  AssignFile(We,Src);
  Reset(We);
  AssignFile(Wy,Dest);
  Rewrite(Wy);
  while not Eof(we) do begin
    Readln(We,Linia);
    if Linia=''  then
      Writeln(Wy,Linia)
    else
      Writeln(Wy,EncodeStr(Linia));
  end;
  CloseFile(We);
  CloseFile(Wy);
End;{of CodeFile}
{***************************************************************************}
Procedure DecodeFile(Src,Dest:String);
var
  We,Wy:TextFile;
  Linia:String;
Begin
  if not FileExists(Src) then begin
    Writeln('W bie¿¹cym katalogu brak jest zbioru '+Src,'');
    Writeln('Nacisnij klawisz ENTER');
    Readln;
    Writeln('OK');
    Sleep(1500);
    Exit;
  end;
  AssignFile(We,Src);
  Reset(We);
  AssignFile(Wy,Dest);
  Rewrite(Wy);
  while not Eof(we) do begin
    Readln(We,Linia);
    Writeln(Wy,DecodeStr(Linia));
  end;
  CloseFile(We);
  CloseFile(Wy);
End;{of DecodeFile}
{***************************************************************************}
END.

(https://4programmers.net/assets/63052/pCJqQN8cK3Q0jsnMnktooUbsHp8ztulKScN19rjU.txt)SezamMD2.pas.txt

1

Czy możesz zrobić przykład minimałny z kodowaniem i dekodowaniem łańcucha (nie plika) - żeby było widoczne jakij text został zakodowan, jakij jest zakodowany wynik, jakij jest złamany wynik dekodowania. Przepraszem, ale nie wszyscy z nas mają delphi pod ręką.

Pom:=Pom+Chr(Ord(S[I])+CodeKey[J]);
    Inc(J);
    if J>5 then
      J:=1;
  end;{of for}

musisz wziąc modulo od ord(...) + codekey[...]

  Pom:String;

string jest typ który załęży od ustawień kompilatora
chyba zmień go na coś konkretnego (ansistring?)

5

Zapewne problem w kodowaniu znaków. Musisz określić kodowanie np. UTF-8 czyli:

AssignFile(We, Src, TEncoding.UTF8.CodePage); //65001 - można na sztywno podać ale tak przynajmniej wiadomo o chodzi...

Poza tym cały ten kod można by znacznie skrócić ponieważ funkcje są do siebie bardzo podobne, wystarczy tylko zmienić ich działanie (kodowanie, dekodowanie) przekazując odpowiednią wartość jako parametr:

//AInputStr - tekst wejsciowy
//AEndode - True - kodowanie; False - dekodowanie
//zwraca kodowany lub dekodowany tekst
function CodeStr(AInputStr: string; AEndode: Boolean = True): string;
const
  CODE_KEY: array[1..5] of Byte = (2, 3, 5, 7, 11);
var
  i, j: Integer;
Begin
  result:= '';
  j:= Low(CODE_KEY);
  for i:= 1 to Length(AInputStr) do 
  begin
    if (AEndode) then
      result:= result + Chr(Ord(AInputStr[i]) + CODE_KEY[j])
    else
      result:= result + Chr(Ord(AInputStr[i]) - CODE_KEY[j]);
    Inc(j);
    if (j > High(CODE_KEY)) then
      j:= Low(CODE_KEY);
  end;
end;

//AInFileName - nazwa pliku wejściowego
//AOutFileName - nazwa pliku wyjściowego 
//AEndode - True - kodowanie; False - dekodowanie
procedure CodeFile(AInFileName, AOutFileName: string; AEndode: Boolean = True);
var
  fileIn, fileOut: TextFile;
  sLine: string;
begin
  if (not FileExists(AInFileName)) then
  begin
    Writeln('W bieżącym katalogu brak jest zbioru ' +  AInFileName);
    Writeln('Nacisnij klawisz ENTER');
    Readln;
    Writeln('OK');
    Sleep(1500);
    Exit();
  end;
  AssignFile(fileIn, AInFileName, TEncoding.UTF8.CodePage);
  Reset(fileIn);
  AssignFile(fileOut, AOutFileName, TEncoding.UTF8.CodePage);
  Rewrite(fileOut);  
  while not Eof(fileIn) do 
  begin
    Readln(fileIn, sLine);
    Writeln(fileOut, CodeStr(sLine, AEndode));
  end;
  CloseFile(fileOut);
  CloseFile(fileIn);  
end;
3
AssignFile(We,Src,CP_UTF8); 
AssignFile(Wy,Dest,CP_UTF8);

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.