เปิดรูปภาพ JPG ด้วย notepad แล้ววาง "text" ทั้งหมดลงในไฟล์ notepad ใหม่เปลี่ยนเป็น. JPG และจะไม่เปิดอีกต่อไป ทำไม?


82

ปรากฏการณ์นี้ทำให้ฉันต้องถามคำถาม

นี่คือการทดลองโดยละเอียดระบบปฏิบัติการของฉันคือ Windows 7 x64 SP1:

  • ฉันเปลี่ยนไฟล์รูปภาพ (JPG) เป็น TXT โดยเพียงแค่เปลี่ยนนามสกุล (หรือเพียงแค่เลือกเปิด JPG ด้วย notepad ก็ได้)

มันควรมีหน้าตาแบบนี้แปลก ๆ ที่เรียงลำดับข้อความและบางส่วน (หายากมาก) มีความหมายเช่นในภาพด้านล่าง "creator: dg-jpeg v1.0 ... "

ตัวอย่างข้อความ JPG

  • ฉันปิดการตัดคำและเลือกข้อความทั้งหมดโดยใช้ Ctrl + A (เพื่อให้แน่ใจว่าไม่มีอะไรพลาด)
  • ฉันวางข้อความที่คัดลอกไปยังไฟล์ TXT ว่างเปล่าอีกไฟล์และบันทึกเป็น JPG ฉันเปรียบเทียบขนาดไฟล์ใหม่กับ JPG ดั้งเดิม ทั้งหมดของพวกเขา (คนเดิม JPG ไฟล์ TXT แปลงและไฟล์ TXT ที่สร้างขึ้นใหม่) เป็นของที่แน่นอนขนาดเดียวกันเพื่อไบต์

เมื่อฉันพยายามที่จะเปิด, Windows จะบอกว่า"Windows Photo Viewer ไม่สามารถเปิดภาพนี้เพราะไฟล์ที่ดูเหมือนจะได้รับความเสียหายเสียหายหรือมีขนาดใหญ่เกินไป"

ฉันพยายามทดสอบด้วยวิธีอื่น: เปิด JPG ด้วย notepad ฉันตัดหนึ่งอักขระที่รู้จักจากตำแหน่งที่จดจำได้ง่าย (เช่นตัวอักษรตัวแรกของบรรทัดที่ 2) จากนั้นบันทึกไฟล์ แน่นอนว่าผู้ดูจะแสดงข้อความเดียวกัน จากนั้นฉันก็เปิดมันอีกครั้งและวางตัวอักษรไปยังตำแหน่งที่แน่นอน (Notepad จะจดจำสถานะทางออกของมันเช่นตำแหน่งของหน้าต่างการห่อขนาดตัวอักษร ... ดังนั้นฉันจึงไม่มีปัญหาในการทำให้ถูกต้อง)

และยังคงมีข้อผิดพลาดเดียวกัน คุณสามารถลองสิ่งนี้เพื่อให้ได้ความคิดอย่าลืมเลือกรูปภาพขนาดเล็กมิฉะนั้น Notepad จะทำตัวเหมือนชายชราสนิม

อะไรเป็นสาเหตุของปรากฏการณ์นี้


4
ลองคำสั่ง fc เปิดพรอมต์คำสั่งและทำ - C:\blah>fc file1 file2 เป็นไปได้ที่ไฟล์จะมีขนาดเท่ากัน แต่ต่างกัน (แม้ว่าโดยทั่วไปแล้วการเปลี่ยนแปลงแบบสุ่มจะไม่ทำให้ไฟล์มีขนาดเท่ากัน แต่ทำได้อย่างง่ายดาย) คำสั่ง fc จะมีประโยชน์มากสำหรับคุณในการตรวจสอบสิ่งที่เกิดขึ้น คุณยังสามารถใช้คำสั่ง xxd นี่คือใน cygwin และยังมาพร้อมกับ vim7 xxd -p file1 ที่จะถ่ายโอนฐานสิบหกของไฟล์ คุณสามารถเปรียบเทียบ hex ของไฟล์ทั้งสองกับมันและ fc หรือแม้กระทั่งเปิด hex ในแผ่นจดบันทึกแล้วสะบัดระหว่างหน้าต่างแผ่นจดบันทึกทั้งสองด้วย alt-tab
barlop

