您的位置:首页 > 产品设计 > UI/UE

acFileStorage equivalent

2016-04-12 19:53 519 查看
searching for a vcl that can enable embed any files within dfm similar to acfilestorage

When there are bugs with the file naming, then the porting wasn't completely done. The problem with "malformed" strings is still always the same. A string is treated as ANSI, but since Delphi 2009 the strings in Delphi has the Unicode format. What means, a string of Length 5 needs 10 bytes to store. Another typical fault is to treat a Unicode Buffer as ANSI. Such things leads always into "malformed" strings.

Now, you need to change the way the file name is stored. The function "WriteStream(…)" should be something like this…

Code:
procedure TStoredFile.WriteData(Stream: TStream);
var
Buffer: TArray<Byte>;
TheSize: Cardinal;
Target: Pointer;
begin
// storing the file name
Buffer := TEncoding.UTF8.GetBytes(FFileName);       <- The filename is converted to UTF8…
TheSize := Length(Buffer);
Stream.Write(TheSize, 4);
Stream.Write(Buffer, 0, TheSize);                   <- …and the bytes will be written

// pack and write data
TheSize := SFCalcTargetSz(FSize); // calculate required size for taget buffer
GetMem(Target, TheSize);
try
TheSize := SFPack(FData.Memory, Target, FSize);
Stream.Write(TheSize, 4); // compressed size
Stream.Write(Target^, TheSize); // original size and compressed data
finally
FreeMem(Target);
end;
end;

Here is the function "ReadStream(…)"…

Code:
procedure TStoredFile.ReadData(Stream: TStream);
var
Buffer: TArray<Byte>;
TheSize: Cardinal;
Source: Pointer;
begin
// reading the file name
Stream.Read(TheSize, SizeOf(TheSize));
SetLength(Buffer, TheSize);
Stream.Read(Buffer, 0, TheSize);                              <- Read the UTF8 Bytes…
FFileName := TEncoding.UTF8.GetString(Buffer, 0, TheSize);    <- …and convert them back to Unicode

// reading the file size
Stream.Read(TheSize, 4); // compressed size
if (Owner = nil) or TacFileStorage(Owner).Compressed then
begin
dec(TheSize, 4);
GetMem(Source, TheSize); // allocating memory for compressed buffer
Stream.Read(FSize, 4); // original size
FData.SetSize(FSize); // allocating memory for decompressed buffer
try
Stream.Read(Source^, TheSize); // reading compressed data
SFUnpack(Source, FData.Memory, TheSize);
finally
FreeMem(Source);
end
end
else // this is for compatibility with older versions
begin
FSize := TheSize;
FData.SetSize(FSize);
// reading the stream
Stream.ReadBuffer(FData.Memory^, FSize);
end;
end;


The filename is stored in the format UTF8 byte, which allows in the best case one Byte for one Character. Please remember Unicode needs two Bytes per Character.

Useless to say, that this is a breaking change. The chance is high, that existing streams couldn't be read sucessfulyy. In this case the DFM should be clear manually. I should be enough to remove the content of the property "StoredData = { ... }", which is easy to find. The component could then be loaded again.

Note: Now, it's not recommended to use the component TacFileStorage, because in the worst case a file with 1 MiB became 2 MiB, because of it is stored as Hex string. It would be much better to use a resource file that is unpacked on run-time.
https://www.board4allcz.eu/showthread.php?t=626035
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: