将以null结尾的内存流转换为unicode字符串

时间:2011-01-19 17:39:48

标签: delphi memorystream unicode-string null-terminated

在Delphi XE中,我从剪贴板中捕获CF_UNICODETEXT数据。结果是一个以两个空字节终止的流。要获取复制到剪贴板的实际字符串,我需要删除空值。

This similar so question包含一个从TMemoryStream转换为Delphi的unicode字符串的好方法:

function MemoryStreamToString(M: TMemoryStream): string;
begin
  SetString(Result, M.Memory, M.Size div SizeOf(Char));
end;

然而,在我的情况下,这会产生一个包含尾随空值的字符串。我可以通过限制大小来解决这个问题:

function ClipboardMemoryStreamToString(M: TMemoryStream): string;
begin
  SetString(Result, M.Memory, (M.Size - SizeOf(Char)) div SizeOf(Char));
end;

......但这感觉很难看,“特殊情况”。我想知道是否有更简洁的方法对此进行编码,以便后来查看代码的任何人(我!)都不会立即询问“为什么会从流中删除尾随的字符?”

编辑:预先解决问题的一种方法是添加评论。但是,除此之外?

2 个答案:

答案 0 :(得分:5)

Clipboard.AsText出了什么问题?它为您完成所有操作,无需流,按字节戳,处理空终止符等。

至于你提出的确切问题,我只想写:

SetString(Result, M.Memory, M.Size div SizeOf(Result[1]) - 1);

答案 1 :(得分:2)

如果您定位CF_UNICODETEXT,则需要专门指定 unicode 字符串:

// For old Delphi versions
{$IFNDEF UNICODE}
type
  UnicodeString = WideString;
{$ENDIF}

// For CF_TEXT
function MemoryStreamToAnsiString(M: TMemoryStream): AnsiString;
begin
  SetString(Result, M.Memory, M.Size);
  if (Result <> '') and (Result[Length(Result)] = #0) then
    SetLength(Result, Length(Result) - 1);
end;

// For CF_UNICODETEXT
function MemoryStreamToUnicodeString(M: TMemoryStream): UnicodeString;
begin
  SetString(Result, M.Memory, M.Size div SizeOf(WideChar));
  if (Result <> '') and (Result[Length(Result)] = #0) then
    SetLength(Result, Length(Result) - 1);
end;

// I'm not sure that you should use this form
function MemoryStreamToString(M: TMemoryStream): String;
begin
  SetString(Result, M.Memory, M.Size div SizeOf(Char));
  if (Result <> '') and (Result[Length(Result)] = #0) then
    SetLength(Result, Length(Result) - 1);
end;

如果你100%确定字符串是零终止的,那么:

// For CF_TEXT
function MemoryStreamToAnsiString(M: TMemoryStream): AnsiString;
begin
  SetString(Result, M.Memory, M.Size - 1);
end;

// For CF_UNICODETEXT
function MemoryStreamToUnicodeString(M: TMemoryStream): UnicodeString;
begin
  SetString(Result, M.Memory, (M.Size div SizeOf(WideChar)) - 1);
end;

function MemoryStreamToString(M: TMemoryStream): String;
begin
  SetString(Result, M.Memory, (M.Size div SizeOf(Char)) - 1);
end;