22
คุณกำลังพยายามอ่านไฟล์ไบนารีด้วยโปรแกรมแก้ไขข้อความอย่างง่ายเช่นแผ่นจดบันทึก มันจะไม่สามารถอ่านการเข้ารหัส ANSI ได้อย่างถูกต้องและมันจะแปลงมัน เมื่อคุณบันทึกไฟล์จากนั้นไฟล์จะไม่เป็นแบบไบนารีอีกต่อไปดังนั้น parser จึงไม่สามารถอ่านข้อมูลภายในไฟล์ได้ (ค้นหาความแตกต่างระหว่างการบันทึกไฟล์ที่อิงกับ XML และการบันทึกไฟล์ไบนารีเป็นหัวข้อที่น่าสนใจ) หากคุณลองใช้การทดลองเดียวกันกับ Notepad ++ คุณจะประสบความสำเร็จในสิ่งที่คุณพยายาม
woutervs


3
สำหรับผู้ที่สนใจ: คุณสามารถแก้ไขภาพใน Vim: อย่างไรก็ตามเคล็ดลับคือ Vim ที่แปลงไฟล์ในรูปแบบXPMซึ่งเป็น ASCII ธรรมดา
Boldewyn

4
เรื่องราวสั้น ๆ สั้น ๆ Notepad จะแก้ไขไฟล์ของคุณก่อนที่จะแสดงให้คุณเห็น
Derek 朕會功夫

คำตอบ:


81

ขึ้นอยู่กับการเข้ารหัสที่ใช้ในการเปิดไฟล์คุณอาจเห็นพฤติกรรมที่แตกต่างกัน Notepad Windows 7 ของฉันอนุญาตให้เปิดไฟล์ใน ANSI, UTF-8, Unicode หรือ Unicode big endian

ฉันได้ทดสอบปัญหานี้ด้วยภาพ jpeg ขนาด 2x2 พิกเซลขนาดเล็กที่สร้างขึ้นด้วย gimp และการเปิดและบันทึกไฟล์ภาพด้วยการเข้ารหัส ANSI การเปิดทั้งภาพต้นฉบับและภาพที่บันทึกด้วยโปรแกรมแก้ไข hex ฉันเห็นว่าลำดับ 00 ทั้งหมด (เลขฐานสิบหกสองตัวอักขระควบคุม NUL ) ถูกแปลงเป็น 20 (อักขระเว้นวรรค)

การแทนที่กลับในเครื่องมือแก้ไขฐานสิบหกทั้ง 20 ด้วย 00 จะคืนค่ารูปแบบภาพ

ฉันทำไปนิดหน่อยแล้วก็ไม่พบข้อมูลอ้างอิงใด ๆ ที่อธิบายว่าทำไมมันถึงเป็นเช่นนั้น เฉพาะการอ้างอิงถึงโพสต์ที่เตือนเกี่ยวกับมัน (ลิงค์แคชของ Google หน้าไม่สามารถใช้ได้)

หากคุณบันทึก / เปิดไฟล์เป็น UTF-8 ดูเหมือนว่ามันจะยังคงแปลงอักขระ NUL เป็นช่องว่าง แต่ก็ยังเพิ่มขนาดไฟล์ผลลัพธ์เนื่องจากการแปลงจากอักขระไบต์เดียวเป็น UTF-8 หลายลำดับไบต์

ถ้าคุณบันทึก / เปิดแฟ้มเป็น Unicode ดูเหมือนว่ามันยังแปลงอักขระ NUL ไปที่ช่องว่าง แต่ยังเพิ่มไบต์ที่จุดเริ่มต้นของไฟล์ที่BOM


22
0x00 เป็นตัวยุติสตริงในสตริง C พวกเขาอาจแทนที่พวกเขาเนื่องจากไฟล์ข้อความไม่ควรมีพวกเขา Notepad เป็นโปรแกรมที่เก่ามาก
Zonder

25
ฉันสงสัยว่า notepad.exe เป็น. NET ที่ปฏิบัติการได้
knittl

