Ошибка чтения текстового файла Delphi xe8, созданного из версии Delphi 7, и наоборот

Я пытаюсь преобразовать код из Delphi 7 в delphi xe8 и не могу найти решение для следующего случая.

Наше старое приложение создает текстовый файл, первая строка которого выглядит так

±HEADER―ID°N1799―USER_ID°N1―PATH_NAME―R_DATABASE°TC:\DATA―R_SERVER°TTEST_SRV―R_COMPUTER°TMYPC―

Char(―) — это chr(175).

Мы попытались прочитать уже созданный файл из нашего нового приложения с Delphi xe8 следующим образом:

  StrData := TStringList.Create;
  StrData.LoadFromFile(sFile);

StrData.Text возвращает нужный текст, но chr(175) заменяется на chr(8213).

Чтобы продолжить, я сделал следующее:

  StrData.LoadFromFile(sFile,TEncoding.ANSI);  
  StrData.Text := StringReplace(StrData.Text,Chr(8213),Chr(175),[rfReplaceAll]);

Чего я не могу решить, так это обратного случая.

Я должен создать этот файл из Delphi xe8, чтобы он был точно таким же, как и файл, созданный из старого приложения Delphi 7.

В начале я использовал тот же код, что и у нас:

StrData.SavetoFile(sFile); //returns text but chr(175) is replaced with (?)

Также я пробовал все кодировки безрезультатно.

StrData.SavetoFile(sFile,Ansi);//returns text but chr(175) is replaced with (?) etc.

То же самое происходит и при преобразовании кода в TStreamFile или текстовый файл.

файлы кодирования base64

Старый - правильный (StrData.SavetoFile(sFile)) //Delphi 7

wrFIRUFERVLigJVJRMKwTjE4NjbigJVSSUTCsE4zNjHigJVDU0lURV9JRMKwTjHigJVSU0lURV9JRMKwTjEwMeKAlVNTSVRFX0lEwrBOMeKAlVRSTl9EQVRFwrBENDIzODIuNjA2NzkzOTgxNeKAlVVTRVJfSUTCsE4x4oCVUEFUSF9OQU1FwrBUXFxkZWxwaGkyMDEycjJcQkVORUZJVF9URVNUXFBBX09GRklDRV9WU0xcVFJBTlNGRVJcRVhQT1JU4oCVRklMRV9OQU1FwrBUQU5BRDM2MU0udHh04oCVRklMRV9UWVBFwrBO4oCVUENLX1NFTkRFUsKwVEFkbWlu4oCVUENLX05PVEVTwrBU4oCVX1JWX0lEMcKwTuKAlVNWX0lEwrBO4oCVUlZfSUTCsE7igJVSREJfSUTCsE4xMeKAlVNEQl9JRMKwTjEx4oCVUENLX0NOWFTCsFQwMywxNSw3MiwwMOKAlUtFWUlEwrBUezczRDIwMDU3LTM3NTgtNDlDMi05NTlGLTA4QzYxMDY4NEZGNn3igJVGTF9UWVBFwrBOMuKAlUZMX1NUQVRVU8KwTjDigJVTVEFSVF9EVMKwRDQyMzgyLjYwNjQ5MzA1NTbigJVSX1NUQVJUX0RUwrBE4oCVUl9FTkRfRFTCsETigJVSX1VTRVLCsFTigJVSX1BBVEjCsFTigJVTSVpFX1BDS8KwTuKAlVNJWkVfREFUQcKwTuKAlVNJWkVfQVRDSMKwTuKAlVNJWkVfRE9DU8KwTuKAlURBVEVfSU7CsETigJVSX0RBVEFCQVNFwrBU4oCVUl9TRVJWRVLCsFTigJVSX0NPTVBVVEVSwrBU4oCV

StrData.SavetoFile(sFile,Tencoding.Ansi); & StrData.SavetoFile(sFile); //ХЕ8

wrFIRUFERVI / SUTCsE4xODY3P1JJRMKwTjM2Mj9DU0lURV9JRMKwTjE / UlNJVEVfSUTCsE4xMDE / U1NJVEVfSUTCsE4xP1RSTl9EQVRFwrBENDIzODIuNzA3NzA4MzMzMz9VU0VSX0lEwrBOMT9QQVRIX05BTUXCsFRcXGRlbHBoaTIwMTJyMlxCRU5FRklUX1RFU1RcUEFfT0ZGSUNFX1ZTTFxUUkFOU0ZFUlxFWFBPUlQ / RklMRV9OQU1FwrBUQU5BRDM2Mk0udHh0P0ZJTEVfVFlQRcKwTj9QQ0tfU0VOREVSwrBUQWRtaW4 / UENLX05PVEVTwrBOP19SVl9JRDHCsE4 / U1ZfSUTCsE4 / UlZfSUTCsE4 / UkRCX0lEwrBOMTE / U0RCX0lEwrBOMTE / UENLX0NOWFTCsFQwMywxNSw3MiwwMD9LRVlJRMKwVHtGQzM1N0QyNC1EQjRBLTRBOUMtQkE3My0xQ0FBMEVFRDUzOUJ9P0ZMX1RZUEXCsE4yP0ZMX1NUQVRVU8KwTjA / U1RBUlRfRFTCsEQ0MjM4Mi43MDcyNjg1MTg1P1JfU1RBUlRfRFTCsEQ / Ul9FTkRfRFTCsEQ / Ul9VU0VSwrBUP1JfUEFUSMKwVD9TSVpFX1BDS8KwTj9TSVpFX0RBVEHCsE4 / U0laRV9BVENIwrBOP1NJWkVfRE9DU8KwTj9EQVRFX0lOwrBEP1JfREFUQUJBU0XCsFQ / Ul9TRVJWRVLCsFQ / Ul9DT01QVVRFUsKwVD8 =

StrData.SavetoFile(sFile,Tencoding.UTF8); //ХЕ8

wrFIRUFERVLCr0lEwrBOMTg3MMKvUklEwrBOMzY1wq9DU0lURV9JRMKwTjHCr1JTSVRFX0lEwrBOMTAxwq9TU0lURV9JRMKwTjHCr1RSTl9EQVRFwrBENDIzODIuNzIyODEyNcKvVVNFUl9JRMKwTjHCr1BBVEhfTkFNRcKwVFxcZGVscGhpMjAxMnIyXEJFTkVGSVRfVEVTVFxQQV9PRkZJQ0VfVlNMXFRSQU5TRkVSXEVYUE9SVMKvRklMRV9OQU1FwrBUQU5BRDM2NU0udHh0wq9GSUxFX1RZUEXCsE7Cr1BDS19TRU5ERVLCsFRBZG1pbsKvUENLX05PVEVTwrBOwq9fUlZfSUQxwrBOwq9TVl9JRMKwTsKvUlZfSUTCsE7Cr1JEQl9JRMKwTjExwq9TREJfSUTCsE4xMcKvUENLX0NOWFTCsFQwMywxNSw3MiwwMMKvS0VZSUTCsFR7ODE5REQ0NDQtQzEwQi00MTY1LUFEQjAtQkI2NDAyRjA3NUI4fcKvRkxfVFlQRcKwTjLCr0ZMX1NUQVRVU8KwTjDCr1NUQVJUX0RUwrBENDIzODIuNzIyNTIzMTQ4McKvUl9TVEFSVF9EVMKwRMKvUl9FTkRfRFTCsETCr1JfVVNFUsKwVMKvUl9QQVRIwrBUwq9TSVpFX1BDS8KwTsKvU0laRV9EQVRBwrBOwq9TSVpFX0FUQ0jCsE7Cr1NJWkVfRE9DU8KwTsKvREFURV9JTsKwRMKvUl9EQVRBQkFTRcKwVMKvUl9TRVJWRVLCsFTCr1JfQ09NUFVURVLCsFTCrw ==

Есть идеи?


person P.A    schedule 13.01.2016    source источник
comment
Это не звучит правдоподобно. Пожалуйста, не могли бы вы закодировать свой текстовый файл в base64, отредактировать его в вопросе и дать нам взглянуть на него.   -  person David Heffernan    schedule 13.01.2016
comment
@ Дэвид Хеффернан, извините, но я не понял, что именно вы хотите, чтобы я сделал. Не могли бы вы быть более конкретным, пожалуйста?   -  person P.A    schedule 13.01.2016
comment
Кажется достаточно простым. Какой бы текстовый файл у вас ни был, запустите его через кодировщик Base64 и поделитесь результатом здесь, в своем вопросе.   -  person Jerry Dodge    schedule 13.01.2016
comment
@ Кен Уайт, в моем случае «E» и «R» могут быть любыми символами. Мне кажется сложным заменить этого персонажа таким образом. Кстати, этот символ создается из кода с помощью chr(175).   -  person P.A    schedule 13.01.2016
comment
Мы хотели бы увидеть настоящий файл. То, что вы описываете, не стыкуется. Вы описали свой файл. Мы можем помочь свойству, если мы можем видеть фактический файл. Если вы закодируете его в base64, мы будем знать, что у нас точно такой же файл. Вызов StringReplace явно неверен.   -  person David Heffernan    schedule 13.01.2016
comment
Не могли бы вы поместить этот файл (или его начало) на какой-нибудь файлообменный сервер для проверки бинарного содержимого?   -  person MBo    schedule 13.01.2016
comment
@MBo Тогда ссылка устареет. Кодировка Base64, и это будет длиться вечно.   -  person David Heffernan    schedule 13.01.2016
comment
@David Heffernan Мне пока не ясно - может ли автор изменить старое приложение.   -  person MBo    schedule 13.01.2016
comment
@MBo Вопрос о коде в XE8, поэтому предполагается, что старая программа исправлена.   -  person David Heffernan    schedule 13.01.2016
comment
@MBo нет, я не могу изменить старое приложение. Это проблема.   -  person P.A    schedule 13.01.2016
comment
Я вижу, что двоичные данные имеют (65001) кодировку UTF-8.   -  person MBo    schedule 13.01.2016


Ответы (1)


Файл, сохраненный вашей программой Delphi 7, имеет кодировку UTF-8. Я расшифровал base64, который вы предоставили, и посмотрите на него в шестнадцатеричном редакторе. Это выглядит так:

введите здесь описание изображения

Первые два байта C2 B1. Это кодировка UTF-8 для ±. Вы можете проверить это здесь: https://mothereff.in/utf-8.

Используйте LoadFromFile(..., TEncoding.UTF8) для загрузки файла и SaveToFile(..., TEncoding.UTF8) для его сохранения. Это все, что вам нужно сделать. Обратите внимание, что при сохранении таким образом в файл будет включена спецификация. Если это нежелательно, можно опустить спецификацию, как было описано здесь ранее.

Обратите внимание, что вы должны удалить вызов StringReplace. Это изменяет текст и не служит никакой полезной цели. Вы абсолютно не хотите заменять U+2015 ― на U+00AF ¯.

Основываясь на комментариях к этому ответу, кажется, что у вас есть код Delphi 7, который создает текст в кодировке UTF-8, который ведет себя неправильно при выполнении Delphi XE8. Это неудивительно из-за перехода с ANSI на UTF-16. Вам нужно будет пересмотреть этот код и адаптировать его соответствующим образом. Мы не можем сказать больше, учитывая тот факт, что этот код есть только у вас.

Такое ощущение, что вы пробуете что-то почти наугад и надеетесь на быстрое решение. Это не продуктивно. Вы добьетесь прогресса только с четким пониманием Unicode и вашей программы. Вам нужно будет сделать шаг назад, замедлиться и заполнить пробелы в своих знаниях.

person David Heffernan    schedule 13.01.2016
comment
SaveToFile(..., TEncoding.UTF8) приводит к третьему закодированному файлу, который не совпадает с первым. - person P.A; 13.01.2016
comment
Здесь работает нормально. Единственное отличие состоит в том, что при сохранении с использованием TEncoding.UTF8 вы получите спецификацию, а в исходном файле спецификации не было. В любом случае, я расшифровал файлы и показал вам, что такое кодировка. Я думаю, что следующим шагом для вас будет взять эти знания и убедиться, что вы полностью понимаете, что происходит. Мы не можем вам помочь с мельчайшими деталями вашей реальной программы. - person David Heffernan; 13.01.2016
comment
Глядя на этот третий файл в вашем вопросе, это результат вашего кода, который все еще использует StringReplace для изменения содержимого. Прочитайте последний абзац в моем ответе, пожалуйста. - person David Heffernan; 13.01.2016
comment
Нет, это не так. Я использовал замену только при загрузке. Процедура создания совсем другая и файл новый не модифицированный) - person P.A; 13.01.2016
comment
Начиная с первого файла в кодировке base64, я декодировал его в двоичный код. Я заметил, что это кодировка UTF-8. Затем я загрузил и сохранил, используя TEncoding.UTF8, и содержимое было идентичным, за исключением сохраненного файла со спецификацией впереди. Вы можете сделать то же самое, чтобы убедить себя, что я прав. Пока я читал твой последний комментарий, ты все еще звонишь StringReplace. Почему? - person David Heffernan; 13.01.2016
comment
Теперь, если у вас есть код, который генерирует файл с нуля, то я предполагаю, что есть проблема с этим кодом. Возможно, вы пишете такой код, как chr(175), который раньше был символом ANSI, а теперь является другим символом Unicode. Если у вас есть код для создания файла, то проблема, вероятно, будет найдена там. Мы не можем этого видеть. Теперь вы знаете, что файл, который вы создаете, должен иметь кодировку UTF-8. Вероятно, самый чистый путь вперед - это изменить код, чтобы использовать кодовые точки UTF-16, а затем TEncoding.UTF8 при записи. - person David Heffernan; 13.01.2016
comment
Другим маршрутом было бы создание вашего текста в кодировке UTF-8, как вы это делаете сейчас. Но вам придется прекратить использовать строки и списки строк, поскольку они кодируются UTF-16. Вы можете использовать кодированный тип UTF8 или, возможно, даже массив байтов. Много способов решить проблему, но это действительно на вас. Мы не можем посоветовать вам ваш код, который мы не видим. Вам определенно нужно пересмотреть Unicode, кодировки и то, как они обрабатываются в Delphi, потому что ваше понимание все еще несколько шаткое. Удачи. - person David Heffernan; 13.01.2016
comment
когда я вызываю loadfromfile(sfile,tencoding.utf8), я получаю следующее сообщение: В целевой многобайтовой кодовой странице не существует сопоставления для символа Юникода. Вот почему я использовал замену. - person P.A; 13.01.2016
comment
Я повторю то, что сказал выше. Я взял ваш первый файл в кодировке base64 и декодировал его в двоичные байты, которые я поместил на диск. Затем я загрузился с помощью LoadFromFile(..., TEncoding.UTF8). Это удалось и дало текст, начинающийся ±HEADER―ID°. Если вы сделаете то же самое, вы увидите то же самое. Что еще вы хотите от нас? - person David Heffernan; 13.01.2016
comment
@ Дэвид Хеффернан Я использовал этот кодировщик сайта base64encode.org, возможно, проблема в этом. Я попробую сделать это с более безопасным. Спасибо за помощь . - person P.A; 13.01.2016
comment
Проблема в том, что вы плохо разбираетесь в Unicode или в том, что делает ваша программа. Например, вы закодировали файл в base64 или вставили текст в окно? В любом случае, пока у вас не будет большего понимания, вы тратите свое время впустую. Хватит гадать. Прекратите использовать метод проб и ошибок. Потратьте некоторое время, чтобы учиться. - person David Heffernan; 13.01.2016
comment
@PA Я второй совет Дэвида. Программа состоит из этапов, которые преобразуют данные и передают их следующему. Вы должны проверять данные между этапами, чтобы найти именно тот этап, который делает их неправильными. Тогда вы сможете обнаружить ошибку или разделить et empera неисправный этап на подэтапы и снова найти неисправный фрагмент. То, что вы делаете сейчас, пробуя почти случайные догадки и дергая почти случайные ручки, может привести вас только к комбинаторному взрыву. Если он не сработал в первый час или два - шансы, что он случайно начнет работать в следующий час, бесконечно малы. Время анализировать. - person Arioch 'The; 14.01.2016