81

Это явление оставляло мне вопросы.

Вот подробный эксперимент, моя ОС - Windows 7 x64 SP1:

  • Я изменил файл изображения (JPG) на TXT, просто изменив его расширение (или можно было просто открыть JPG с помощью блокнота, тоже самое)

Это должно выглядеть так, странно выглядящие последовательности текстов, а некоторые из них (очень редкие) на самом деле имеют смысл, как на скриншоте ниже «creator: dg-jpeg v1.0 ...»

Образец текста в формате JPG

  • Я отключил перенос и выделил весь текст, используя Ctrl+A (чтобы убедиться, что ничего не пропущено)
  • Я вставил скопированный текст в другой пустой текстовый файл и сохранил его как JPG, сравнил новый размер файла с исходным JPG. Все они (оригинального JPG, преобразованного TXT файл и вновь созданный файл TXT) имеют точно такой же размер, в байтах.

Когда я пытался открыть, Windows говорила: «Windows Photo Viewer не может открыть это изображение, потому что файл кажется поврежденным, поврежденным или слишком большим».

Я даже пытался протестировать его, используя другой метод: открыл JPG с помощью блокнота, я вырезал ОДИН известный символ из легко запоминающегося места (например, первый символ 2-й строки), а затем сохранил файл. Зритель, конечно, будет отображать то же сообщение. Затем я снова открыл его и вставил символ в ТОЧНОЕ расположение (Блокнот запоминает его состояние выхода, например, положение окон, обтекание, размер шрифтов ... поэтому у меня нет проблем с получением правильной информации)

И все та же ошибка. Вы можете попробовать это, чтобы получить идею, не забудьте выбрать маленькую картинку, иначе Блокнот будет вести себя как старый ржавый человек.

Что могло быть причиной этого явления?

6 ответов6

80

В зависимости от кодировки, используемой для открытия файла, вы можете увидеть другое поведение. Мой блокнот Windows 7 позволяет открывать файлы в формате ANSI, UTF-8, Unicode или Unicode с прямым порядком байтов.

Я проверил эту проблему с помощью небольшого JPEG-изображения размером 2x2, созданного с помощью GIMP и открывающего и сохраняющего файл изображения с кодировкой ANSI. Открывая исходное и сохраненное изображение с помощью шестнадцатеричного редактора, я вижу, что все последовательности 00 (две шестнадцатеричные цифры, управляющий символ NUL) были преобразованы в 20 (пробел).

Замена обратно в шестнадцатеричном редакторе всех 20 на 00 восстанавливает формат изображения.

Я немного погуглил и не нашел ссылок, объясняющих, почему это происходит. Только ссылка на пост, который предупреждает об этом (ссылка на кеш Google, страница недоступна).

Если вы сохраняете / открываете файл как UTF-8, кажется, что он по-прежнему преобразует символы NUL в пробелы, но также увеличивает размер получаемого файла из-за преобразования однобайтовых символов в многобайтовые последовательности UTF-8.

Если вы сохраняете / открываете файл как Unicode, кажется, что он по-прежнему преобразует символы NUL в пробелы, но также добавляет байт в начало файла, спецификацию.

36

Почему это не удается:

Блокнот создает пробелы (ASCII code 32) для символов, таких как NUL (ASCII code 0) потому что в текстовом поле Windows API допускается только завершенный нулем char * ASCIIZ (массив символов, указатель). Он отключается при первом NUL.

Это происходит потому, что Windows API в основном написан на языке C, а строки с нулевым символом в конце являются одной из общих функций. Даже когда считается, что современные Windows и Unicode имеют одинаковые строки с нулевым символом в конце. Поэтому блокнот просто замените их пробелом, чтобы вы могли просмотреть весь файл.

Поэтому, когда вы сохраняете файл, он поврежден.

Википедия - завершенные строки


Как сделать дальнейшие исследования:

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

шестнадцатеричное сравнение

Примечание : (20)16 = (32)10


Причина для блокнота действует медленно на больших файлах

Он проверяет каждый символ и заменяет специальные символы пробелами. Другое программное обеспечение не выполняет преобразования в памяти (по крайней мере, не примитивно, как блокнот). Они просто по-разному отображают специальные символы. И они используют передовые методы буферизации.

Глядя в Notepad.exe (XP 32 бит)

(Я предполагаю, что он все еще написан на C++ или, по крайней мере, использует сравнительно похожий компоновщик )

блокнот

Я использую инструмент PEiD (который остановил разработку с введением PE+/64 exes)

PEiD можно найти в папке bin в Universal Extractor

Я извлек блокнот. ex_ файл из Windows XP iso очевидно. Попробуйте это. Это распаковка с использованием 7z.

Предупреждение! Ваш антивирусный сканер может обнаружить Universal Extractor/PEiD как хакерские инструменты или вирусы. Не верь, не скачивай !!


Дополнительная информация о Windows API

Авторы:Джейсон С

Это не просто текстовое поле; WM_SETTEXT в общем случае не предоставляет параметров для указания длины строки, и предполагается, что строки всегда заканчиваются нулем. Вы всегда можете создать собственное текстовое поле с пользовательским сообщением, в котором указана длина строки, но Блокнот и большинство других программ этого не делают. Также функция SetWindowText также не предоставляет параметр длины.

28

Блокнот не сохраняет все специальные / расширенные символы в точности так, как они есть. У меня нет ссылки на это поведение под рукой, но я обнаружил, что это имеет место, например, в конце строки LF в стиле UNIX, который Notepad преобразует в CRLF, и ноль (0x00), который он игнорирует. В двоичном файле, таком как JPG, возможны случайные вхождения символов, которые Блокнот не сохраняет. Попробуйте поэкспериментировать с редактором, поддерживающим HEX, и тогда он должен работать. Я обновлю свой ответ, если найду хорошую ссылку, и когда я протестирую HEX-редактор.

Обновление: я попробовал несколько известных редакторов-программистов, но только один из них работал сразу, HxD от Maël Hörz. Я никогда раньше не использовал HxD, но нашел его благодаря ответу на эту статью о стеках - плагине hex hex viewer / editor для Notepad++.

Другими редакторами, которые не работали через несколько минут, были Notepad++, Notepad2 и UltraEdit (v17.3, более старая версия). У некоторых из них были проблемы с копированием / вставкой первых нескольких байтов, магического числа подписи файла JPEG FF D8 FF. Может быть, они будут работать немного сложнее, чем у меня сейчас есть время.

6

Раньше вы могли делать это с помощью функции «Написать обратно». Это была стандартная программа в Windows 3.1, но я не могу вспомнить, включена ли она в Windows 95. Запись позволит в двоичном режиме безопасно редактировать любой файл, который может открыть (возможно, очень ограниченный размер файла). Блокнот определенно не является бинарно-безопасным (текст остается тем же, но фактические байты нетекстовых символов (например, управляющих кодов) могут измениться), поэтому ваш пример JPG не работает. Попробуйте получить копию Write (и очень старой Windows) и попробуйте еще раз!

Согласно статье Википедии "Windows Write", запись была включена до Windows NT 3.5. Он был заменен Wordpad в Windows 95 и далее. write.exe все еще присутствовал в каталоге Windows, но был просто оболочкой для открытия Wordpad.

5

Я думаю, что это не столько проблема кодирования, сколько набор символов. Формат JPG - это в основном поток байтов. Таким образом, допускаются непечатные символы, такие как NUL, ETX, STX, SOH, DLE и т.д.

Microsoft Notepad не может отображать эти непечатаемые символы. Он может отображать заполнители некоторого вида, такие как пробел для нулевого символа. Таким образом, при открытии файла с помощью Блокнота отображается не фактическое содержимое, а содержимое, декодированное выбранной кодировкой (utf-8, utf-16 и т.д.) И отображаемое определенным набором символов (Unicode, ASCII и т.д.), Исключая не печатные символы.

При выделении всего отображаемого текста и копировании текста в буфер обмена вы копируете только печатные символы, включая заполнители. Таким образом, автоматическое преобразование нулевых символов в пробелы и полное игнорирование других непечатных символов.

Так что в основном вы просто теряете контент, делая это таким образом. Если вместо этого вы используете hex-редактор, он полностью скопирует весь контент.


Обновление: Bhathiya Pereras ответ правильный: https://superuser.com/a/782885/322784 Непечатные символы не игнорируются при копировании текста в буфер обмена.

2

Файл JPEG содержит нетекстовые данные, за исключением некоторых полей, в основном будут найдены любые байтовые значения от 0 до 255, особенно в области, представляющей закодированное сжатое изображение, которое содержит почти псевдослучайные данные.

Но Блокнот по умолчанию будет обрабатывать данные как текст ANSI, поэтому он будет выполнять различные действия, которые будут изменять исходные данные, как:

  • заменять байты, отображая специальные / неопределенные / запрещенные символы, так как они не имеют смысла для допустимого текста ANSI

  • перекодировать нулевые символы, конец строки и конец последовательности файлов в соглашения Windows / DOS

Это означает, что если вы отредактируете и сохраните данные в виде текста, это изменит jpeg в лучшем случае и сделает его непригодным для использования в худшем случае.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .