Ошибка из-за кавычки после преобразования файла в строку с Delphi XE? - PullRequest
0 голосов
/ 16 мая 2011

У меня неверный результат при преобразовании файла в строку в Delphi XE.Есть несколько ' символов, которые делают результат неверным.Я использовал UnicodeFileToWideString и FileToString из http://www.delphidabbler.com/codesnip и мой код:

 function LoadFile(const FileName: TFileName): ansistring;
  begin
    with TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite) do
    begin
      try
        SetLength(Result, Size);
        Read(Pointer(Result)^, Size);
        // ReadBuffer(Result[1], Size);
      except
        Result := ''; 
        Free;
      end;
      Free;
    end;
  end;

Результат между Delphi XE и Delphi 6 отличается.Результат от D6 правильный.Я сравнил с результатом программы hex редактора.

Ответы [ 3 ]

1 голос
/ 16 мая 2011

Ваш вывод создается в стиле отладчика Delphi, который отображает строковые переменные в собственном строково-литеральном формате Delphi. Независимо от того, какую функцию вы используете для создания этого вывода из вашей собственной программы, для Delphi XE на самом деле зафиксировано . Это действительно ваш вывод Delphi 6, который неверен.

Строковые литералы Delphi состоят из серии печатаемых символов между апострофами и серии непечатаемых символов, обозначенных цифровыми знаками и числовыми значениями каждого символа. Чтобы представить апостроф, напишите два из них рядом друг с другом. Печатные и непечатные серии символов могут быть написаны не друг другу; нет необходимости объединять их с оператором +.

Вот выдержка из вывода, который вы считаете правильным:

#$12'O)=ù'dlû'#6't

В этой строке четыре одиноких апострофа, поэтому каждый из них либо открывает, либо закрывает серию печатных символов. Мы не обязательно знаем, что именно, когда мы начинаем читать строку слева, потому что символы #, $, 1 и 2 могут быть напечатаны самостоятельно. Но если они представляют печатные символы, то символы 0, ), = и ù находятся в области, недоступной для печати, и этого не может быть. Следовательно, первый апостроф над открывает печатную серию, а часть #$12 представляет символ в коде 18 (12 в шестнадцатеричном формате). После ù еще один апостроф. Поскольку предыдущая открыла строку для печати, эта должна закрыть ее. Но следующий символ после этого - d, который не является #, и поэтому не может быть началом непечатаемого символьного кода. Поэтому эта строка из вашего кода Delphi 6 сформирована некорректно.

Правильная версия этого отрывка такова:

#$12'O)=ù''dlû'#6't

Теперь есть три одиноких апострофов и один набор удвоенных апострофов. Проблемный апостроф из предыдущей строки был удвоен, что указывает на то, что это буквальный апостроф, а не закрывающий строку для печати. Серия печати продолжается с dlû. Затем он закрывается для вставки символа № 6, а затем снова открывается для t. Апостроф, открывающий всю строку в начале файла: неявный .

Вы не указали, какой код вы используете для создания вывода, который вы показали, но это , где проблема была. Его больше нет, и код, который загружает файл, является правильным, поэтому единственное место, которое требует вашего внимания при отладке, - это любой код, который зависел от старого, неправильного формата. Вам все равно стоит заменить свой код на из кода Robmil , поскольку он лучше обрабатывает (или не обрабатывает) исключения и пустые файлы.

0 голосов
/ 17 мая 2011

На самом деле, глядя на реальные данные, ваша проблема в том, что в файле хранятся двоичные данные, а не строковые данные, поэтому интерпретация этого как строки недопустима вообще. Единственная причина, по которой он работает в Delphi 6, заключается в том, что не-Unicode Delphi позволяет обрабатывать двоичные данные и строки одинаково. Вы не можете делать это в Unicode Delphi, как и вы.

Решение, чтобы получить фактический текст из файла, состоит в том, чтобы прочитать файл как двоичные данные, а затем скопировать любые значения из этих двоичных данных, по одному байту за раз, в строку, если это «действительный» Ansi символ (для печати).

0 голосов
/ 16 мая 2011

Я предложу код:

function LoadFile(const FileName: TFileName): AnsiString;
begin
  with TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite) do
  try
    SetLength(Result, Size);
    if Size > 0 then
      Read(Result[1], Size);
  finally
    Free;
  end;
end;
...