Otworzyłem obraz JPG w notatniku, wkleiłem cały „tekst” do nowego pliku notatnika, zmieniono na .JPG i już się nie otwiera. Dlaczego?

82

Zjawisko to pozostawia mi pytania.

Oto szczegółowy eksperyment, moim systemem operacyjnym jest Windows 7 x64 SP1:

  • Zmieniłem plik obrazu (JPG) na TXT, po prostu zmieniając jego rozszerzenie (lub można po prostu otworzyć plik JPG za pomocą notatnika, to samo)

Powinno to wyglądać tak, dziwnie wyglądające sekwencje tekstów, a niektóre z nich (bardzo rzadkie) są rzeczywiście znaczące, jak na zrzucie ekranu poniżej „creator: dg-jpeg v1.0 ...”

Przykładowy tekst JPG

  • Wyłączyłem zawijanie i zaznaczyłem cały tekst za pomocą Ctrl + A (aby upewnić się, że nic nie zostało pominięte)
  • Wkleiłem skopiowany tekst do innego pustego pliku TXT i zapisałem go jako JPG, porównałem nowy rozmiar pliku z oryginalnym JPG. Wszystkie z nich (oryginalny JPG, przekonwertowany plik TXT i nowo utworzony plik TXT) mają dokładnie taki sam rozmiar, w bajtach.

Gdy próbowałem otworzyć, system Windows powiedział: „Przeglądarka fotografii systemu Windows nie może otworzyć tego obrazu, ponieważ plik wydaje się być uszkodzony, uszkodzony lub jest za duży” .

Próbowałem nawet przetestować go przy użyciu innej metody: otworzyłem JPG za pomocą notatnika, wyciąłem JEDEN znany znak z miejsca łatwego do zapamiętania (jak pierwszy znak drugiej linii), a następnie zapisałem plik. Przeglądarka oczywiście wyświetli tę samą wiadomość. Następnie otworzyłem go ponownie i wkleiłem znak do DOKŁADNEJ lokalizacji (Notatnik pamięta jego stan wyjścia, taki jak położenie okien, zawijanie, rozmiar czcionek ... więc nie mam problemu z prawidłowym ustawieniem)

I wciąż ten sam błąd. Możesz spróbować tego, aby uzyskać pomysł, pamiętaj, aby wybrać małe zdjęcie, w przeciwnym razie Notatnik będzie działał jak stary zardzewiały człowiek.

Co mogło być przyczyną tego zjawiska?

Nguyễn Tuấn Danh
źródło
4
Wypróbuj polecenie fc. otwórz polecenie cmd i zrób- C:\blah>fc file1 file2 Możliwe, że pliki mają ten sam rozmiar, ale różny. (chociaż zwykle jakaś losowa zmiana zwykle nie pozostawia pliku o tym samym rozmiarze, ale łatwo może). Polecenie fc będzie bardzo przydatne w badaniu tego, co się dzieje. Możesz także użyć polecenia xxd, to jest w cygwin, a także pochodzi z vim7. xxd -p plik1 Zrzuci szesnastkę pliku. Możesz porównać hex tych dwóch plików z tym i fc. Lub nawet otwórz hex w notatniku i przesuwaj między dwoma oknami notatnika za pomocą klawisza Alt.
barlop
22
Próbujesz odczytać plik binarny za pomocą prostego edytora tekstu, takiego jak notatnik. Nie będzie w stanie poprawnie odczytać kodowania ANSI i dlatego go skonwertuje. Po zapisaniu plik nie będzie już binarny, a zatem analizator składni nie może odczytać danych w pliku. (Sprawdź różnicę między zapisywaniem plików opartym na XML a zapisywaniem plików binarnych to interesujący temat.) Jeśli spróbujesz tego samego eksperymentu z Notepad ++, odniesiesz sukces.
woutervs
3
Dla zainteresowanych: Możesz edytować obrazy w Vimie: Jednak sztuczka polega na tym, że Vim konwertuje plik w formacie XPM , który jest zwykłym ASCII.
Boldewyn
4
Krótko mówiąc, Notatnik modyfikuje plik przed wyświetleniem go.
Derek 朕 會 功夫

Odpowiedzi:

81

W zależności od kodowania użytego do otwarcia pliku może wystąpić inne zachowanie. Mój notatnik z systemem Windows 7 pozwala otwierać pliki w ANSI, UTF-8, Unicode lub Unicode big endian.

