#1 2014-05-25 21:24:19

tech
Member
Registered: 2014-01-13
Posts: 110

ReadStringFromStream returns empty string

Hi,

I've a TMemorystream containing a fastreport file (xml) that I want to save onto a blob field but this code doesn't work

  try
    Stream := TMemoryStream.Create;
    Stream.Position := 0;
    Report.SaveToStream(Stream);
    ShowMessage(ReadStringFromStream(Stream)); <--- Empty string although Stream.Size = 1828
  finally
    Stream.Free;
  end;

Offline

#2 2014-05-26 06:12:05

DigDiver
Member
Registered: 2013-04-29
Posts: 137

Re: ReadStringFromStream returns empty string

Report.SaveToStream(Stream);

Stream.seek(0,0);

Last edited by DigDiver (2014-05-26 06:12:31)

Offline

#3 2014-05-26 07:00:45

tech
Member
Registered: 2014-01-13
Posts: 110

Re: ReadStringFromStream returns empty string

Sorry but it doesn't work for me, I've already an empty string !!

Offline

#4 2014-05-26 07:01:35

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: ReadStringFromStream returns empty string

Indeed.

I've just enhanced the doc about ReadStringFromStream() to make it clear.
See http://synopse.info/fossil/info/518822d716

Online

#5 2014-05-26 08:55:23

tech
Member
Registered: 2014-01-13
Posts: 110

Re: ReadStringFromStream returns empty string

Hi AB,

It doesn't work for me yikes When I've updated the source with the latest one, I got this compilation error in syncommons.pas at line 25231

[Erreur fatale] SynCommons.pas(25231): Erreur interne : C3950

I'm on D7 and win8

Last edited by tech (2014-05-26 09:01:27)

Offline

#6 2014-05-26 11:27:47

tech
Member
Registered: 2014-01-13
Posts: 110

Re: ReadStringFromStream returns empty string

I forgot the MaxAllowedSize parameter then I put :

    Report.SaveToStream(msStream);
    msStream.seek(0,soBeginning);
    msStream.Read(L,4);
    ShowMessage(ReadStringFromStream(msStream, L));

and I got an Out of memory here

function ReadStringFromStream(S: TStream; MaxAllowedSize: integer): RawUTF8;
var L: integer;
begin
  result := '';
  L := 0;
  if (S.Read(L,4)<>4) or (L<=0) or (L>MaxAllowedSize) then
    exit;
  SetLength(Result,L);   <--------------------- out of memory L = 1702240364
  if S.Read(pointer(result)^,L)<>L then
    result := '';
end;

Offline

#7 2014-05-26 11:36:31

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: ReadStringFromStream returns empty string

ReadStringFromStream() does not work with any stream.
It does work only as reverse function to WriteStringToStream.

For instance:

WriteStringToStream(Stream,aUTF8Text);
Stream.Seek(0,soBeginning);
str := ReadStringFromStream(Stream);

So for your purpose, you should NOT use ReadStringFromStream() at all.

The easiest is in fact to use our TRawByteStringStream class, as such:

var Stream: TRawByteStringStream;
...
  Stream := TRawByteStringStream.Create;
  try
    Report.SaveToStream(Stream);
    // Stream.DataString now contains the text
  finally
    Stream.Free;
  end;

Note that TRawByteStringStream uses 8 bit string (i.e. a RawByteString) so your Report.SaveToStream() should create UTF-8 content.

BTW, I do not have any problem with Delphi 7 compilation of the latest trunk revision.
Perhaps quit and reopen the IDE, try to delete all you .dcu files, and force a rebuild of the project.

Online

#8 2014-05-26 14:53:33

tech
Member
Registered: 2014-01-13
Posts: 110

Re: ReadStringFromStream returns empty string

Ok AB it works now with TRawByteStringStream thnx,

BTW, the compilation error persists although I restarted the IDE and tryed to compile "01 - In Memory ORM" sample.

Offline

#9 2014-06-18 14:57:49

tech
Member
Registered: 2014-01-13
Posts: 110

Re: ReadStringFromStream returns empty string

Hi AB,
The TRawByteStringStream works fine but I've the UTF-8 content problem. Normaly fastreport creates a UTF-8 content but when I put a text "Libellé" on the report and save it, I got on the database "Libelé".
How can I fix that ?

BTW, the new version of mORMot compiles fine with D7.

Offline

#10 2014-06-18 15:17:02

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: ReadStringFromStream returns empty string

"Libelé" is "Libellé" encoded in UTF-8.

Prior to Delphi 2009, the Delphi string type does not have an encoding, so it assumes that it is encoded with the system code page of non unicode applications.
You can use RawUTF8ToString() to convert a RawUTF8 into a Delphi 7 ansi string.

But within mORMot, UTF-8 is used everywhere, up to the database.
Which DB are you using?

Online

#11 2014-06-18 15:24:59

tech
Member
Registered: 2014-01-13
Posts: 110

Re: ReadStringFromStream returns empty string

