Відкрив JPG-зображення із блокнотом, вставив увесь «текст» у новий файл блокнота, змінив на .JPG і він більше не відкривається. Чому?


82

Це явище залишає мені питання.

Ось детальний експеримент, моя ОС Windows 7 x64 SP1:

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

Це повинно виглядати так, як не дивно виглядають послідовності текстів, і деякі з них (дуже рідкісні) насправді мають сенс, як на скріншоті нижче "Творець: dg-jpeg v1.0 ..."

Зразок тексту JPG

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

Коли я намагався відкрити, Windows сказав би: "Програма перегляду фотографій Windows не може відкрити це зображення, оскільки файл видається пошкодженим, пошкодженим або занадто великим" .

Я навіть спробував це протестувати іншим методом: відкривши JPG з блокнотом, я вирізав ОДИН відомий символ із місця, яке легко запам'ятовується (як перший символ 2-го рядка), а потім збережу файл. Переглядач, звичайно, відображатиме те саме повідомлення. Потім я знову відкрив його і вставив персонажа в точне місце (Блокнот пам'ятає його вихідний стан, наприклад, положення вікна, обгортання, розмір шрифтів ... тому у мене немає проблем з цим правом)

І ще та сама помилка. Ви можете спробувати це, щоб отримати ідею, пам’ятайте, що вибираєте маленьку картинку ще Блокнот буде діяти як старий іржавий чоловік.

Що могло бути причиною цього явища?


4
Спробуйте команду fc. відкрийте підказку cmd і зробіть. C:\blah>fc file1 file2 Можливо, щоб файли були однакового розміру, але різними. (хоча зазвичай деякі випадкові зміни, як правило, не залишають файл однакового розміру, але він легко може). Команда fc буде дуже корисною для розслідування того, що відбувається. Ви також можете використовувати команду xxd, це в cygwin, а також постачається з vim7. xxd -p file1 Це скидає шістнадцятковий файл. Ви можете порівняти шістнадцяткові два файли з цим і fc. Або навіть відкрийте шістнадцяткову в блокноті і переведіть між двома вікнами блокнота за допомогою вкладки Alt.
барлоп

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


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

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 у пробіли, але також додає байт на початок файлу, BOM .


22
0x00 - це строковий термінатор у C рядках. Вони, можливо, замінили їх, оскільки текстовий файл не повинен містити їх. Блокнот - це дуже стара програма.
Зондер

25
Я сумніваюся, що notepad.exe - це виконаний файл .NET.
knittl

10
@Bakuriu AC string, безумовно, може існувати у файлі; Я можу придумати численні формати файлів, які їх містять. І переважна більшість програм, які постачаються із програмами Windows, є рідними, а не .NET. Однак, блокнот не записує рядки з нульовим завершенням у файли.
Carey Gregory

4
@Bakuriu: Програми Windows, як правило, не записуються у .Net. Це C / C ++ і є основним в основі. Однією з програм .Net, розроблених microsoft, був живий письменник, який зараз припинено.
bhathiya-pera

5
@ SJuan76 Так? C ++ не визначає тип даних з назвою byte. Можливо, ви думаєте про якусь іншу мову. І розробники додатків можуть працювати з бінарними даними, проте вони вважають за потрібне, включаючи використання рядків C, якщо вони захочуть. Як я вже говорив, я можу придумати численні формати бінарних файлів, що містять рядки C.
Carey Gregory

37

Чому це не вдається:

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

Це трапляється тому, що API Windows в основному написаний мовою С, а рядки з нульовим завершенням - одна з загальних особливостей. Навіть коли сучасні Windows і Unicode вважаються такими ж нульовими закінченими рядками. Тому блокнот просто замініть їх пробілом, щоб ви могли переглянути повний файл.

Отже, коли ви зберігаєте файл, він пошкоджується.

wikipedia - нульові завершені рядки


Як зробити подальше дослідження:

Ви можете використовувати порівняльник на зразок поза порівнянням (комерційний, пробний), щоб побачити ефект заміни символів. див. також інші інструменти порівняння двійкових даних .

шістнадцяткове порівняння

Примітка : (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 як хакерські інструменти або віруси. Не довіряйте, що не завантажуйте його !!


Додаткова інформація про API API

кредити: Джейсон С

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


1
Дещо дивно, що ви показуєте аркуш властивостей для виконуваного файлу Notepad у комплекті з версією Windows XP, але, судячи з теми вікна, ви чітко запускаєте деяку версію Windows 8. Це пояснювало б, чому виконуваний файл був пов'язаний з версія 7.1 набору інструментів - ось що вони використовували для компіляції Windows XP та пов'язаних з ними утиліт. Версія Notepad для Windows 8, безсумнівно, буде складена з новою версією інструментів SDK.
Коді Грей

2
Це не лише текстове поле; WM_SETTEXTяк правило, не містить жодного параметра для визначення довжини рядка, а рядки завжди вважаються закінченими на нулі. Ви завжди можете створити спеціальне текстове поле зі спеціальним повідомленням, яке визначає довжину рядка, але Блокнот та більшість інших програм розумно цього не роблять.
Джейсон C

@BhathiyaPerera Тому що я задоволений рівнем роботи, яку я зробив, додавши інформацію в коментар. Запрошуємо покращити свою відповідь цією інформацією, якщо хочете.
Джейсон C

28

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

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

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


Піднесений текст (2/3) автоматично відкриває двійковий файл, показуючи його у шестигранному форматі. Наприклад, запуск файлу JPEG, просто натиснувши «відкрити»: puu.sh/aaAVx/bd08dab46e.png
tomsmeding

3
Насправді, частіше, ніж блокнот перетворюватиме LF у CRLF, він залишатиме LF таким, яким він є, і відображатиме текст так, ніби зовсім не було розриву рядків!
Моше Кац

6

Раніше ви могли це робити за допомогою програми "Назад" назад. Це була стандартна програма в Windows 3.1, але я не можу пригадати, чи включала в неї Windows 95. Функція Write дозволила б бінарне безпечне редагування будь-якого файлу, який він може відкрити (ймовірно, дуже обмежений розмір файлу). Блокнот, безумовно, не є бінарним (безпечний текст залишається тим самим, але фактичні байти нетекстових символів (наприклад, контрольні коди) можуть змінюватися), тому ваш приклад JPG не працює. Спробуйте отримати копію Write (і дуже старої Windows) і спробуйте експеримент ще раз!

Згідно «Windows Write» статті Вікіпедії Write була включена до Windows NT 3.5. Він був замінений Wordpad в Windows 95 і далі. write.exeвсе ще був у каталозі Windows, але був просто обгорткою для відкриття Wordpad.


5

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

Блокнот Microsoft не може відображати ці недрукувальні символи. Він може відображати такі заповнювачі, як пробіл для нульового символу. Таким чином, відкриття файлу в Блокноті не показує фактичний вміст, але вміст, декодований вибраним кодуванням (utf-8, utf-16 тощо) і відображається певним набором символів (unicode, ascii тощо), виключаючи не- символи для друку

Вибираючи весь відображений текст і копіюючи текст до буфера обміну, ви копіюєте лише друковані символи, включаючи заповнювачі. Таким чином, автоматично перетворюючи нульові символи в пробіли та повністю ігноруючи інші символи, які не можна друкувати.

Отже, ви просто втрачаєте вміст, роблячи це таким чином. Якщо ви замість цього використовуєте шестнадцятковий редактор, він повністю копіюватиме весь вміст.


Оновлення: відповідь Бхатія Перерас правильна: https://superuser.com/a/782885/322784 Недруковані символи не ігноруються під час копіювання тексту у буфер обміну.


Кожен файл є "в основному потоком байтів".
Джейсон C

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

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

@JasonC Насправді не можу з цим посперечатися. :) Touché!
sbecker

2

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

Але Блокнот за замовчуванням буде розглядати дані як текст ANSI, тому він буде робити різні речі, які змінять вихідні дані, як:

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

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

Що означає, що якщо ви відредагуєте та збережете дані у вигляді тексту, це змінить jpeg у кращому випадку та зробить його непридатним у гіршому.


"ANSI" технічно не є коректним , хоча це загальновідомо.
Джейсон C
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.