Ładowanie pliku *.pdf do zmiennej.

0

W jaki sposób załadować plik pdf do zmiennej ( dość duży pdf)?
I w jaki sposob na takim duzym stringu znaleźć poszczególne fragmenty?

0

Załadować plik PDF? Jakoś tak:

Var F: File of Byte;
    C: Byte;
    Content: String = '';
Begin
 AssignFile(F, ' pdf.pdf');
 Reset(F);
 Try
  While (not EOF(F)) Do
  Begin
   Read(F, C);
   Content += chr(C);
  End;
 Finally
  CloseFile(F);
 End;
End.

Ale zapewne nie jest to to, czego oczekujesz.


Hint: poszukaj biblioteki do obsługi PDF-ów.

i w jaki sposob na takim duzym stringu znaleŹĆ poszczególne fragmenty

Pos
PosEx
0

Dzięki, tzn z ładowniem to sobie poradziłem wczesniej , ale twój kod szybciej działa a to istotne przy tak dużym pdfie,
mam załadowany plik do memo, i teraz w jaki sposób użyć funkcji Pos , nigdy tego nie uzyałem szczrze mówiąc

<<
/Length 2113
/Filter []
/Type /XObject
/Subtype /Image
/ColorSpace /DeviceRGB
/Width 180
/Height 120
/BitsPerComponent 8
/Name /823712
>>

Założmy że potrzebuje wyszukać taki fragment , a następnie podmienic na

<<
/Length 2113
/Filter []
/Type /XObject
/Subtype /Image
/ColorSpace /DeviceRGB
/Width 56
/Height 90
/BitsPerComponent 8
/Name /823712
>>

Szczerze byłbym bardzo wdzięczny za jakies objasnienie bo już siedze nadtym zagdanieniem dość długo.

0

Wygląda na to że tak skomplikowane zagadnienia jak podmiana substringów w stringach znajdziesz w najbliższym kursie delphi, z którego na pewno korzystałeś.

0

Na razie staneło na takiej procedurze aczkolwiek wydaje sie ze nie wszystko zostało załadowane, czy Memo ma ograniczoną pojemność? jezeli tak w to w co można wczytać TStringlist?

// na codzien nie korzystam z tego języka i środowiska.

procedure TForm1.FormCreate(Sender: TObject);
var
Lst:TStringList;
begin
  Lst:=TStringList.Create;
  try
    Lst.Capacity:=128*1024;
    Lst.LoadFromFile('plik.pdf');
    Memo4.Lines.Assign(Lst);
  finally
    Lst.Free;
  end;
end;

Można prosić o pomoc?
Wczytuje 20mb plik do TStringList
następnie przepisuje do String'a(nie jestem pewien czy cały plik mieści się w stringu,tstringliscie)

dane:= data.CommaText;
procedure szukaj1;
begin
  if Pos(tekst1, dane) > 0 then
  begin
//procedura podmiany
    end;
end;

tekst1:='Width 120';

potrzebuje podmienic na

ptekst1:='123456';

Jest kilka pozycji w całym pliku o wartości tekst1. próowałem z tym pos ale własciwie nie wiem co dalej z podmianą ReplaceString?

0
  tekst1:='Width 120';
  tekst2:='12345678';
 str:=LoadFile('plik.pdf');
 Str := StringReplace(Str, tekst1, tekst2, [rfReplaceAll]);
SaveFile('plik.pdf',Str);



 procedure SaveFile(const FileName: TFileName; const content: string);
begin
  with TFileStream.Create(FileName, fmCreate) do
    try
      Write(Pointer(content)^, Length(content));
    finally
      Free;
    end;
end;

function LoadFile(const FileName: TFileName): string;
begin
  with TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite) do 
  begin
    try
      SetLength(Result, Size);
      Read(Pointer(Result)^, Size);
    except
      Result := ''; 
      Free;
      raise;
    end;
    Free;
  end;
end;

Niestety nic sie nie dzieje, 0% uzycia cpu dla tego procesu.

0

Dobra - prim@ @prilis był wczoraj. Od teraz napisz na poważnie co Ty ćwiczysz i co chcesz osiągnąć. Bo póki co to ja widzę dialog wewnętrzny, jak jednego zdolnego artykuł makera tutaj i jedno wielkie... WTF :/ Mogę tylko dodać, że TStringList raczej 20 MB plik pomieści. Tylko o ile ja się orientuje, jeżeli podmienisz zawartość pdf'a zmieniając jeden string na dłuższy/krótszy to pewnie go uszkodzisz. Do prawidłowej modyfikacji pdf'ów za pewne trzeba użyć zewnętrznych bibliotek lub kontrolek OCX. A zapis i odczyt pliku do zmiennej typu string najprościej zrobić w WinAPI imo tak:

function ReadTextFromFile(AFileName : string; var OutStr : string) : boolean;
var
  BytesRead : DWORD;
  SrcFile : THandle;
  SrcFileSize : Int64;
begin
  OutStr := '';
  SrcFile := CreateFile(PChar(AFileName), GENERIC_READ,
    FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  Result := SrcFile <> INVALID_HANDLE_VALUE;
  if Result then
  begin
    SrcFileSize := GetFileSize(SrcFile, nil);
    SetLength(OutStr, SrcFileSize);
    ReadFile(SrcFile, OutStr[1], SrcFileSize, BytesRead, nil);
    CloseHandle(SrcFile);
  end;
end;

function SaveTextToFile(AFileName : string; InStr : string) : boolean;
var
  OutFile : THandle;
  BytesWritten : DWORD;
  OutFileSize : integer;
begin
  OutFile := CreateFile(PChar(AFileName), GENERIC_WRITE,
    FILE_SHARE_READ, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  Result := OutFile <> INVALID_HANDLE_VALUE;
  if Result then
  begin
    OutFileSize := Length(InStr);
    WriteFile(OutFile, InStr[1], OutFileSize, BytesWritten, nil);
    CloseHandle(OutFile);
  end;
end;
0

Tzn Funkcja nic nie zmienia w pliku, plik zostaje przekopiowany po prostu.

Odczyt i zapis akurat działa. A co do edycji to windowsowy notepad potrafi zedytować bez problemu i pdf działa, ta funkcja podmiany, po prostu nic nie robi, jest ale nie wykonuje tego co ma wykonać. Jest jakis inny sposób podmiany wyznaczonego tekstu?

0

Bo tak działa oryginalna funkcja StringReplace przynajmniej w modułe VCL SysUtils w Delphi 7. Prawopodobnie przez napotkanie znaków #0 ucinany jest string i funkcja głupieje. Zgaduje, że to przez użycia w jej "ciele" funkcji AnsiPos, zamiast Pos. Ale mogę się mylić. Domyślać mi się nie chce ani bawić w detektywa. Poniższy kod działa. Także powtórzę za tytułem projektu, który na szybko stworzyłem - WinAPI rulez ;P Ale wiadomo, każdy pisze, jak mu wygodnie.

program winapi_rulez;

{$APPTYPE CONSOLE}

uses
  Windows;

type
  TReplaceFlags = set of (rfReplaceAll, rfIgnoreCase);

function AnsiUpperCase(const S : string) : string;
var
  Len : integer;
begin
  Len := Length(S);
  SetString(Result, PChar(S), Len);
  if Len > 0 then
  begin
    CharUpperBuff(Pointer(Result), Len);
  end;
end;

function StringReplace(const S, OldPattern, NewPattern : string; Flags : TReplaceFlags) : string;
var
  SearchStr, Patt, NewStr : string;
  Offset : integer;
begin
  if rfIgnoreCase in Flags then
  begin
    SearchStr := AnsiUpperCase(S);
    Patt := AnsiUpperCase(OldPattern);
  end
  else
  begin
    SearchStr := S;
    Patt := OldPattern;
  end;
  NewStr := S;
  Result := '';
  while SearchStr <> '' do
  begin
    Offset := Pos(Patt, SearchStr);
    if Offset = 0 then
    begin
      Result := Result + NewStr;
      Break;
    end;
    Result := Result + Copy(NewStr, 1, Offset - 1) + NewPattern;
    NewStr := Copy(NewStr, Offset + Length(OldPattern), MaxInt);
    if not (rfReplaceAll in Flags) then
    begin
      Result := Result + NewStr;
      Break;
    end;
    SearchStr := Copy(SearchStr, Offset + Length(Patt), MaxInt);
  end;
end;

function ReadTextFromFile(AFileName : string; var OutStr : string) : boolean;
var
  BytesRead : DWORD;
  SrcFile : THandle;
  SrcFileSize : Int64;
begin
  OutStr := '';
  SrcFile := CreateFile(PChar(AFileName), GENERIC_READ,
    FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  Result := SrcFile <> INVALID_HANDLE_VALUE;
  if Result then
  begin
    SrcFileSize := GetFileSize(SrcFile, nil);
    SetLength(OutStr, SrcFileSize);
    ReadFile(SrcFile, OutStr[1], SrcFileSize, BytesRead, nil);
    CloseHandle(SrcFile);
  end;
end;

function SaveTextToFile(AFileName : string; InStr : string) : boolean;
var
  OutFile : THandle;
  BytesWritten : DWORD;
  OutFileSize : integer;
begin
  OutFile := CreateFile(PChar(AFileName), GENERIC_WRITE,
    FILE_SHARE_READ, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  Result := OutFile <> INVALID_HANDLE_VALUE;
  if Result then
  begin
    OutFileSize := Length(InStr);
    WriteFile(OutFile, InStr[1], OutFileSize, BytesWritten, nil);
    CloseHandle(OutFile);
  end;
end;

var
  Str : string;
begin
  if ReadTextFromFile('D:\test.pdf', Str) then
  begin
    Str := StringReplace(Str, 'AvgWidth 479', 'Think before you ask!', []);
    SaveTextToFile('D:\test2.pdf', Str);
  end;
end.

EDIT: a tak na poważnie. StringReplace, to jak nazwa wkazuje funkcja raczej do stringów, a plik pdf typowym stringiem nie jest, bo zawiera znaki nie będące możłiwymi do wpisania w łatwy sposób z klawiatury. Zresztą pojęcia "null terminated string" nie istnieje sobie od tak, dla jaj. Takie rzeczy jak zamiana w plikach trzeba właśnie dokonywać raczej z użyciem funkcji Read/Write File, ponieważ klasa TstringList może zachować się rownież w sposób cięzki do przewidzenia przy takim nietypowym pliku. Gdzie tymbardziej jak dla niej, moga wystąpić na przykład "mieszane" znaki kóńca linii i własnie te #0 czyli null terminated.

Ale kto wie, może trzeba migrować do TP 7.0. Niektóre uczelnie - nawet wyższe tak pewnie robiły i robić będą. My tak robimy jeśli chodzi o oprogramowanie serwera 4p (info w dziale Coyote), na przykład mydevil.net = jak tam wspomniałem = migruje z FreeBSD do Ubunutu. Także może w tym jest metoda - kto wie ;)

0

Serdeczne Dzięki za przejrzysty kod, i objasnienie problematyki. Pozdrawiam.

0

Proszę bardzo. Mogłem to pomogłem, jak to ja :) Na przyszłość jednak polecam założyć sobie tutaj konto, zawsze będziesz mogł wedytować swoje posty, bo troszkę w tym wątku panuje "lekki chaos". Ale już nic nie modyfikuje. Sorry, ale początkowo myślałem, że tymi wklejeniami ktoś sobie robił żarty ;)

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