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;
Related
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...
I've written procedure to download file from google drive:
procedure DownloadfromDriveMyGolden2File;
begin
form2.RESTResponseDataSetAdapter1.AutoUpdate := false;
form2.RESTRequest1.Params.Clear;
form2.RESTRequest1.ClearBody;
form2.RESTRequest1.Method:=rmget;
Form2.RESTClient1.BaseURL:='https://www.googleapis.com/drive/v2/files/{FileId}?alt=media';
form2.RESTRequest1.Resource := '';
form2.RESTRequest1.Params.AddUrlSegment('FileId', form2.Edit4.Text);
try
form2.RESTRequest1.Execute;
except
on e: Exception do
begin
ShowMessage(e.Message);//Show Exception
end;
end;
end;
But i cant imagine where i can catch Tfilestream or Tmemorystream to get my file, is it possible or i should use idhttp to do this ?
I've found the answer:
procedure ServerResponseToFile;
var
SomeStream : tmemorystream;
local_filename : string;
begin
//в андроиде обратные слеши
{$IF DEFINED(MsWindows)}
local_filename := ExtractFilePath(ParamStr(0)) +'syncdownload/Northwindpers.sqlite3';
{$ENDIF}
SomeStream := tmemorystream.Create;
Somestream.WriteData(form2.RESTResponse1.RawBytes,Length(form2.RESTResponse1.Raw Bytes));
SomeStream.SaveToFile(local_filename);
SomeStream.free;
end;
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;
I have this basic code that should encode a string and then get it back. However, the decoded text is garbage.
procedure TForm5.Button2Click(Sender: TObject);
VAR s1, s2, s3: String;
i: Integer;
begin
for i:= 1 to 200
DO s1:= s1+ char(Random(255));
s1:= EncdDecd.EncodeString(s1);
s3:= EncdDecd.DecodeString(s2);
if s1= s3
then Caption:= 'Equal'
else Caption:= 'Not equal';
end;
Update:
It works if I do char(Random(128)) instead of 255!
The problem is here, in the Soap.EncdDecd unit:
function EncodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr := TStringStream.Create(Input);
try
OutStr := TStringStream.Create('');
try
EncodeStream(InStr, OutStr);
Result := OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
This code has not been updated for Unicode. The use of TStringStream for InStr without specifying an encoding is the problem. With no encoding specified, ANSI is used to decode to a byte array. And so only characters in the local ANSI code page are decoded correctly.
The same mistake is made in the other direction in DecodeString.
You can fix this readily enough by creating variants that specify a full Unicode encoding. For example:
function EncodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr := TStringStream.Create(Input, TEncoding.UTF8);
try
OutStr := TStringStream.Create('');
try
EncodeStream(InStr, OutStr);
Result := OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
function DecodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr := TStringStream.Create(Input);
try
OutStr := TStringStream.Create('', TEncoding.UTF8);
try
DecodeStream(InStr, OutStr);
Result := OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
It doesn't matter which encoding you specify so long as it is a full Unicode encoding, and you use the same encoding in both directions!
Clearly Embarcadero should be encouraged to make this change to their code.
This program demonstrates that the fix works:
{$APPTYPE CONSOLE}
uses
System.SysUtils, System.Classes, Soap.EncdDecd;
function EncodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr := TStringStream.Create(Input, TEncoding.UTF8);
try
OutStr := TStringStream.Create('');
try
EncodeStream(InStr, OutStr);
Result := OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
function DecodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr := TStringStream.Create(Input);
try
OutStr := TStringStream.Create('', TEncoding.UTF8);
try
DecodeStream(InStr, OutStr);
Result := OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
const
N = 256;
var
i: Integer;
s1, s2: string;
begin
SetLength(s1, N);
for i := 1 to N do
s1[i] := Chr(i-1);
s2 := Soap.EncdDecd.EncodeString(s1);
s2 := Soap.EncdDecd.DecodeString(s2);
Writeln(s1=s2);
s2 := EncodeString(s1);
s2 := DecodeString(s2);
Writeln(s1=s2);
end.
Output:
FALSE
TRUE
Quick fix:
ANSI is enough for me since the text resulted after encoding must be as short as possible (easy to send via email). So, I put my ANSI string into a stream and encoded/decoded the stream. It worked!
Jesus. Some documentation (at least a single comment line) would have been nice!
I have a problem with using streams. I would like to read my html code line by line. With reading file line by line i have no problems but i need to read actualy opened document with webbrowser so i write this:
procedure TForm2.SpeedButton2Click(Sender: TObject);
var
iall : IHTMLElement;
strumien : TStringStream;
reader : TStreamReader;
begin
if Assigned(WebBrowser1.Document) then
begin
iall := (WebBrowser1.Document AS IHTMLDocument2).body;
while iall.parentElement <> nil do
begin
iall := iall.parentElement;
end;
Strumien:=Tstringstream.Create(iall.innerHTML);
Strumien.Position:=0;
reader:=TStreamReader.Create(Strumien, TEncoding.UTF8);
reader.OwnStream;
while not reader.EndOfStream do
memo1.Lines.Add(reader.ReadLine);
end;
end;
This code doesnt work. Reads only few lines from center of document and gives "List index out of bounds" Anyone know why? Using Embarcadero XE2 Delphi
Thanks a lot!
You are mixing different string encodings together, which might account for why TStreamReader is not able to read everything correctly. TStringStream also uses TEncoding in D2009+, but you are not specifying any TEncoding type in the TStringStream constructor, so it will use TEncoding.Default, which is not the same encoding as TEncoding.UTF8. So you are taking the original UTF-16 encoded HTML string, converting it to the OS default Ansi encoding, and then trying to read it back as UTF-8. That can only work if the data does not contain any non-ASCII characters in it.
Try this instead:
procedure TForm2.SpeedButton2Click(Sender: TObject);
var
iall : IHTMLElement;
iparent : IHTMLElement;
strumien : TStringStream;
reader : TStreamReader;
s: String;
begin
if Assigned(WebBrowser1.Document) then
begin
iall := (WebBrowser1.Document AS IHTMLDocument2).body;
iparent := iall.parentElement;
while iparent <> nil do
begin
iall := iparent;
iparent := iparent.parentElement;
end;
Strumien := TStringStream.Create(iall.innerHTML, TEncoding.UTF8, False);
try
Strumien.Position := 0;
reader := TStreamReader.Create(Strumien, TEncoding.UTF8);
try
while not reader.EndOfStream do
begin
s := reader.ReadLine;
// use s as needed...
end;
finally
reader.Free;
end;
finally
Strumien.Free;
end;
end;
end;
In the specific case of loading the document into a TMemo, you don't need the TStringStream or TStreamReader at all:
procedure TForm2.SpeedButton2Click(Sender: TObject);
var
iall : IHTMLElement;
iparent : IHTMLElement;
begin
if Assigned(WebBrowser1.Document) then
begin
iall := (WebBrowser1.Document AS IHTMLDocument2).body;
iparent := iall.parentElement;
while iparent <> nil do
begin
iall := iparent;
iparent := iparent.parentElement;
end;
Memo1.Text := iall.innerHTML;
end;
end;