当TStringStream加载二进制非文本文件时,为什么TStringStream.Da
>正如专家建议的那样,TStringStream.DataString不能用于检索由TStringStream.LoadFromFile加载的非文本数据,因为TStringStream.GetDataString将调用TEncoding的编码方法,例如,以TMBCSEncoding为例,将调用TMBCSEncoding.GetChars反过来调用TMBCSEncoding.UnicodeFromLocaleChars,最后是
Windows的MultiByteToWideChar.
>建议将TBytes用作数据缓冲区/二进制存储. (为此,建议使用TBytes而不是AnsiString.) >可以从TStringStream.ReadBuffer方法或TStringStream.Bytes属性中检索字节.无论哪种方式,都应该考虑TStream.Size. ================================================== == 我试图使用TStringStream及其DataString进行base64编码/解码.似乎有可能如Nils Haeck的回复here或here所示. >在TMainForm.QuestionOfString_StringStream(No.2至No.7)中使用TStringStream.DataString失败,因为信息已损坏(即,与原始信息不同).但是,ss_loaded_2.SaveToFile(No.1)保存原始信息,表明TStringStream在内部正确保存解码的非文本数据?你能帮忙评论一下DataString损坏的可能原因吗? 非常感谢您的帮助! 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} // https://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. 解决方法
示例3到7失败并不奇怪.您的文件不是文本数据,因此将其存储在文本数据结构中肯定会出现问题.每个测试都涉及将数据从一种编码转换为另一种编码.由于您的数据未编码为UTF-16文本,因此任何期望数据具有该编码的转换都将失败.
示例2可能会失败,因为您有一个奇数个字节,并且您将它存储在一个字符串中,根据定义,该字符串包含偶数个字节.在某处,将引入或删除一个字节,从而导致存储不同的数据. 除非您正在处理文本,否则请不要使用TStringStream,string或AnsiString.请尝试使用TBytesStream或TMemoryStream. 随意将Base64编码的数据存储在字符串中. Base64是一种文本格式.但是一旦你解码它,它再次成为二进制文件,并且再也没有业务在文本数据结构中了. 你现在看到Nils Haeck建议你应该期待的不同结果的原因是Haeck在2007年写作,之后Delphi字符串变为Unicode并且RTL进行了任何自动代码页转换.你正在使用Delphi XE,其中string是UnicodeString. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |