Открыл изображение JPG с помощью блокнота, вставил весь «текст» в новый файл блокнота, изменил на .JPG и больше не открывал. Почему?


82

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

Вот подробный эксперимент, моя ОС - 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-й строки), а затем сохранил файл. Зритель, конечно, будет отображать то же сообщение. Затем я снова открыл его и вставил символ в ТОЧНОЕ расположение (Блокнот запоминает его состояние выхода, например, положение окон, обтекание, размер шрифтов ... поэтому у меня нет проблем с получением правильной информации)

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

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


4
Попробуйте команду fc. откройте командную строку и C:\blah>fc file1 file2 выполните команду. Возможно, файлы имеют одинаковый размер, но разные. (хотя обычно некоторые случайные изменения не дают файлу одинакового размера, но это легко может произойти). Команда fc будет очень полезна для изучения происходящего. Вы также можете использовать команду xxd, это в cygwin, а также поставляется с vim7. xxd -p file1 Это выгрузит шестнадцатеричный файл. Вы можете сравнить гекс двух файлов с этим и fc. Или даже откройте шестнадцатеричное в блокноте и пролистайте между двумя окнами блокнота с помощью alt-tab.
Барлоп

22
Вы пытаетесь прочитать двоичный файл с помощью простого текстового редактора, такого как блокнот. Он не сможет правильно прочитать кодировку ANSI и, следовательно, преобразует ее. Когда вы сохраните его, файл больше не будет двоичным, и, следовательно, парсер не сможет прочитать данные внутри файла. (Найти разницу между сохранением файлов на основе XML и сохранением двоичных файлов - это интересная тема.) Если вы попробуете тот же эксперимент с Notepad ++, вы добьетесь успеха в том, что пытались.
woutervs


3
Для интересующихся: Вы можете редактировать изображения в Vim: Однако хитрость в том, что Vim преобразует файл в формат XPM , который является простым ASCII.
Болдевин

4
Короче говоря, Блокнот изменяет ваш файл перед его отображением.
Дерек 朕 會 功夫

Ответы:


81

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

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

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

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

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

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


22
0x00 - это терминатор строки в C-строках. Они могли заменить их, так как текстовый файл не должен содержать их. Блокнот очень старая программа.
Зондер

25
Я сомневаюсь, что notepad.exe - это исполняемый файл .NET.
knittl

10
@Bakuriu AC строка, безусловно, может существовать в файле; Я могу думать о многочисленных форматах файлов, которые их содержат. И подавляющее большинство приложений, которые поставляются с приложениями Windows, являются нативными, а не .NET. Тем не менее, блокнот не записывает строки с нулевым символом в конце.
Кэри Грегори

4
@Bakuriu: Программы для Windows обычно не пишутся в .Net. Это C / C ++ и родной в основе. Одним из приложений .Net, разработанным Microsoft, был live writer, который сейчас закрыт.
бхатия-перера

5
@ SJuan76 А? C ++ не определяет тип данных с именем byte. Возможно, вы думаете о каком-то другом языке. И разработчики приложений могут иметь дело с двоичными данными, как они считают нужным, включая использование строк C, если они того пожелают. Как я уже говорил, я могу думать о многочисленных форматах двоичных файлов, которые содержат строки C.
Кэри Грегори

37

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

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

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

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

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


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

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

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

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


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

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


Глядя в Notepad.exe (32-разрядная версия XP)

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

блокнот

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

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

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

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


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

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

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


1
Немного странно, что вы показываете лист свойств для исполняемого файла Notepad в комплекте с версией Windows XP, но, судя по теме окна, вы явно работаете с некоторой версией Windows 8. Это объясняет, почему исполняемый файл был связан с версия 7.1 набора инструментов - это то, что они использовали для компиляции Windows XP и связанных утилит. Версия Notepad для Windows 8, несомненно, будет скомпилирована с более новой версией инструментов SDK.
Коди Грей

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

@BhathiyaPerera Потому что я доволен уровнем работы, которую я проделал, добавив информацию в комментарии. Вы можете улучшить свой ответ с этой информацией, если хотите.
Джейсон С

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. Может быть, они будут работать немного сложнее, чем у меня сейчас есть время.


Sublime Text (2/3) автоматически открывает двоичный файл, показывая его в шестнадцатеричном формате. Например, для запуска файла JPEG достаточно нажать кнопку «Открыть»: puu.sh/aaAVx/bd08dab46e.png
tomsmeding

3
На самом деле, чаще, чем блокнот конвертирует LF в CRLF, он оставляет LF таким, какой он есть, и отображает текст, как будто вообще не было разрыва строки!
Моше Кац

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 Непечатные символы не игнорируются при копировании текста в буфер обмена.


Каждый файл "в основном поток байтов".
Джейсон С

1
@JasonC Я бы не согласился. Хотя каждый файл может быть прочитан как поток байтов. Структурированные файлы, такие как XML-файлы, не читаются как поток данных. Содержимое не будет действительным, пока не будет прочитан конец файла. Сокращение пополам jpg все еще действует и может быть отображено. Просто отсутствует половина картинки.
sbecker

В этом нет места для разногласий. :) XML - это поток байтов, как и все остальное, и XML (наряду с кодировкой символов) определяет формат для этих байтов. Он, безусловно, читается как поток данных. Откройте его в шестнадцатеричном редакторе, например. Этот поток данных может быть проанализирован как XML.
Джейсон C

@JasonC Спорить с этим не могу. :) Touché!
sbecker

2

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

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

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

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

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


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.