4
  1. 専門家が親切に提案したように、によってロードされたデータを取得するためTStringStream.DataStringに使用することはできません。これは、のエンコーディングメソッドを呼び出すためです。たとえば、を呼び出し、次にを呼び出し、最後にを呼び出します。non-textTStringStream.LoadFromFileTStringStream.GetDataStringTEncodingTMBCSEncodingTMBCSEncoding.GetCharsTMBCSEncoding.UnicodeFromLocaleCharsWindowsMultiByteToWideChar

  2. TBytesは、データバッファ/バイナリストレージとして使用することをお勧めします。(この目的のために、AnsiStringよりもTBytesをお勧めします。)

  3. は、メソッドまたはプロパティbytesから取得できます。いずれにせよ、検討する必要があります。TStringStream.ReadBufferTStringStream.BytesTStream.Size

================================================== ==

私はbase64のエンコード/デコードの目的でTStringStreamそれを使用しようとしています。ここまたはここでの返信でDataString示されているように、それは可能のようです。Nils Haeck

  1. TStringStream.DataStringin TMainForm.QuestionOfString_StringStream(No.2〜No.7)を使用すると、情報が破損している(つまり、元の情報と同じではない)という点で失敗します。しかし、ss_loaded_2.SaveToFile(No.1)は元の情報を保存しており、TStringStreamデコードされた非テキストデータを内部で正しく保持していることを示していますか?DataStringの破損の考えられる理由についてコメントしていただけますか?

  2. Rob Kennedyの親切な回答の中で、彼はbase64でデコードされた非テキストデータを保存する際に言及したstringansistring、避けるべきであり、これは非常に理にかなっています。ただし、に示すようにTMainForm.QuestionOfString_NativeXMLDecStringofAnsiStringタイプにはデコードされたバイトが含まれているため、データをエンコードして戻すことができます。これは、AnsiStringがデコードされた非テキストデータをそのまま保持できることを意味しますか?

  3. David HeffernanそしてRob Kennedybytes/TBytesについて親切にコメントしました。ただし、でbytes抽出されたは、ののとTMainForm.QuestionOfString_NativeXML_Bytes_1は異なります。(Base64でのエンコード/デコードの結果から、間違っています。上記の段落に基づいて、内部にそのままのバイトが含まれている必要があるため、混乱しますか?)考えられる理由についてコメントしていただけますか?TStringStreamBytesTMainForm.QuestionOfString_NativeXML_Bytes_2TStringStream.BytesTStringStream

ご助力ありがとうございます!

PS:サンプルファイルはSkyDriveからダウンロードできます:REF_EncodedSample&REF_DecodedSample。(Zlibで圧縮された画像ファイル。)

PS:Delphi XE、Windows7(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.
4

2 に答える 2

9

例3から7が失敗するのは当然のことです。ファイルはテキストデータではないため、テキストデータ構造に保存すると問題が発生します。これらの各テストには、データを1つのエンコーディングから別のエンコーディングに変換することが含まれます。データはそもそもUTF-16テキストとしてエンコードされていないため、データにそのエンコードが含まれていることを期待する変換は失敗します。

例2は、バイト数が奇数であり、定義上偶数バイトを含む文字列に格納しているため、おそらく失敗します。どこかで、バイトが導入または削除され、さまざまなデータが格納されます。

テキストを扱っている場合を除いて、、、、またはを使用TStringStreamしないでください。または代わりに試してください。stringAnsiStringTBytesStreamTMemoryStream

Base64でエンコードされたデータを文字列に自由に保存してください。Base64はテキスト形式です。しかし、一度デコードすると、再びバイナリになり、テキストデータ構造に組み込まれることはなくなります。

Nils Haeckが予想した結果とは異なる結果が表示される理由は、Delphi文字列がUnicodeになり、RTLが自動コードページ変換を行う前の2007年にHaeckが記述していたためです。DelphiXEを使用しています。ここstringUnicodeString

于 2012-07-05T14:59:27.363 に答える
3

D2009 +から派生したものであり、以前のバージョン から直接派生したTStringStreamものは考慮されていません。コードが期待するのとは異なる方法でメモリを割り当てます。プロパティは、割り当てるメモリブロック全体を表しますが、そのメモリの内容全体が実際のデータで満たされることを意味するわけではありません。コードが無視する必要のある余分なパディングがいくつかあります。TMemoryStreamTByteStreamTStreamTMemoryStreamTByteStream.BytesTMemoryStream

コードが失敗する理由の詳細については、他の質問に対する私の回答を参照してください。

于 2012-07-05T22:56:15.547 に答える