Делает ли StringOf копию переданных ему данных? - PullRequest
3 голосов
/ 23 декабря 2011

Я читаю в файле, пытаясь проверить, является ли это двоичным файлом, проверяя первые n байтов для байта NUL, и если он не определен как двоичный, то это манипулировать как строка. Я попытался перебрать строку и проверить первые n индексы для NUL, но это дало бы ложные срабатывания, что проверка TBytes не делает.

Я использую TFile.ReadAllBytes, который возвращает TBytes и выполняю проверку NUL на этом. Затем, если NUL не найден, я использую StringOf на TBytes, чтобы получить строку. Мне было интересно, нужно ли StringOf сделать копию данных, чтобы из нее сделать строку (это большие файлы, поэтому я хочу этого избежать), и если да, то как лучше сделать то, что я пытаюсь сделать? делаем.

Ответы [ 3 ]

3 голосов
/ 23 декабря 2011

Делает ли StringOf копию переданных ему данных?

Да, в соответствии с документами : '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.
Предположим, у вас есть гигабайт (ы) данных, и вы спешите.
Файловый поток позволит вам просто прочитать небольшой фрагмент данных, ускоряя процесс.

Этот пример кода читает весь файл, но его можно легко изменить, чтобы получить только небольшую часть:

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 символ = 1 байт: -).

1 голос
/ 23 декабря 2011

Если вы считаете, что StringOf - это просто приведение типов на месте, вы ошибаетесь.
StringOf обрабатывает свой аргумент как массив символов в кодировке кодовой страницы системы ANSI по умолчанию и преобразует его в кодировку Unicode UTF16.Конечно, вы найдете много нулевых байтов в результирующей строке (старшие байты WideChar's).

1 голос
/ 23 декабря 2011
  1. Использование TFile.ReadAllBytes
  2. Выполните проверку на наличие байтов NUL (имейте в виду, что UTF-16 будет содержать много NUL)
  3. Если это строка, используйте SetLength для увеличения ТБ на 1 или 2 байта (в зависимости от кодировки)
  4. Добавить 1 или 2 NUL в конце (снова зависит от кодировки)
  5. Приведите @Bytes [0] к PAnsiChar / PWideChar (в зависимости от кодировки)

Вы можете найти кодировку, посмотрев на спецификацию. Конечно, это зависит от того, как ваши входные файлы закодированы.

Однако SetLength может сделать копию данных.

...