Now I'm using SQLite but for the future I'll use perhaps Firebird.
I don't see where can I use RawUTF8ToString() on the Report.saveToStream ?

Thnx

Offline

#12 2014-06-18 15:29:00

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: ReadStringFromStream returns empty string

If you store Stream.DataString into a RawUTF8 property, it will be stored properly in the SQLite3 database.

Please show some of your code.

Online

#13 2014-06-18 15:42:38

tech
Member
Registered: 2014-01-13
Posts: 110

Re: ReadStringFromStream returns empty string

The class :

  TSQLEtat = class(TSQLRecord)
  private
    fLibelle : RawUTF8;
    fFiche : RawUTF8;
    fEtat : TSQLRawBlob;
  published
    property ManCode : RawUTF8 index 10 read fManCode write fManCode stored AS_UNIQUE;
    property Fiche : RawUTF8 index 20 read fFiche write fFiche;
    property Etat : TSQLRawBlob read fEtat write fEtat;
  end;  

The function to save the report :

  
function TF_Etat.frxDesigner1SaveReport(Report: TfrxReport;
  SaveAs: Boolean): Boolean;
var Stream: TRawByteStringStream;
  fEtat : TSQLEtat;
begin
  try
    fEtat := TSQLEtat.Create;
    Stream := TRawByteStringStream.Create;
    Stream.Position := 0;
    Report.SaveToStream(Stream);
    Stream.seek(0,soBeginning);
    fEtat.Etat := S2U(Stream.DataString);
    globalClient.Add(fetat, true);
  finally
      fEtat.Free;
    Stream.Free;  
  end;
end;  

The function to load the report :

function TF_Etat.LoadFromStream():boolean;
var Stream : TMemoryStream;
begin
  if not globalClient.RetrieveBlobFields(fEtat) then
  begin
    result := False;
    exit;
  end
  else
    result := True;
  try
    Stream := TMemoryStream.Create;
    WriteStringToStream(Stream, fEtat.Etat);
    if (Stream.Size > 0) and (fEtat.Etat <> '') then
    begin
      Stream.Position := 0;
      frxReport.LoadFromStream(Stream);
      frxReport.ShowReport();
    end
    else
      result := False;
  finally
    Stream.Free;
  end;
end;

Last edited by tech (2014-06-18 15:44:08)

Offline

#14 2014-06-18 15:50:05

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: ReadStringFromStream returns empty string

You are storing a BLOB in the database, not UTF-8.

I would rather define a TEXT field here:

TSQLEtat = class(TSQLRecord)
  private
    fLibelle : RawUTF8;
    fFiche : RawUTF8;
    fEtat : RawUTF8;
  published
    property ManCode : RawUTF8 index 10 read fManCode write fManCode stored AS_UNIQUE;
    property Fiche : RawUTF8 index 20 read fFiche write fFiche;
    property Etat : RawUTF8 read fEtat write fEtat; // without "index ??" to force a CLOB
  end;  

And then the following line should write good UTF-8, as expected:

fEtat.Etat := S2U(Stream.DataString);

You may also leave "Etat: TSQLRawBlob", then UTF-8 will be stored as BLOB.
And reported as such.

Online

#15 2014-06-18 16:03:01

tech
Member
Registered: 2014-01-13
Posts: 110

Re: ReadStringFromStream returns empty string

I've changed the TSQRawBlob by RawUTF8 but it doesn't work for me, I've already this following line on the save function

fEtat.Etat := S2U(Stream.DataString);

I think that because of this line that I got that "Libelé", now we need to convert U2S for this line

WriteStringToStream(Stream, fEtat.Etat);

Offline

#16 2014-06-18 16:16:59

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: ReadStringFromStream returns empty string

tech wrote:

I've changed the TSQRawBlob by RawUTF8 but it doesn't work for me,

Did you delete the database file, to update the schema?

Online

#17 2014-06-18 16:23:54

tech
Member
Registered: 2014-01-13
Posts: 110

Re: ReadStringFromStream returns empty string

Yes, and the exe created a new db file.

Offline

#18 2014-06-18 18:15:27

tech
Member
Registered: 2014-01-13
Posts: 110

Re: ReadStringFromStream returns empty string

Hi AB,
I've convert the TMemoryStream to TStringStream and that works fine with U2S on the loadfromStream function

function TF_Etat.LoadFromStream():boolean;
var Stream : TStringStream;  <---------------------------------- Modification
begin
  if not globalClient.RetrieveBlobFields(fEtat) then
  begin
    result := False;
    exit;
  end
  else
    result := True;
  try
    Stream := TStringStream.Create(u2S(fEtat.Etat));  <----------------- Conversion u2s
    //WriteStringToStream(Stream, fEtat.Etat); 
    if (Stream.Size > 0) and (fEtat.Etat <> '') then
    begin
      Stream.Position := 0;
      frxReport.LoadFromStream(Stream);
      frxReport.ShowReport();
    end
    else
      result := False;
  finally
    Stream.Free;
  end;
end;

Thnx

Offline

Board footer

Powered by FluxBB