SOU*_*ser 4 delphi string hex stringstream delphi-xe
正如专家已经建议好心,TStringStream.DataString
不能用于检索non-text
由加载的数据TStringStream.LoadFromFile
,因为TStringStream.GetDataString
会叫TEncoding
的编码方法,其中,采取TMBCSEncoding
例如,将调用TMBCSEncoding.GetChars
这反过来又来电TMBCSEncoding.UnicodeFromLocaleChars
,最后Windows
的MultiByteToWideChar
.
建议将TBytes用作数据缓冲区/二进制存储.(为此,建议使用TBytes而不是AnsiString.)
在bytes
可以从被检索TStringStream.ReadBuffer
的方法或TStringStream.Bytes
属性.无论哪种方式,TStream.Size
都应该考虑.
================================================== ==
我正在尝试使用TStringStream
它并DataString
用于base64编码/解码目的.似乎有可能如此处或此处Nils Haeck
的回复所示.
使用TStringStream.DataString
中TMainForm.QuestionOfString_StringStream
(第2号至7号)失败,该信息已损坏(即不一样的原始信息).但是,ss_loaded_2.SaveToFile
(No.1)保存原始信息,表示TStringStream
是否在内部正确保存解码的非文本数据?你能帮忙评论一下DataString损坏的可能原因吗?
在Rob Kennedy
他的答复中,他提到string
或ansistring
应该避免存储base64解码的非文本数据,这很有意义.然而,如图中TMainForm.QuestionOfString_NativeXML
,所述DecString
的AnsiString
类型包含所以正确的数据可以被编码回经解码的字节.这是否意味着AnsiString可以保存已解码的非文本数据?
David Heffernan
并且Rob Kennedy
好好评论了字节/ TBytes.然而,bytes
提取的TMainForm.QuestionOfString_NativeXML_Bytes_1
,从不同TStringStream
的Bytes
中TMainForm.QuestionOfString_NativeXML_Bytes_2
.(从Base64编码/解码结果来看,这TStringStream.Bytes
是错误的.它是令人困惑的,因为根据上面的段落,TStringStream
内部应该包含完整的字节?)你能否帮助评论可能的原因?
非常感谢您的帮助!
PS:可以从SkyDrive下载示例文件:REF_EncodedSample和REF_DecodedSample.(Zlib压缩的图像文件.).
PS:Delphi XE,Windows 7.(似乎在Delphi 7中的TStringStream没有LoadFromFile或SaveToFile.)
unit uMainForm;
interface
uses
CodeSiteLogging,
NativeXml, // v3.10
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure QuestionOfString_StringStream;
procedure QuestionOfString_NativeXML;
procedure QuestionOfString_NativeXML_Bytes_1;
procedure QuestionOfString_NativeXML_Bytes_2;
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
// http://stackoverflow.com/questions/773297/how-can-i-convert-tbytes-to-rawbytestring
function Convert(const Bytes: TBytes): RawByteString;
begin
SetLength(Result, Length(Bytes));
if Length(Bytes) > 0 then
begin
Move(Bytes[0], Result[1], Length(Bytes));
// SetCodePage(Result, CP_ACP, False);
end;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
QuestionOfString_StringStream;
QuestionOfString_NativeXML;
QuestionOfString_NativeXML_Bytes_1;
QuestionOfString_NativeXML_Bytes_2;
end;
// http://www.delphigroups.info/2/3/321962.html
// http://borland.newsgroups.archived.at/public.delphi.graphics/200712/0712125679.html
procedure TMainForm.QuestionOfString_StringStream;
var
ss_loaded_2, ss_loaded_3: TStringStream;
dataStr: AnsiString;
hexOfDataStr: AnsiString;
begin
ss_loaded_2 := TStringStream.Create();
// load the file containing Base64-decoded sample data
ss_loaded_2.LoadFromFile('REF_DecodedSample');
// 1
ss_loaded_2.SaveToFile('REF_DecodedSample_1_SavedByStringStream');
// 2
ss_loaded_3 := TStringStream.Create(ss_loaded_2.DataString);
ss_loaded_3.SaveToFile('REF_DecodedSample_2_SavedByStringStream');
// 3
ss_loaded_3.Free;
ss_loaded_3 := TStringStream.Create(ss_loaded_2.DataString, TEncoding.ASCII);
ss_loaded_3.SaveToFile('REF_DecodedSample_3_SavedByStringStream');
// 4
ss_loaded_3.Free;
ss_loaded_3 := TStringStream.Create(ss_loaded_2.DataString, TEncoding.UTF8);
ss_loaded_3.SaveToFile('REF_DecodedSample_4_SavedByStringStream');
// 5
ss_loaded_3.Free;
ss_loaded_3 := TStringStream.Create(AnsiString(ss_loaded_2.DataString));
ss_loaded_3.SaveToFile('REF_DecodedSample_5_SavedByStringStream');
// 6
ss_loaded_3.Free;
ss_loaded_3 := TStringStream.Create(UTF8String(ss_loaded_2.DataString));
ss_loaded_3.SaveToFile('REF_DecodedSample_6_SavedByStringStream');
// 7
dataStr := ss_loaded_2.DataString;
SetLength(hexOfDataStr, 2 * Length(dataStr));
BinToHex(@dataStr[1], PAnsiChar(@hexOfDataStr[1]), Length(dataStr));
CodeSite.Send(hexOfDataStr);
ss_loaded_2.Free;
ss_loaded_3.Free;
end;
// http://www.simdesign.nl/forum/viewtopic.php?f=2&t=1311
procedure TMainForm.QuestionOfString_NativeXML;
var
LEnc, LDec: integer;
EncStream: TMemoryStream;
DecStream: TMemoryStream;
EncString: AnsiString;
DecString: AnsiString;
begin
// encode and decode streams
EncStream := TMemoryStream.Create;
DecStream := TMemoryStream.Create;
try
// load BASE64-encoded data
EncStream.LoadFromFile('REF_EncodedSample');
LEnc := EncStream.Size;
SetLength(EncString, LEnc);
EncStream.Read(EncString[1], LEnc);
// decode BASE64-encoded data, after removing control chars
DecString := DecodeBase64(sdRemoveControlChars(EncString));
LDec := length(DecString);
DecStream.Write(DecString[1], LDec);
// save the decoded data
DecStream.SaveToFile('REF_DecodedSample_7_SavedByNativeXml');
// EncString := sdAddControlChars(EncodeBase64(DecString), #$0D#$0A);
EncString := EncodeBase64(DecString);
// clear and resave encode stream as a copy
EncStream.Clear;
EncStream.Write(EncString[1], Length(EncString));
EncStream.SaveToFile('REF_EncodedSampleCopy');
finally
EncStream.Free;
DecStream.Free;
end;
end;
procedure TMainForm.QuestionOfString_NativeXML_Bytes_1;
var
LEnc, LDec: integer;
EncStream: TMemoryStream;
DecStream: TMemoryStream;
EncString: AnsiString;
DecString: AnsiString;
DecBytes: TBytes;
begin
// encode and decode streams
EncStream := TMemoryStream.Create;
DecStream := TMemoryStream.Create;
try
// load BASE64-decoded data
DecStream.LoadFromFile('REF_DecodedSample');
LDec := DecStream.Size;
SetLength(DecBytes, LDec);
DecStream.Read(DecBytes[0], LDec);
EncString := EncodeBase64(Convert(DecBytes));
// clear and resave encode stream as a copy
EncStream.Write(EncString[1], Length(EncString));
EncStream.SaveToFile('REF_EncodedSampleCopy_Bytes_1');
finally
EncStream.Free;
DecStream.Free;
end;
end;
procedure TMainForm.QuestionOfString_NativeXML_Bytes_2;
var
LEnc, LDec: integer;
EncStream: TMemoryStream;
DecStream: TStringStream;
EncString: AnsiString;
DecString: AnsiString;
DecBytes: TBytes;
begin
// encode and decode streams
EncStream := TMemoryStream.Create;
DecStream := TStringStream.Create;
try
// load BASE64-decoded data
DecStream.LoadFromFile('REF_DecodedSample');
DecBytes := DecStream.Bytes;
EncString := EncodeBase64(Convert(DecBytes));
// clear and resave encode stream as a copy
EncStream.Write(EncString[1], Length(EncString));
EncStream.SaveToFile('REF_EncodedSampleCopy_Bytes_2');
finally
EncStream.Free;
DecStream.Free;
end;
end;
end.
Run Code Online (Sandbox Code Playgroud)
示例3到7失败并不奇怪.您的文件不是文本数据,因此将其存储在文本数据结构中肯定会出现问题.每个测试都涉及将数据从一种编码转换为另一种编码.由于您的数据未编码为UTF-16文本,因此任何期望数据具有该编码的转换都将失败.
示例2可能会失败,因为您有一个奇数个字节,并且您将它存储在一个字符串中,根据定义,该字符串包含偶数个字节.在某处,将引入或删除一个字节,从而导致存储不同的数据.
除非你在处理文本,不使用TStringStream
,string
或AnsiString
.尝试TBytesStream
或TMemoryStream
改为.
随意将Base64编码的数据存储在字符串中.Base64是一种文本格式.但是一旦你解码它,它再次成为二进制文件,并且再也没有业务在文本数据结构中了.
你现在看到Nils Haeck建议你应该期待的不同结果的原因是Haeck在2007年写作,之后Delphi字符串变为Unicode并且RTL进行了任何自动代码页转换.您使用德尔福XE,这里string
是UnicodeString
.