10
@Bakuriu สตริง AC แน่นอนที่สุดสามารถอยู่ในไฟล์; ฉันสามารถนึกถึงรูปแบบไฟล์มากมายที่มีอยู่ และแอพพลิเคชั่นส่วนใหญ่ที่มาพร้อมกับแอพ Windows นั้นไม่ใช่ของเนทีฟ ที่กล่าวว่า notepad ไม่เขียนสตริงที่สิ้นสุดด้วย null ลงในไฟล์
Carey Gregory

4
@Bakuriu: โปรแกรม Windows มักจะไม่ได้เขียนด้วย. Net มันคือ C / C ++ และเนทีฟเป็นหลัก หนึ่งในแอปพลิเคชั่น. Net ที่พัฒนาโดยไมโครซอฟท์คือ live writer ซึ่งถูกยกเลิกแล้ว
bhathiya-perera

5
@ SJuan76 หืม? C ++ byteไม่ได้กำหนดชนิดของข้อมูลที่มีชื่อว่า บางทีคุณอาจกำลังคิดถึงภาษาอื่น และนักพัฒนาแอปพลิเคชันสามารถจัดการกับข้อมูลไบนารีอย่างไรก็ตามพวกเขาเห็นว่าเหมาะสมรวมถึงการใช้สตริง C หากพวกเขาเลือก อย่างที่ฉันพูดไปก่อนหน้านี้ฉันนึกถึงรูปแบบไฟล์ไบนารีจำนวนมากที่มีสตริง C
Carey Gregory

37

ทำไมมันล้มเหลว:

Notepad สร้าง(ASCII code 32)อักขระช่องว่างสำหรับอักขระเช่นNUL (ASCII code 0)เนื่องจากกล่องข้อความของ Windows API อนุญาตเฉพาะchar * ASCIIZ ที่สิ้นสุดด้วย null (อาเรย์อักขระตัวชี้) มันถูกตัดออกที่ NUL แรก

ที่เกิดขึ้นเนื่องจากWindows APIส่วนใหญ่เขียนด้วยภาษาCและสตริงที่สิ้นสุดด้วยค่า nullเป็นหนึ่งในคุณสมบัติทั่วไป แม้ว่า Windows และ Unicode สมัยใหม่จะถือเป็นสตริงที่สิ้นสุดด้วยค่า null ที่เหมือนกัน ดังนั้นแผ่นจดบันทึกจะแทนที่ด้วยพื้นที่ว่างเพื่อให้คุณสามารถดูไฟล์ทั้งหมด

ดังนั้นเมื่อคุณบันทึกไฟล์มันจะเสียหาย

สตริงที่สิ้นสุดด้วย wikipedia-null


วิธีทำการวิจัยเพิ่มเติม:

คุณสามารถใช้ตัวเปรียบเทียบเช่นการเปรียบเทียบ (เชิงพาณิชย์การทดลอง)เพื่อดูเอฟเฟกต์การแทนที่อักขระ ยังเห็นไบนารีอื่น ๆ เปรียบเทียบเครื่องมือ

การเปรียบเทียบฐานสิบหก

หมายเหตุ : (20) 16 = (32) 10


เหตุผลที่ notepad ทำงานช้าลงในไฟล์ขนาดใหญ่

มันจะตรวจสอบตัวละครแต่ละตัวและแทนที่ตัวอักษรพิเศษด้วยช่องว่าง ซอฟต์แวร์อื่นไม่ทำการแปลงในหน่วยความจำ (อย่างน้อยไม่เป็นดั้งเดิม) เป็นแผ่นจดบันทึก พวกเขาแสดงอักขระพิเศษต่างกัน และพวกเขาใช้เทคนิคการบัฟเฟอร์ขั้นสูง


ค้นหา Notepad.exe (XP 32 บิต)

(ฉันสมมติว่ามันยังคงเขียนใน C ++ หรืออย่างน้อยใช้linker ที่คล้ายกันเปรียบเทียบ)

Notepad

ฉันใช้เครื่องมือPEiD (ซึ่งหยุดการพัฒนาด้วยการเปิดตัว PE + / 64 exes)

สามารถพบ PEiD ที่รวมอยู่ในโฟลเดอร์ bin ของUniversal Extractor

ฉันดึงแผ่นจดบันทึก ไฟล์ ex_ จาก Windows xp iso อย่างชัดเจน ลองดู มันเป็นสารสกัดไฟล์ cab ใช้ 7z

คำเตือน! เครื่องสแกนไวรัสของคุณอาจตรวจพบ Universal Extractor / PEiD เป็นเครื่องมือแฮ็คหรือไวรัส อย่าไว้ใจมันอย่าดาวน์โหลดเลย !!


ข้อมูลเพิ่มเติมเกี่ยวกับ windows API

เครดิต: Jason C

มันไม่ใช่แค่กล่องข้อความ โดยทั่วไปแล้วWM_SETTEXTจะไม่มีพารามิเตอร์สำหรับการระบุความยาวของสตริงและสตริงนั้นจะถือว่าสิ้นสุดที่ null เสมอ คุณสามารถสร้างกล่องข้อความที่กำหนดเองพร้อมข้อความที่กำหนดเองซึ่งระบุความยาวสตริงได้เสมอ แต่ Notepad และโปรแกรมอื่น ๆ ส่วนใหญ่จะไม่สมเหตุสมผล นอกจากนี้ฟังก์ชันSetWindowTextไม่ได้ให้พารามิเตอร์ความยาวเช่นกัน


1
เป็นเรื่องแปลกเล็กน้อยที่คุณแสดงแผ่นคุณสมบัติสำหรับการปฏิบัติการ Notepad ที่มาพร้อมกับรุ่นของ Windows XP แต่ตัดสินจากชุดรูปแบบของหน้าต่างคุณกำลังใช้งาน Windows 8 บางรุ่นอย่างชัดเจนซึ่งจะอธิบายว่าทำไมปฏิบัติการที่เชื่อมโยงกับ ชุดเครื่องมือเวอร์ชัน 7.1 นั่นคือสิ่งที่พวกเขาใช้ในการรวบรวม Windows XP และยูทิลิตี้ที่เกี่ยวข้อง Notepad เวอร์ชั่น Windows 8 จะถูกรวบรวมด้วยเครื่องมือ SDK รุ่นใหม่อย่างไม่ต้องสงสัย
โคดี้เกรย์

2
มันไม่ใช่แค่กล่องข้อความ WM_SETTEXTโดยทั่วไปจะไม่มีพารามิเตอร์สำหรับการระบุความยาวของสตริงและสตริงจะถือว่าสิ้นสุดที่ null เสมอ คุณสามารถสร้างกล่องข้อความที่กำหนดเองพร้อมข้อความที่กำหนดเองซึ่งระบุความยาวสตริงได้เสมอ แต่ Notepad และโปรแกรมอื่น ๆ ส่วนใหญ่จะไม่สมเหตุสมผล
Jason C

@BhathiyaPerera เพราะฉันพอใจกับระดับของงานที่ฉันทำโดยการเพิ่มข้อมูลในความคิดเห็น คุณสามารถปรับปรุงคำตอบด้วยข้อมูลนั้นหากคุณต้องการ
Jason C

28

แผ่นจดบันทึกไม่ได้เก็บรักษาอักขระพิเศษ / ขยายทั้งหมดไว้อย่างถูกต้อง ฉันไม่มีการอ้างอิงสำหรับพฤติกรรมนี้ในมือ แต่พบว่าเป็นกรณีเช่นนี้กับจุดสิ้นสุดของบรรทัดสไตล์ LF ของ UNIX ซึ่ง Notepad จะแปลงเป็น CRLF และ null (0x00) ซึ่งมันจะไม่สนใจ ในไฟล์ไบนารีเช่น JPG มีแนวโน้มที่จะเกิดขึ้นแบบสุ่มของตัวละครที่ Notepad ไม่รักษา ลองการทดสอบของคุณด้วยเครื่องมือแก้ไข HEX ที่ทราบแล้วและควรใช้งานได้ ฉันจะอัปเดตคำตอบของฉันหากฉันพบการอ้างอิงที่ดีและเมื่อฉันทดสอบ HEX editor แล้ว

