从Amazon S3检索对象后如何从流中获取常规Delphi字符串?

问题描述 投票:0回答:1

我正在使用TAmazonStorageService类UploadObject方法将JSON字符串放入Amazon S3。当我检索对象时,它放在一个流中(我正在使用TStringStream),该流似乎是用UTF-16 LE编码的。然后,如果我尝试将该JSON加载到备忘录,TStringList或任何其他类似的对象中,那么我只会得到第一个字符,即JSON的大括号。另一方面,如果我将其写入文件,则会获得整个JSON(UTF-16 LE编码)。我假设因为UTF-16 LE用两个字节编码每个字符,而第二个字节始终为0,所以Delphi假设0是文件标记的结尾。

如何从TStringStream中获取常规的Delphi字符串(WideString)或什至是ANSIString,或者是否有我可以用来获取WideString或ANSIString的其他流。

这里是代表上传的伪代码:

procedure StorePayload( AmazonConnectionInfo: TAmazonConnectionInfo; JSONString: String;
                        PayloadMemTable: TFDAdaptedDataSet;
                        PayloadType: String; PayloadVersion: Integer);
var
  AmazonStorageService: TAmazonStorageService;
  ab: TBytes;
  ResponseInfo: TCloudResponseInfo;
  ss: TStringStream;
  Guid: TGuid;
begin
  Guid := TGuid.NewGuid;
  AmazonStorageService := TAmazonStorageService.Create( AmazonConnectionInfo );
  try
  // Write payload to S3
  ResponseInfo := TCloudResponseInfo.Create;
  try
    ss := TStringStream.Create( JSONString );
    try
      ab := StringToBytes( ss.DataString );
      if AmazonStorageService.UploadObject( BucketName, Guid.ToString, ab, false, nil, nil, amzbaPrivate, ResponseInfo ) then
        PayloadMemTable.AppendRecord( [Guid.ToString, PayloadType, PayloadVersion, now() ] );
    finally
      ss.Free;
    end;
  finally
    ResponseInfo.Free;
  end;
  finally
    AmazonStorageService.Free;
  end;
end;

这是代表JSON检索的伪代码:

function RetrievePayload( AmazonConnectionInfo: TAmazonConnectionInfo ): String;
var
  AmazonStorageService: TAmazonStorageService;
  ObjectName: string;
  ResponseInfo: TCloudResponseInfo;
  ss: TStringStream;
  OptParams: TAmazonGetObjectOptionals;
begin
  // I tried with and without the TAmazonGetObjectOptionals
  OptParams := TAmazonGetObjectOptionals.Create;
  OptParams.ResponseContentEncoding := 'ANSI';
  OptParams.ResponseContentType := 'text/plain';
  AmazonStorageService := TAmazonStorageService.Create( AmazonConnectionInfo );
  try
    ss := TStringStream.Create( );
    try
      ResponseInfo := TCloudResponseInfo.Create;
      try
        if not AmazonStorageService.GetObject( BucketName, PayloadID, OptParams, 
                                               ss, ResponseInfo, amzrNotSpecified ) then
          raise Exception.Create('Error retrieving item ' + ObjectName);
      Result := ss.DataString;
      // The memo will contain only {
      Form1.Memo1.Lines.Text := ss.DataString;
      finally
        ResponseInfo.Free;
      end;
    finally
      ss.Free;
    end;
  finally
    AmazonStorageService.Free;
  end;
end;
delphi amazon-s3 unicode-string utf-16le
1个回答
0
投票

[在Delphi 2009及更高版本中,String是UTF-16 UnicodeString,但是TStringStream默认情况下在8位ANSI上运行(以与Unicode以前的Delphi版本向后兼容)。

完全不需要StorePayload()使用TStringStream。您将String存储到流中只是为了从中读取String。因此,请照原样使用原始的String

也不需要使用StringToBytes()。您可以并且应该使用TEncoding.UTF8代替,因为UTF-8是JSON数据的首选编码,例如:

procedure StorePayload( AmazonConnectionInfo: TAmazonConnectionInfo; JSONString: String;
                        PayloadMemTable: TFDAdaptedDataSet;
                        PayloadType: String; PayloadVersion: Integer);
var
  AmazonStorageService: TAmazonStorageService;
  ab: TBytes;
  ResponseInfo: TCloudResponseInfo;
  Guid: TGuid;
begin
  Guid := TGuid.NewGuid;
  AmazonStorageService := TAmazonStorageService.Create( AmazonConnectionInfo );
  try
    // Write payload to S3
    ResponseInfo := TCloudResponseInfo.Create;
    try
      ab := TEncoding.UTF8.GetBytes( JSONString );
      if AmazonStorageService.UploadObject( BucketName, Guid.ToString, ab, false, nil, nil, amzbaPrivate, ResponseInfo ) then
        PayloadMemTable.AppendRecord( [Guid.ToString, PayloadType, PayloadVersion, Now() ] );
    finally
      ResponseInfo.Free;
    end;
  finally
    AmazonStorageService.Free;
  end;
end;

相反,当RetrievePayload()之后调用GetObject()时,可以将TEncoding.UTF8TStringStream一起使用来解码String,例如:

function RetrievePayload( AmazonConnectionInfo: TAmazonConnectionInfo ): String;
var
  AmazonStorageService: TAmazonStorageService;
  ResponseInfo: TCloudResponseInfo;
  ss: TStringStream;
begin
  AmazonStorageService := TAmazonStorageService.Create( AmazonConnectionInfo );
  try
    ss := TStringStream.Create( '', TEncoding.UTF8 );
    try
      ResponseInfo := TCloudResponseInfo.Create;
      try
        if not AmazonStorageService.GetObject( BucketName, PayloadID, ss, ResponseInfo, amzrNotSpecified ) then
          raise Exception.Create('Error retrieving item ' + ObjectName);
        Result := ss.DataString;
        Form1.Memo1.Text := Result;
      finally
        ResponseInfo.Free;
      end;
    finally
      ss.Free;
    end;
  finally
    AmazonStorageService.Free;
  end;
end;
© www.soinside.com 2019 - 2024. All rights reserved.