Testowałem ten problem z małym obrazem JPEG JPEG 2x2 utworzonym za pomocą gimp oraz otwierając i zapisując plik obrazu z kodowaniem ANSI. Otwierając zarówno oryginalny, jak i zapisany obraz za pomocą edytora szesnastkowego, widzę, że wszystkie 00 sekwencji (dwie cyfry szesnastkowe, znak kontrolny NUL ) zostały przekonwertowane na 20 (znak spacji).

Wymiana z powrotem w edytorze szesnastkowym wszystkie 20 na 00 przywraca format obrazu.

Trochę go przejrzałem i nie znalazłem żadnych referencji wyjaśniających, dlaczego tak się dzieje. Tylko odniesienie do postu, który go ostrzega (link do pamięci podręcznej Google, strona nie jest dostępna).

Jeśli zapiszesz / otworzysz plik jako UTF-8, wydaje się, że nadal konwertuje znaki NUL na spacje, ale zwiększa również rozmiar wynikowego pliku dzięki konwersji z znaków jednobajtowych na wielobajtowe sekwencje UTF-8.

Jeśli zapiszesz / otworzysz plik jako Unicode, wydaje się, że nadal konwertuje znaki NUL na spacje, ale dodaje również bajt na początku pliku, BOM .

mangper
źródło
22
0x00 jest zakończeniem łańcucha w łańcuchach C. Mogły je zastąpić, ponieważ plik tekstowy nie powinien ich zawierać. Notatnik to bardzo stary program.
Zonder
25
Wątpię, czy notepad.exe jest plikiem wykonywalnym .NET.
knittl
10
@Bakuriu Ciąg AC z pewnością może istnieć w pliku; Mogę wymyślić wiele formatów plików, które je zawierają. Zdecydowana większość aplikacji dostarczanych z aplikacjami Windows jest natywna, a nie .NET. To powiedziawszy, notatnik nie zapisuje ciągów zakończonych znakiem zerowym do plików.
Carey Gregory
4
@ Bakuriu: Programy Windows zwykle nie są napisane w .Net. Jest to C / C ++ i natywny w rdzeniu. Jedną z aplikacji .Net opracowanych przez Microsoft był program do nagrywania na żywo, który został obecnie wycofany.
bhathiya-perera
5
@ SJuan76 Huh? C ++ nie definiuje typu danych o nazwie byte. Być może myślisz o innym języku. Programiści aplikacji mogą radzić sobie z danymi binarnymi, które uznają za stosowne, w tym z wykorzystaniem ciągów C, jeśli tak wybiorą. Jak powiedziałem wcześniej, mogę myśleć o wielu formatach plików binarnych zawierających ciągi C.
Carey Gregory
37

Dlaczego zawodzi:

Notatnik tworzy (ASCII code 32)znak spacji dla znaków takich jak NUL, (ASCII code 0) ponieważ pole tekstowe interfejsu API systemu Windows zezwala tylko na char * ASCIIZ zakończone znakiem null (tablica znaków, wskaźnik). Odcina się przy pierwszym NUL.

Dzieje się tak, ponieważ Windows API jest napisany głównie w języku C , a ciągi zakończone znakiem zerowym są jedną z typowych funkcji. Nawet jeśli współczesne systemy Windows i Unicode są uważane za takie same, występują ciągi zerowane. Notatnik wystarczy więc zastąpić je spacją, aby można było wyświetlić cały plik.

Kiedy zapisujesz plik, jest on uszkodzony.

wikipedia-null zakończone ciągi


Jak przeprowadzić dalsze badania:

Możesz użyć komparatora, takiego jak „ porównaj” (komercyjny, testowy), aby zobaczyć efekt zamiany postaci. zobacz także inne narzędzia do porównywania binarnego .

porównanie szesnastkowe

Uwaga : (20) 16 = (32) 10


Powód, dla którego Notatnik działa powoli w przypadku dużych plików

Sprawdza każdą postać i zastępuje znaki specjalne spacjami. Inne oprogramowanie nie wykonuje konwersji w pamięci (przynajmniej nie prymitywnych jak notatnik). Po prostu renderują znaki specjalne inaczej. I używają zaawansowanych technik buforowania.


Wyszukiwanie w Notepad.exe (XP, 32-bitowy)

(Zakładam, że nadal jest napisany w C ++ lub przynajmniej używa porównywalnie podobnego linkera )

notatnik

Korzystam z narzędzia PEiD (które zatrzymało programowanie wraz z wprowadzeniem plików PE + / 64 ex)

PEiD można znaleźć w pakiecie w folderze bin Universal Extractor

Wyjąłem notatnik. Plik ex_ z systemu Windows XP jest oczywiście oczywiście. Wypróbuj to. Jest to wyciąg z pliku cab używający 7z.

Ostrzeżenie ! Twój skaner antywirusowy może wykryć Universal Extractor / PEiD jako narzędzia hakerskie lub wirusy. Nie ufaj, nie pobieraj go !!


Więcej informacji o Windows API

kredyty: Jason C.

To nie tylko pole tekstowe; WM_SETTEXT na ogół nie podaje parametru do określania długości łańcucha, i zawsze przyjmuje się, że łańcuchy kończą się zerem. Zawsze możesz utworzyć niestandardowe pole tekstowe z niestandardowym komunikatem, który określa długość łańcucha, ale Notatnik i większość innych programów nie. Również funkcja SetWindowText nie podaje również parametru długości.

bhathiya-perera
źródło
1
To trochę dziwne, że wyświetlasz arkusz właściwości dla pliku wykonywalnego Notatnika w pakiecie z wersją systemu Windows XP, ale sądząc po motywie okna, wyraźnie używasz wersji Windows 8. To by wyjaśniało, dlaczego plik wykonywalny był powiązany z wersja 7.1 zestawu narzędzi - tego właśnie używali do kompilacji systemu Windows XP i powiązanych narzędzi. Wersja Notatnika na Windows 8 zostanie bez wątpienia skompilowana z nowszą wersją narzędzi SDK.
Cody Gray
2
To nie tylko pole tekstowe; WM_SETTEXTogólnie nie podaje parametru do określania długości łańcucha, a ciągi zawsze przyjmuje się za zakończone o wartości null. Zawsze możesz utworzyć niestandardowe pole tekstowe z niestandardowym komunikatem, który określa długość łańcucha, ale Notatnik i większość innych programów nie.
Jason C
@BhathiyaPerera Ponieważ jestem zadowolony z poziomu pracy, którą wykonałem, dodając informacje w komentarzu. Jeśli chcesz, możesz poprawić swoją odpowiedź za pomocą tych informacji.
Jason C
28

Notatnik nie zachowuje wszystkich znaków specjalnych / rozszerzonych dokładnie tak, jak są. Nie mam od razu odniesienia do tego zachowania, ale stwierdziłem, że tak jest na przykład w przypadku LF typu końca wiersza w stylu UNIX, który Notatnik zamieni na CRLF i null (0x00), który zignoruje. W pliku binarnym, takim jak JPG, mogą występować losowe znaki, których Notatnik nie zachowuje. Wypróbuj eksperyment z edytorem obsługującym HEX i powinien on wtedy działać. Zaktualizuję swoją odpowiedź, jeśli znajdę dobre referencje i po przetestowaniu edytora HEX.

Aktualizacja: Wypróbowałem kilka dobrze znanych edytorów programistów, ale tylko jeden z nich działał od razu, HxD autorstwa Maëla Hörza . Nigdy wcześniej nie korzystałem z HxD, ale znalazłem go dzięki odpowiedzi na ten artykuł na temat stosu, Wtyczka przeglądarki / edytora hex dla Notepad ++ .

Innymi edytorami, które nie działały po kilku minutach wysiłku, były Notepad ++, Notepad2 i UltraEdit (wersja 17.3, starsza wersja). Kilka z nich miało problemy z kopiowaniem / wklejaniem pierwszych kilku bajtów, magiczną liczbą podpisu pliku JPEG FF D8 FF. Może pracowaliby z trochę więcej zabawy, niż mam obecnie czas.

JohnC
źródło
Sublime Text (2/3) automatycznie otwiera plik binarny, pokazując go w formacie szesnastkowym. Na przykład początek pliku JPEG po prostu klikając „otwórz”: puu.sh/aaAVx/bd08dab46e.png
tomsmeding
3
W rzeczywistości częściej niż notatnik konwertuje LF na CRLF, pozostawia LF takim, jakim jest i wyświetla tekst, jakby w ogóle nie było podziału linii!
Moshe Katz
6

Kiedyś byłeś w stanie to zrobić za pomocą opcji Napisz w ciągu dnia. Był to standardowy program w systemie Windows 3.1, ale nie pamiętam, czy system Windows 95 go zawierał. Zapis umożliwiłby bezpieczną edycję binarną każdego pliku, który mógłby otworzyć (prawdopodobnie bardzo ograniczony rozmiar pliku). Notatnik na pewno nie jest binarnie bezpieczny (tekst pozostaje taki sam, ale rzeczywiste bajty znaków nietekstowych [np. Kody sterujące] mogą się zmienić), dlatego twój przykład JPG nie działa. Spróbuj uzyskać kopię zapisu (i bardzo starego systemu Windows) i spróbuj ponownie eksperymentu!

Zgodnie z artykułem Wikipedii „Windows Write”, pisanie zostało dołączone do Windows NT 3.5. Został zastąpiony przez Wordpad w Windows 95 i nowszych. write.exewciąż był obecny w katalogu Windows, ale był po prostu opakowaniem do otwierania Wordpada.

CJ Dennis
źródło
5

Myślę, że to nie tyle problem kodowania, ile zestawu znaków. Format JPG jest w zasadzie strumieniem bajtów. Umożliwiając w ten sposób znaki niedrukowalne, takie jak NUL, ETX, STX, SOH, DLE itp.

Microsoft Notepad nie może wyświetlać tych niedrukowalnych znaków. Może wyświetlać symbole zastępcze, takie jak miejsce na znak zerowy. Otwieranie pliku za pomocą Notatnika nie pokazuje rzeczywistej treści, ale treść dekodowaną przez wybrane kodowanie (utf-8, utf-16 itp.) I wyświetlaną przez określony zestaw znaków (Unicode, Ascii itp.) Z wyłączeniem innych niż znaki do druku.

Wybierając cały wyświetlany tekst i kopiując tekst do schowka, kopiujesz tylko znaki do wydruku, w tym symbole zastępcze. W ten sposób automatycznie konwertuje znaki zerowe na spacje i całkowicie ignoruje inne znaki niedrukowalne.

Zasadniczo po prostu tracisz zawartość, robiąc to w ten sposób. Jeśli zamiast tego użyjesz edytora szesnastkowego, cała zawartość zostanie skopiowana w całości.


Aktualizacja: odpowiedź Bhathiya Pereras jest prawidłowa: https://superuser.com/a/782885/322784 Znaki niedrukowalne nie są ignorowane podczas kopiowania tekstu do schowka.

Sbecker
źródło
Każdy plik jest „w zasadzie strumieniem bajtów”.
Jason C
1
@JasonC Nie zgadzam się. Chociaż każdy plik można odczytać jako strumień bajtów. Pliki strukturalne, takie jak pliki XML, nie są czytelne jako strumień danych. Treść nie byłaby ważna do momentu odczytania końca pliku. Przecięcie na pół jpg jest nadal aktualne i można je wyświetlić. Brakuje tylko połowy zdjęcia.
sbecker
Nie ma naprawdę miejsca na spory w tej sprawie. :) XML to strumień bajtów jak wszystko inne, a XML (wraz z kodowaniem znaków) określa format tych bajtów. Z pewnością jest czytelny jako strumień danych. Otwórz na przykład w edytorze szesnastkowym. Ten strumień danych jest po prostu analizowalny jako XML.
Jason C
@JasonC Tak naprawdę nie mogę się z tym kłócić. :) Touché!
sbecker
2

Plik JPEG zawiera dane nietekstowe z wyjątkiem niektórych pól, w zasadzie zostaną znalezione wszystkie wartości bajtów od 0 do 255, szczególnie w obszarze reprezentującym zakodowany skompresowany obraz, który zawiera prawie pseudolosowe dane.

Ale Notatnik domyślnie będzie traktował dane jako tekst ANSI, więc zrobi różne rzeczy, które zmienią oryginalne dane, jak:

  • zamień bajty odwzorowując znaki specjalne / niezdefiniowane / zabronione, ponieważ nie ma to sensu dla poprawnego tekstu ANSI

  • ponownie koduje znaki puste, koniec linii i koniec sekwencji plików zgodnie z konwencjami Windows / DOS

Co oznacza, że ​​jeśli edytujesz i zapisujesz dane jako tekst, w najlepszym przypadku zmieni on JPEG, aw najgorszym stanie się bezużyteczny.

Kości 9
źródło
„ANSI” nie jest technicznie poprawne , chociaż jest powszechnie rozumiane.
Jason C