ปรับปรุง: ฉันพยายามไม่กี่ที่รู้จักกันดีบรรณาธิการโปรแกรมเมอร์ แต่เพียงหนึ่งของพวกเขาทำงานขวาปิดค้างคาวHXD โดย Mael horz ผมไม่เคยใช้ HxD ก่อน แต่พบว่ามันต้องขอบคุณคำตอบจากบทความ Stack นี้ปลั๊กอินผู้ชม hex / บรรณาธิการ Notepad ++

เครื่องมือแก้ไขอื่น ๆ ที่ไม่ทำงานหลังจากผ่านไปสองสามนาทีคือ Notepad ++, Notepad2 และ UltraEdit (v17.3, เวอร์ชันที่เก่ากว่า) คู่เหล่านี้มีปัญหาเกี่ยวกับการคัดลอก / วางของสองสามไบต์แรกหมายเลขมายากลลายเซ็นไฟล์ JPEG FF D8 FF บางทีพวกเขาอาจจะทำงานด้วยการเล่นซอมากกว่าที่ฉันมีเวลาในปัจจุบัน


Sublime Text (2/3) จะเปิดไฟล์ไบนารีโดยอัตโนมัติโดยแสดงในรูปแบบฐานสิบหก ตัวอย่างเช่นการเริ่มต้นของไฟล์ JPEG เพียงแค่คลิก "เปิด": puu.sh/aaAVx/bd08dab46e.png
tomsmeding

3
ที่จริงแล้วบ่อยกว่า notepad จะแปลง LF เป็น CRLF มันจะปล่อยให้ LF เป็นแบบเดิมและแสดงข้อความราวกับว่าไม่มีการขึ้นบรรทัดใหม่เลย!
Moshe Katz

6

คุณเคยสามารถทำสิ่งนี้กับเขียนกลับมาในวันที่ มันเป็นโปรแกรมมาตรฐานใน Windows 3.1 แต่ฉันจำไม่ได้ว่ามี Windows 95 รวมอยู่หรือไม่ การเขียนจะช่วยให้สามารถแก้ไขไฟล์ใด ๆ ที่สามารถเปิดได้อย่างปลอดภัยแบบไบนารี่ Notepad แน่นอนไม่ปลอดภัยไบนารี (ข้อความยังคงเหมือนเดิม แต่ไบต์ที่แท้จริงของตัวละครที่ไม่ใช่ข้อความ [เช่นรหัสควบคุม] อาจมีการเปลี่ยนแปลง) ซึ่งเป็นสาเหตุที่ตัวอย่าง JPG ของคุณไม่ทำงาน ลองรับสำเนาการเขียน (และ Windows ที่เก่ามาก) และลองการทดสอบของคุณอีกครั้ง!

อ้างอิงจากบทความ "การเขียนของ Windows" ของ Wikipedia ซึ่งรวมอยู่ใน Windows NT 3.5 มันถูกแทนที่ด้วย Wordpad ใน Windows 95 เป็นต้นไป write.exeยังคงอยู่ในไดเรกทอรี Windows แต่เป็นเพียงเสื้อคลุมสำหรับเปิด Wordpad


5

ฉันคิดว่ามันไม่ได้เป็นปัญหาของการเข้ารหัส แต่ยังเป็นชุดอักขระ รูปแบบ JPG นั้นเป็นสตรีมไบต์ ดังนั้นการอนุญาตให้ใช้อักขระที่ไม่สามารถพิมพ์ได้เช่น NUL, ETX, STX, SOH, DLE เป็นต้น

Microsoft Notepad ไม่สามารถแสดงอักขระที่ไม่สามารถพิมพ์ได้ มันอาจแสดงตัวยึดบางชนิดเช่นช่องว่างสำหรับตัวอักขระ null ดังนั้นการเปิดไฟล์ด้วย Notepad จะไม่แสดงเนื้อหาจริง แต่เนื้อหาที่ถอดรหัสโดยการเข้ารหัสที่เลือก (utf-8, utf-16, ฯลฯ ) และแสดงโดยชุดอักขระบางตัว (unicode, ascii, etc) ยกเว้นที่ไม่ใช่ อักขระที่พิมพ์ได้

เมื่อเลือกข้อความที่แสดงทั้งหมดและคัดลอกข้อความไปยังคลิปบอร์ดคุณเพียงคัดลอกอักขระที่พิมพ์ได้รวมถึงตัวยึดตำแหน่ง ดังนั้นการแปลงอักขระ null ให้เป็นช่องว่างโดยอัตโนมัติและไม่สนใจอักขระอื่นที่ไม่สามารถพิมพ์ได้ทั้งหมด

ดังนั้นโดยทั่วไปคุณก็สูญเสียเนื้อหาทำอย่างนี้ หากคุณใช้ hex-editor แทนมันจะคัดลอกเนื้อหาทั้งหมด


อัปเดต: คำตอบ Bhathiya Pereras ถูกต้อง: https://superuser.com/a/782885/322784 อักขระที่ไม่สามารถพิมพ์ได้จะไม่ถูกละเว้นเมื่อคัดลอกข้อความไปยังคลิปบอร์ด


ทุกไฟล์คือ "โดยทั่วไปเป็นสตรีมไบต์"
Jason C

1
@ JasonC ฉันจะไม่เห็นด้วย ในขณะที่ทุกไฟล์สามารถอ่านได้ในรูปแบบสตรีมไบต์ ไฟล์ที่มีโครงสร้างเช่นไฟล์ XML ไม่สามารถอ่านเป็นสตรีมข้อมูลได้ เนื้อหาจะไม่ถูกต้องจนกว่าจะสิ้นสุดการอ่านไฟล์ การตัดครึ่ง jpg ยังคงใช้ได้และสามารถแสดงผลได้ มันหายไปครึ่งภาพ
sbecker

ไม่มีที่ว่างสำหรับความขัดแย้งในเรื่องนั้น :) XML เป็นกระแสข้อมูลไบต์เหมือนอย่างอื่นและ XML (พร้อมการเข้ารหัสอักขระ) กำหนดรูปแบบสำหรับไบต์เหล่านั้น แน่นอนมันสามารถอ่านได้เป็นกระแสข้อมูล ตัวอย่างเช่นเปิดมันในโปรแกรมแก้ไข hex กระแสข้อมูลนั้นเกิดขึ้นเพื่อแยกวิเคราะห์เป็น XML
Jason C

@ JasonC ไม่สามารถโต้เถียงกับที่จริงแล้ว :) Touché!
sbecker

2

ไฟล์ JPEG มีข้อมูลที่ไม่ใช่ข้อความยกเว้นบางฟิลด์โดยทั่วไปแล้วจะพบค่าไบต์ใด ๆ ระหว่าง 0 ถึง 255 โดยเฉพาะอย่างยิ่งในพื้นที่ที่เป็นตัวแทนของภาพบีบอัดที่เข้ารหัสซึ่งมีข้อมูลปลอมเกือบทั้งหมด

แต่ Notepad จะใช้ข้อมูลเป็นข้อความ ANSI ตามค่าเริ่มต้นดังนั้นมันจะทำสิ่งต่าง ๆ ที่จะเปลี่ยนแปลงข้อมูลต้นฉบับเช่น:

  • แทนที่ไบต์การแมปอักขระพิเศษ / ไม่ได้กำหนด / ต้องห้ามเนื่องจากไม่เหมาะสมสำหรับข้อความ ANSI ที่ถูกต้อง

  • กำลังเข้ารหัสอักขระ null, สิ้นสุดบรรทัดและสิ้นสุดการเรียงลำดับไฟล์ตามแบบแผน Windows / DOS

ซึ่งหมายความว่าถ้าคุณแก้ไขและบันทึกข้อมูลเป็นข้อความมันจะเปลี่ยน jpeg ในกรณีที่ดีที่สุดและทำให้ใช้ไม่ได้ในที่เลวร้ายที่สุด


"ANSI" ไม่ถูกต้องทางเทคนิคแม้ว่าจะเป็นที่เข้าใจกันทั่วไป
Jason C
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.