Using TIdCompressorLib to Decompress gzip file - delphi

I am using Delphi 2007 with Indy 10. I have a gzip file. I have verified it can be decompressed with this Online Decompression Tool.
I am trying to use the TIdCompressorZlib component to decompress using Delphi. Here is my code:
procedure TForm2.Button9Click(Sender: TObject);
var
lCompressor : TIdCompressorZLib;
FileStream : TFileStream;
memorystream: TMemoryStream;
begin
lCompressor := TIdCompressorZLib.create(self);
FileStream := TFileStream.Create('c:\temp\test.gz', fmOpenRead);
filestream.position := 0;
memorystream:= TMemoryStream.create;
memorystream.position := 0;
lcompressor.DecompressGZipStream(FileStream,MemoryStream);
filestream.free;
showmessage('done');
end;
I cannot get it to work. If I pass fmOpenReadWrite in the constructor I get a zlib error (-5) when DecompressGZipStream is called.
If I pass fmOpenRead in the constructor I get a OS System Error Code 5 Access Denied when DecompressGZipStream is called.
Update David Hefferan suggested it is a file reading issue. So I am zeroing in on that. I am able to copy the file using this procedure:
Procedure FileCopy( Const sourcefilename, targetfilename: String );
Var
S, T: TFileStream;
Begin
S := TFileStream.Create( sourcefilename, fmOpenRead );
try
T := TFileStream.Create( targetfilename,
fmOpenWrite or fmCreate );
try
T.CopyFrom(S, S.Size ) ;
finally
T.Free;
end;
finally
S.Free;
end;
showmessage('done');
End;
UPD Per David Heffernan, I have verified I can Read the data. I successfully ran the file through the following function. It returns the proper number of characters (bytes):
function GetTextFromFile(AFile: string; var Returnstring: string): Boolean;
var
FileStream: TFileStream;
begin
Result := False;
if not FileExists(AFile) then Exit;
FileStream := TFileStream.Create(AFile, fmOpenRead);
try
if FileStream.Size <> 0 then
begin
SetLength(Returnstring, FileStream.Size);
FileStream.Read(Returnstring[1], FileStream.Size);
Result := True;
end;
finally
FileStream.Free;
end;
end;

You can try to use Delphi zlib unit to decompress gzip.
Sample code:
procedure TForm2.Button9Click(Sender: TObject);
var
DecompressionStream : TDecompressionStream;
FileStream : TFileStream;
dest: TFileStream;
byteCount: Integer;
buffer: array [0..65535] of Byte;
begin
FileStream := TFileStream.Create('c:\temp\test.gz', fmOpenRead);
try
//no need to set FileStream position to 0, it's there already
DecompressionStream:=TDecompressionStream.Create(FileStream, 15+16);
//16 is flag that gzip stream used, not zlib.
//15 is maximum memory usage, to speed-up decompression.
try
dest:=TFileStream.Create('c:\temp\test.txt', fmCreate);
try
dest.CopyFrom(DecompressionStream,0);
finally
dest.free;
end;
finally
DecompressionStream.free;
end;
finally
filestream.free;
end;
showmessage('done');
end;
UPD: this code doesn't work for D2007 or earlier versions, no overloaded constructor with WindowBits argument...

Related

Using TIdHTTP to download file using multiple threads [duplicate]

I have two binary files (suppose, this is a ZIP-file previously sliced into 2 parts). How do I can combine them into a single file? More precisely, add the second file to the first one.
UPDATE: Guys, thanks to everyone who responded me, but it's not exactly what I need. Basically, I need an analogue of the shell command: "copy /b file.000+file.001+file.002 file.bin"
Like this:
var
InStream, OutStream: TFileStream;
....
OutStream := TFileStream.Create(OutFileName, fmCreate);
try
InStream := TFileStream.Create(InFileName1, fmOpenRead);
try
OutStream.CopyFrom(InStream, InStream.Size);
finally
InStream.Free;
end;
InStream := TFileStream.Create(InFileName2, fmOpenRead);
try
OutStream.CopyFrom(InStream, InStream.Size);
finally
InStream.Free;
end;
finally
OutStream.Free;
end;
Or more generally to concatenate multiple files:
procedure ConcatenateFiles(const InFileNames: array of string;
const OutFileName: string);
var
i: Integer;
InStream, OutStream: TFileStream;
begin
OutStream := TFileStream.Create(OutFileName, fmCreate);
try
for i := 0 to high(InFileNames) do
begin
InStream := TFileStream.Create(InFileNames[i], fmOpenRead);
try
OutStream.CopyFrom(InStream, InStream.Size);
finally
InStream.Free;
end;
end;
finally
OutStream.Free;
end;
end;
Call it like this:
ConcatenateFiles(['Part1', 'Part2'], 'Outfile.zip')

How to get the pointer position of beginning of second line using TFileStream in Delphi?

I'm trying to create a list of pointers to store pointers of beginning of each line using TFileStream in Delphi.
I have gone through the following link TFileStream_Methods to check all the methods. but i didn't find anything useful using which i can find the pointer value of starting position of each line.
I have tried following :
procedure TForm4.Button3Click(Sender: TObject);
var
InStream: TFileStream;
OutStream: TMemoryStream;
Writer: TStreamWriter;
Buffer: TArray<Byte>;
Encoding: TEncoding;
BOMValue: Integer;
FileName: string;
Temp: string;
TempInt: Integer;
//Buffer2: Buffer;
begin
try
//SetLength(Buffer, 8);
//InStream.Read(Buffer, Length(Buffer));
finally
//InStream.Free;
end;
try
SetLength(Buffer, 8);
//InStream.Read(Buffer, Length(Buffer));
finally
//InStream.Free;
end;
Encoding := nil;
BOMValue := TEncoding.GetBufferEncoding(Buffer, Encoding, TEncoding.ASCII);
OutStream := TMemoryStream.Create;
Writer := TStreamWriter.Create(OutStream, Encoding);
FileName := 'C:\bugs\Rnd\mainfile.cpp';
try
InStream := TFileStream.Create(FileName, fmOpenRead);
InStream.Seek(BOMValue, soCurrent);
Temp := InStream.ToString();
TempInt := InStream.InstanceSize();
OutStream.CopyFrom(InStream, 10);
InStream.Seek(10, soCurrent);
Writer.Write('abc');
OutStream.CopyFrom(InStream,60);
InStream.Free;
OutStream.SaveToFile(FileName);
finally
//InStream.Free;
Writer.Free;
OutStream.Free;
end;
end;
I am having the InStream, how can I read it character by character (even multibyte character) and can calculate the pointer of the first position of each line.
I have been trying for past 2 days but didn't have any luck. Any help would he highly appreciated.

How to get image binary data using XMLHTTPRequest in Delphi

I need to access binary image data using XMLHttpRequest in Delphi. I am using the following code but its not working, could someone please tell me what's wrong with this code, thanks in advance.
//I am using this function to get Image Binary data into Memory Stream.
procedure SendGETRequest(p_Url: string; p_resStream: TMemoryStream);
begin
FXmlHttpReq.open(METHOD_GET, p_Url, false, FUsername, FPassword);
FXmlHttpReq.setRequestHeader(HTTP_AUTHENTICATION, HTTP_BASIC + EncodeBase64(
FUsername + ':'+FPassword));
FXmlHttpReq.setRequestHeader(HTTP_CACHE_CONTROL, HTTP_NO_CACHE);
//FXmlHttpReq.setRequestHeader('Content-type','application/octet-stream');
FXmlHttpReq.send('');
if not VarIsEmpty(FXmlHttpReq.responseBody) then
begin
p_resStream:= OleVariantToMemoryStream(FXmlHttpReq.responseStream);
end;//if...
end;
function OleVariantToMemoryStream(OV: OleVariant): TMemoryStream;
var
Data: PByteArray;
Size: integer;
begin
Result := TMemoryStream.Create;
try
Size := VarArrayHighBound (OV, 1) - VarArrayLowBound(OV, 1) + 1;
Data := VarArrayLock(OV);
try
Result.Position := 0;
Result.WriteBuffer(Data^, Size);
finally
VarArrayUnlock(OV);
end;
except
Result.Free;
Result := nil;
end;
end;
responseStream is IStream. You need to convert it using TOleStream (AxCtrls):
uses AxCtrls, ComObj, ActiveX;
procedure TForm1.Button1Click(Sender: TObject);
var
oXMLHTTP: OleVariant;
MemoryStream: TMemoryStream;
Stream: IStream;
OleStream: TOleStream;
begin
oXMLHTTP := CreateOleObject('MSXML2.XMLHTTP.3.0');
oXMLHTTP.open('GET', 'https://www.google.com/images/srpr/logo11w.png', False);
oXMLHTTP.send(EmptyParam);
Stream := IUnknown(oXMLHTTP.ResponseStream) as IStream;
OleStream := TOleStream.Create(Stream);
try
OleStream.Position := 0;
MemoryStream := TMemoryStream.Create;
try
MemoryStream.CopyFrom(OleStream, OleStream.Size);
MemoryStream.SaveToFile('logo11w.png');
finally
MemoryStream.Free;
end;
finally
OleStream.Free;
end;
end;

