Заменить строку, содержащую #0?

Я использую эту функцию для чтения файла в строку

function LoadFile(const FileName: TFileName): string;
begin
  with TFileStream.Create(FileName,
      fmOpenRead or fmShareDenyWrite) do begin
    try
      SetLength(Result, Size);
      Read(Pointer(Result)^, Size);
    except
      Result := '';  
      Free;
      raise;
    end;
    Free;
  end;
end;

Вот текст файла:

version  

Вот возвращаемое значение LoadFile:

'ÿþv'#0'e'#0'r'#0's'#0'i'#0'o'#0'n'#0

Я хочу, чтобы новый файл содержал "verabc". Проблема в том, что у меня все еще есть проблема с заменой «sion» на «abc». Я использую D2007. Если я удалю все # 0, результат станет китайским иероглифом.


person Ina Ira    schedule 01.07.2010    source источник


Ответы (2)


То, что вы считаете текстом файла, на самом деле не является текстом файла. То, что вы прочитали в своей строковой переменной, является точным. У вас есть текстовый файл Unicode, закодированный как UTF-16 с прямым порядком байтов. Первые два байта представляют собой метку порядка байтов, а каждая пара байтов после этого — еще один символ строки.

Если вы читаете файл Unicode, вы должны использовать тип данных Unicode, например WideString. Вы захотите разделить размер файла на два при установке длины строки и отбросить первые два байта.

Если вы не знаете, какой файл вы читаете, вам нужно сначала прочитать первые два или три байта. Если первые два байта равны $ff $fe, как указано выше, то у вас может быть файл UTF-16 с прямым порядком байтов; прочитайте остальную часть файла в WideString или UnicodeString, если у вас есть этот тип. Если они $fe $ff, то это может быть обратный порядок байтов; прочитайте оставшуюся часть файла в WideString, а затем поменяйте местами порядок каждой пары байтов. Если первые два байта равны $ef $bb, проверьте третий байт. Если это $bf, то, вероятно, это знак порядка байтов UTF-8. Отбросьте все три и прочитайте оставшуюся часть файла в AnsiString или массив байтов, а затем используйте функцию, подобную UTF8Decode, чтобы преобразовать ее в WideString.

Как только ваши данные будут помещены в WideString, отладчик покажет, что он содержит version, и у вас не должно возникнуть проблем с использованием версии StringReplace с поддержкой Unicode для замены.

person Rob Kennedy    schedule 01.07.2010
comment
Роб, я создаю файл с помощью блокнота и заполняю версию, а затем, используя функцию выше, у меня все еще есть символ юникода в моей переменной. Это правило? Я использую D2007 и Vista. - person Ina Ira; 01.07.2010
comment
ах извините, у моего редактора проблемы. Я открываю файл блокнотом, и все идет хорошо! - person Ina Ira; 01.07.2010
comment
Судя по всему, кодировка по умолчанию в Висте UTF-16. Пора. Если вам действительно нужна другая кодировка, используйте диалоговое окно «Сохранить как» и выберите что-то другое. Все идет хорошо, когда вы открываете файл в Блокноте, потому что он использует процедуру, описанную в моем ответе. Это даже немного сложнее, поскольку также учитывает кодировку ANSI. - person Rob Kennedy; 01.07.2010

Кажется, вы загружаете текстовый файл в кодировке Unicode. 0 означает латинский символ.

Если вы не хотите иметь дело с текстом Unicode, выберите кодировку ANSI в редакторе при сохранении файла.

Если вам нужна кодировка Unicode, используйте WideCharToString, чтобы преобразовать ее в строку ANSI, или просто удалите 0, хотя последнее — не лучшее решение. Также удалите два начальных символа, ÿþ.
Редактор поместил эти байты в отметить файл как юникод.

person Nick Dandoulakis    schedule 01.07.2010
comment
0 указывает на английский язык? Какое значение указывает на клингонский язык? :) - person mjn; 01.07.2010
comment
0 означает латиницу? Si tacuisses ... :) - person mjn; 01.07.2010