StringOf是否传递了传递给它的数据的副本?

时间:2011-12-23 09:01:46

标签: string delphi byte delphi-xe

我正在读取一个文件,试图通过检查NUL字节的第一个 n 字节来检查它是否是二进制文件,如果不确定它是二进制文件,那么它被操纵为一个字符串。我试图循环一个字符串并检查NUL的第一个 n 索引,但这会产生误报,检查TBytes不会。

我使用TFile.ReadAllBytes,它返回TBytes并对其执行NUL检查。然后,如果没有找到NUL,我会在StringOf上使用TBytes来获取字符串。我想知道StringOf是否必须制作数据的副本以从中创建一个字符串(这些是大文件,所以我想避免这种情况)如果是这样,那么什么是更好的方法来做我自己的事情试图做。

3 个答案:

答案 0 :(得分:3)

  

StringOf是否会传递传递给它的数据的副本?

是的,according to the docs'Converts a byte array into a Unicode string using the default system locale.'

如果您只想将TBytes作为字符串访问,为什么不将它转换为PChar(如果是Unicode)或PAnsiChar(如果它是AnsiString)?

示例代码:

var
  MyBuffer: TBytes;
  BufferLength: integer;
  BufferAsString: PChar;
  BuferAsAnsiString: PAnsiChar;
begin
  MyBuffer:= TFile.ReadAllBytes(Filename);
  BufferLength:= SizeOf(MyBuffer);
  BufferAsString:= PChar(@MyBuffer[0]);
  BufferAsAnsiString:= PAnsiChar(@MyBuffer[0]);
  //if there's no #0 at the end, make sure not to read past the end of the buffer!

修改
我有点困惑,为什么你不只是使用TFile.OpenRead来获取FileStream 我们假设您已经获得了数十亿字节的数据,而且您很着急 Filestream将允许您只读取一小部分数据,从而加快速度。

此示例代码读取整个文件,但可以轻松修改为仅获得一小部分:

var
  MyData: TFileStream
  MyString: string;  {or AnsiString}
  FileSize: integer;
  Index: integer;
begin
  MyData:= TFile.OpenRead(Filename);
  try
    FileSize:= MyData.GetSize;
    SetLength(MyString,FileSize+1); //Preallocate the string;
    Index:= 0;
    MyData.Read(PChar(MyString[Index])^, FileSize);
  finally
    MyData.Free;
  end;
  //Do stuff with your newly read string.  

请注意,最后一个示例仍然首先从磁盘读取所有数据(可能是您想要的也可能不是)。 但是,您也可以以块的形式读取数据 使用AnsiStrings,所有这一切都更简单,因为1 char = 1个字节: - )。

答案 1 :(得分:1)

  1. 使用TFile.ReadAllBytes
  2. 检查NUL字节(请注意,UTF-16将包含大量NUL)
  3. 如果是字符串,请使用SetLength将TBytes增加1或2个字节(取决于编码)
  4. 在最后添加1或2个NUL(取决于再次编码)
  5. 将@Bytes [0]转换为PAnsiChar / PWideChar(取决于编码)
  6. 您可以通过查看BOM找到编码。这取决于输入文件的编码方式。

    SetLength可能会复制数据。

答案 2 :(得分:1)

如果您认为StringOf只是一个就地类型转换,那么您错了 StringOf将其参数视为默认系统ANSI代码页编码中的字符数组,并将其转换为UTF16 unicode编码。当然,你会在结果字符串中找到很多零字节(WideChar的高位字节)。