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?
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
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.
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ś.
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?
wez się ogarnij,
http://www.delphibasics.co.uk/RTL.asp?Name=StringReplace
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.
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;
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?
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 ;)
Serdeczne Dzięki za przejrzysty kod, i objasnienie problematyki. Pozdrawiam.
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 ;)