What is the equivalent of this construct in Delphi 2007 downward?

In Delphi XE:
function ReadConfig(TextReader: TTextReader): string;
begin
try
Result := TextReader.ReadToEnd;
finally
TextReader.Free;
end;
end.
Typical use:
var
s: string;
...
s := ReadConfig(TStreamReader.Create('MySetting.cf'));
Question:
What is the equivalent construct in Delphi 2007 downward.
Assuming you are asking about reading a file:
var
fils: TFileStream;
stri: TStringStream;
begin
fils := TFileStream.Create(sFileName, fmOpenRead or fmShareDenyNone);
stri := TStringStream.Create('');
try
stri.CopyFrom(fils, fils.Size);
Result := stri.DataString;
finally
fils.Free;
stri.Free;
end;
end;

Stream objects to a file using TFileStream

Why does this code not work?
I am writing an application that has ability to save and load its own files and need to know how to stream objects to a file using FileStream.
procedure TForm1.btnSaveClick(Sender: TObject);
var
fs: TFileStream;
begin
fs := TFileStream.Create('c:\temp\a.my', fmCreate);
try
fs.WriteBuffer(Image1.Picture.Graphic, SizeOf(TGraphic));
finally
fs.Free;
end;
ShowMessage('ok');
Image1.Picture.Graphic := nil;
end;
procedure TForm1.btnLoadClick(Sender: TObject);
var
fs: TFileStream;
g: TGraphic;
begin
fs := TFileStream.Create('c:\temp\a.my', fmOpenRead);
try
fs.ReadBuffer(g, SizeOf(TGraphic));
Image1.Picture.Graphic := g;
finally
fs.Free;
end;
ShowMessage('ok');
end;
EDIT 1:
Found the way to do it, but need some more help:
procedure TForm1.btnSaveClick(Sender: TObject);
var
fs: TFileStream;
s: TMemoryStream;
buf: TBytes;
begin
fs := TFileStream.Create('c:\temp\a.my', fmCreate);
s := TMemoryStream.Create;
try
Image1.Picture.Graphic.SaveToStream(s);
SetLength(buf, s.Size);
s.Position := 0;
s.ReadBuffer(buf[0], s.Size);
//fs.WriteBuffer(, SizeOf(Integer)); <-here how do I save an integer which represents the size of the buffer? (so that when reading back i read this first.)
fs.WriteBuffer(buf[0], s.Size);
finally
s.Free;
fs.Free;
end;
ShowMessage('ok');
Image1.Picture.Graphic := nil;
end;
What you have done there is stream the reference, i.e. a pointer. What you need to stream is the contents. You can that with SaveToFile and LoadFromFile.
Regarding your update, assign s.Size to a local variable of type Integer and then use WriteBuffer to save it. In reverse, use ReadBuffer to read into a local variable.
If I were you I would write direct to the file and avoid the memory streak. Use the Position property of TStream to seek around the file. So write 0 for then length, write the graphic, seek back to the beginning and write the true length accounting for the 4 bytes of the length.

Resources