string to byte array and array of bytes to file - arrays

I need to implement in Delphi 2006 an algoritm that work in .net
Basicaly I need to do the next steps:
Create an XML and validate aganist the XSD
Serialize the XML string into an array of bytes UTF-8 encoded and compress it with zip
The compressed info must be stored again into a array of bytes using base256 format
Create an image using Datamatrix 2D BarCode from this array of bytes and put this image on a report
For step 1, I create the XML using NativeXML library that work ok. In this library exist a metod SaveToBinaryFile but don't work ok. In my tests I used this function to create a binary file.
I was forced to use a binary file becouse my Zip component work only with files not with strings or aray of bytes from memory.
I compressed this binary file with the Zip component and loaded this compresed file into a blob file.
At the moment when I need to create the DataMatrix image I load this blob file into an ansistring and I create the image.
After many tests I found that my fault is when I save my XML into the binary file.
Now I need to found another way to save my xml (utf-8) string to a binarry file.
Please sorry for my english.
Can anyone help me?

procedure CreateXMLBarcodeș
var
BinarySize: Integer;
InputString: utf8string;
StringAsBytes: array of Byte;
F : FIle of Byte;
pTemp : Pointer;
begin
InputString := '';
ADoc := TNativeXml.CreateName(rootName);
try
... //create the XML
InputString := ADoc.WriteToLocalString; //utf8string
if InputString > '' then begin
//serialize the XML string to array of bytes
BinarySize := (Length(InputString) + 1) * SizeOf(Char);
SetLength(StringAsBytes, BinarySize);
Move(InputString[1], StringAsBytes[0], BinarySize);
//save the array of bytes to file
AssignFile( F, xmlFilename );
Rewrite(F);
try
BinarySize := Length( StringAsBytes );
pTemp := #StringAsBytes[0];
BlockWrite(F, pTemp^, BinarySize );
finally
CloseFile( F );
end;
end;
finally
ADoc.Free;
end;
end
...
//in other procedure:
DataSet1XMLBarCode.LoadFromFile(CreateXMLBarcode);
...
//when I want to create the report
//create the DataMatrix image
procedure xyz(Sender: TfrxReportComponent);
var AWidth, AHeight: Integer;
function GetStringFromBlob: AnsiString;
var BlobStream: TStream;
begin
Result := '';
DataSet.Open;
BlobStream := DataSet1.
CreateBlobStream(DataSet1XMLBarCode, bmRead);
try
SetLength(Result, BlobStream.Size);
BlobStream.Position := 0;
BlobStream.Read(Result[1], BlobStream.Size);
finally
BlobStream.Free;
end;
DataSet.Close;
end;
begin
Barcode2D_DataMatrixEcc2001.Locked := True;
Barcode2D_DataMatrixEcc2001.Barcode := GetStringFromBlob;
Barcode2D_DataMatrixEcc2001.Module := 1;
Barcode2D_DataMatrixEcc2001.DrawToSize(AWidth, AHeight);
with TfrxPictureView(frxReport1.FindObject('Picture1')).Picture.Bitmap do
begin
Width := AWidth;
Height := AHeight;
Barcode2D_DataMatrixEcc2001.DrawTo(Canvas, 0, 0);
end;
Barcode2D_DataMatrixEcc2001.Locked := False;
end;
//the code was 'çopied'and adapted from the internet

Related

How to remove the starting header in a MemoryStream and save the rest to a file?

I currently have a TMemoryStream that gets filled via reading a varbinary field, which is originally encoded by UTF8 standard from a MS SQL Server DB table.
The varbinary field contains a header part which needs to be removed before saving the remainder of the stream as a file.
I have successfully pulled out the header information required, which includes the file name, but haven’t
found a solution for then saving the remainder of the stream as a valid file.
The data is initially read into a TdxMemData dataset.
procedure TBaseDataPump.SaveAttachments(mtblAttachmentInfo: TdxMemData);
var
AFile: TMemoryStream;
ANewFile: TStringStream;
sFullPath: String;
wsImageBlob, wsHeader, wsBody: WideString;
iposition: Integer;
begin
if mtblAttachmentInfo.Active then // TdxMemData filled with data
begin
with mtblAttachmentInfo do
begin
First;
while NOT EOF do
begin
// Below code works fine to save the file without removing the data
AFile := TMemoryStream.Create; // Create the memory stream
TBlobField(FieldByName('ImageBlob')).SaveToStream(AFile);
// load the file image from the data to the memory strem
// Get the header content
ANewFile := TStringStream.Create('');
TBlobField(FieldByName('ImageBlob')).SaveToStream(ANewFile);
// read the filed again to a TStringStream
wsImageBlob := UTF8ToString(ANewFile.DataString);
// I can see the data as wide string and can find the header bit and its ending position on the
// its ending position on the string
iposition := AnsiPos(#13#13#10, wsImageBlob); // find the header ending position
// getting the header to another widestring
wsHeader := AnsiLeftStr(wsImageBlob,position);
wsHeader := AnsiLeftStr(wsImageBlob,POS(#9,wsHeader)-1);
wsHeader := StringReplace(wsHeader,'''','',[rfReplaceall]);
// need to save the stream from the position of the end of header as file
end;
end;
end;
end;
Found the solution with the copyfrom method. and its is as follows :
// Create the TStringStream
ANewFile := TStringStream.Create('');
try
TBlobField(FieldByName('ImageBlob')).SaveToStream(ANewFile);
// get the blob as a string so we can extract the header information
wsImageBlob := UTF8ToString(ANewFile.DataString);
position := AnsiPos(#13#13#10, wsImageBlob);
if position <> 0 then begin
// have header information to extract
position := position + 2;
wsHeader := AnsiLeftStr(wsImageBlob, position);
wsHeader := AnsiLeftStr(wsImageBlob, POS(#9, wsHeader) - 1);
wsHeader := StringReplace(wsHeader, '''', '', [rfReplaceall]);
sFilePath := sDirectorypath + wsHeader;
ANewFile.Position := position;
AFile := TMemoryStream.Create;
try
AFile.CopyFrom(ANewFile, ANewFile.Size - position);
AFile.SaveToFile(sFilePath);
finally
FreeAndNil(AFile);
end;
end
finally
FreeAndNil(ANewFile);
end;

Delphi - Store and read 2d array from text file [duplicate]

This question already has answers here:
How do I save the contents of this 2d array to a file
(3 answers)
Closed 7 years ago.
I am trying to store a 2d array which holds characters, into a text file which is in the comma separated values (CSV) format. I have been semi able to store the array into the text file but i dont think it will allow for it to be read back as there is no new line at the end of the end of each line where the end of the array would be (Board[1][8]) for an example. I have been unable to read the informatoin back into the array.
This is my code for storing the array into the text file
Const
BoardDimension = 8;
Type
TBoard = Array[1..BoardDimension, 1..BoardDimension] Of String;
procedure SaveGame(Board : Tboard);
var
FileNm : Textfile;
RankCount : Integer;
FileCount : Integer;
begin
Assignfile(Filenm, 'SavedGame.txt');
Rewrite(Filenm);
for RankCount :=1 to BoardDimension do
begin
for FileCount := 1 to BoardDimension-1 do
begin
write(Filenm,Board[RankCount,FileCount],',');
end;
write(Filenm,Board[RankCount,BoardDimension]);
end;
CloseFile(filenm);
writeln('game saved');
end;
this is my code for reading the text file back, but i am getting an error which states that the function Copy2SymbDel is undeclared but i have included strutils in the using statement
procedure LoadGame(Var Board :TBoard);
var
Filenm : TextFile;
RankCount : Integer;
FileCount : Integer;
Text : String;
begin
AssignFile(Filenm, 'SavedGame.txt');
reset(Filenm);
for RankCount := 1 to BoardDimension do
begin
readln(Filenm,text);
for FileCount := 1 to BoardDimension -1 do
begin
Board[RankCount,FileCount] := Copy2SymbDel(Text, ',');
end;
Board[RankCount,BoardDimension] := Text;
end;
end;
How can I store and read back a 2d array in delphi/pascal
Thank you
Copy2SymbDel is a FreePascal library function that is not available in Delphi. It is described like this:
function Copy2SymbDel(
var S: string;
Symb: Char
):string;
Description
Copy2SymbDel determines the position of the first occurrence of Symb
in the string S and returns all characters up to this position. The
Symb character itself is not included in the result string. All
returned characters and the Symb character, are deleted from the
string S, after which it is right-trimmed. If Symb does not appear in
S, then the whole of S is returned, and S itself is emptied.
In Delphi the function could be implemented like this:
function Copy2SymbDel(var S: string; Symb: Char): string;
var
I: Integer;
begin
I := Pos(Symb, S);
if I = 0 then
begin
Result := S;
S := '';
end
else
begin
Result := Copy(S, 1, I-1);
S := TrimRight(Copy(S, I+1, MaxInt));
end;
end;

TClientDataSet read Binary field to TStream

i have tried this every way that I possible can, but cannot seem to resolve this. I am working with DBExress in Delphi XE3 writing a REST DataSnap Server.
I have data stored in MSQL in a Binary(384) field and Binary is as far as I know that same as a BLOB/Image field as it is all Binary data.
When trying to stream this data to a TStream I receive an exception error and have tried the following
var
STemplate : TStream;
begin
......
Template := TBlobField.Create(cdsBSUserTemplates.FieldByName('bTemplate'));
TBlobField(cdsBSUserTemplates.FieldByName('bTemplate')).SaveToStream(STemplate); //exception
......
end;
and I have tried
var
STemplate : TStream;
begin
......
Template := TBlobField.Create(cdsBSUserTemplates.FieldByName('bTemplate'));
STemplate := cdsBSUserTemplates.CreateBlobStream(Template, bmRead); //exception
......
end;
I can return the value .AsString, but it is Bytes and then I need to try and fix what I have read from that field.
Any idea what else I can try?
You're working much too hard. :-)
You need to properly create the stream, and then just let the field write to it.
var
Output: TMemoryStream;
Fld: TBlobField;
begin
// Use of variable makes it more readable
Fld := cdsBSUserTemplates.FieldByName('bTemplate') as TBlobField;
Output := TMemoryStream.Create;
try
Fld.SaveToStream(Output);
Output.Position := 0;
// Do whatever with the output stream
finally
Output.Free;
end;
end;
After your comment that you might not be using a TBlobField (which would have been nice to know before I posted my answer), you can try this instead (untested, because I clearly don't have your data):
var
Output: TMemoryStream;
Fld: TField;
Bytes: TArray<Byte>;
begin
Fld := ADOQuery1.FieldByName('bTemplate');
Output := TMemoryStream.Create;
try
if Fld.IsBlob then
TBlobField(Fld).SaveToStream(Output)
else
begin
Fld.GetData(Bytes);
Output.WriteData(Bytes, Length(Bytes));
end;
// Do whatever with output
finally
Output.Free;
end;
end;

Delphi7. Read BLOB field with WideString data in it

Can anybody help? I'm keeping an old Delphi7 project and have next trouble. How can I store BLOB field value if it contains Unicode string?
I tried:
var
str: WideString;
begin
...
str := WideString(Fields[1].AsString); - but I get empty string
...
...
str := VarToWideStr(Fields[1].AsVariant); - but I get "(BLOB)" result in str varible.
...
end;
My solution:
Code usage:
...
stream := TMemoryStream.Create;
try
Fields[1].SaveToStream(stream);
ss := MemStreamToWStr(stream);
finally
stream.Destroy;
end;
...
And function:
function TSnsFrame.MemStreamToWStr(Mstream: TMemoryStream): WideString;
begin
Mstream.Seek(0, soFromBeginning);
SetLength(Result, Mstream.size div 2);
MStream.ReadBuffer(Result[1], Mstream.size);
end;
Have a look at TDataSet.CreateBlobStream(). It returns a TStream that can be used to read/write the raw data of a blob field.

Base64 encoded String to binary file

I have a Base64 encoded String that contains PDF data. Using the EncdDecd unit I can decode the String to a Byte Array.
This is where I am having trouble: I tried saving the characters to a String but once it hits a zero value (ASCII = 0 or #0 or $00) the String no longer appends. Example:
uses
EncdDecd;
var
EncodedString : String;
Report : String;
Base64Bytes: TBytes; // contains the binary data
begin
Base64Bytes := DecodeBase64(EncodedString);
for I := 0 to Length(Base64Bytes) - 1 do
begin
Report := Report + Chr(Base64Bytes[I]);
end;
Writing to a text file seems to work better but after renaming it to .PDF the file does not open correctly.
How can I write to a binary file in Delphi? Or even save the data to a stream? Basically I am just trying to take the encoded String and save it to a PDF/binary file, or display the PDF in Delphi.
I have looked around quite a bit and found a possible solution in
Saving a Base64 string to disk as a binary using Delphi 2007 but is there another way?
This should do it:
procedure DecodeBaseToFile(const FileName: string;
const EncodedString: AnsiString);
var
bytes: TBytes;
Stream: TFileStream;
begin
bytes := DecodeBase64(EncodedString);
Stream := TFileStream.Create(FileName, fmCreate);
try
if bytes<>nil then
Stream.WriteBuffer(bytes[0], Length(bytes));
finally
Stream.Free;
end;
end;
Note: I have only compiled this in my head.

Resources