ฉันทำงานกับห้องสมุดที่คืนสตริงไบต์และฉันต้องการแปลงเป็นสตริง
แม้ว่าฉันจะไม่แน่ใจว่าความแตกต่างคืออะไรถ้ามี
ฉันทำงานกับห้องสมุดที่คืนสตริงไบต์และฉันต้องการแปลงเป็นสตริง
แม้ว่าฉันจะไม่แน่ใจว่าความแตกต่างคืออะไรถ้ามี
คำตอบ:
สมมติว่า Python 3 (ใน Python 2 ความแตกต่างนี้มีความหมายน้อยกว่าเล็กน้อย) - สตริงเป็นลำดับของอักขระเช่นunicode codepoints ; นี่เป็นแนวคิดที่เป็นนามธรรมและไม่สามารถเก็บไว้ในดิสก์ได้โดยตรง สตริงไบต์เป็นลำดับไบต์ที่แปลกประหลาดสิ่งต่าง ๆ ที่สามารถเก็บไว้ในดิสก์ การทำแผนที่ระหว่างพวกเขาเป็นการเข้ารหัส - มีจำนวนมากเหล่านี้ (และเป็นไปไม่ได้มากมาย) - และคุณจำเป็นต้องรู้ว่าสิ่งใดที่นำไปใช้ในกรณีเฉพาะเพื่อทำการแปลงเนื่องจากการเข้ารหัสที่แตกต่างกันอาจทำแผนที่ไบต์เดียวกัน เป็นสตริงอื่น:
>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-16')
'蓏콯캁澽苏'
>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-8')
'τoρνoς'
เมื่อคุณทราบว่าจะใช้อันไหนคุณสามารถใช้.decode()
วิธีการของสตริงไบต์เพื่อรับสตริงอักขระที่ถูกต้องจากด้านบน เพื่อความสมบูรณ์.encode()
เมธอดของสตริงอักขระจะไปในทางตรงกันข้าม:
>>> 'τoρνoς'.encode('utf-8')
b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'
str
วัตถุPython 3 นั้นไม่สามารถเข้าถึงได้หรือเกี่ยวข้องจากด้าน Python โครงสร้างข้อมูลเป็นเพียงลำดับของ codepoints ภายใต้PEP 393การเข้ารหัสภายในที่แน่นอนคือหนึ่งใน Latin-1, UCS2 หรือ UCS4 และการแทน utf-8 อาจถูกแคชหลังจากได้รับการร้องขอเป็นครั้งแรก แต่แม้กระทั่งรหัส C ก็ไม่จำเป็นต้องพึ่งพารายละเอียดภายในเหล่านี้
สิ่งเดียวที่คอมพิวเตอร์สามารถจัดเก็บได้คือไบต์
ในการจัดเก็บทุกอย่างในคอมพิวเตอร์คุณต้องเข้ารหัสก่อนเช่นแปลงเป็นไบต์ ตัวอย่างเช่น:
MP3
, WAV
ฯลฯPNG
, JPEG
ฯลฯASCII
, UTF-8
ฯลฯMP3
, WAV
, PNG
, JPEG
, ASCII
และUTF-8
เป็นตัวอย่างของการเข้ารหัส การเข้ารหัสเป็นรูปแบบที่ใช้แทนเสียงรูปภาพข้อความ ฯลฯ เป็นไบต์
ใน Python สตริงไบต์เป็นเพียง: ลำดับของไบต์ มันไม่สามารถอ่านได้โดยมนุษย์ ภายใต้ประทุนทุกอย่างจะต้องถูกแปลงเป็นสตริงไบต์ก่อนที่จะสามารถเก็บไว้ในคอมพิวเตอร์ได้
ในทางกลับกันสตริงอักขระที่มักจะเรียกว่า "สตริง" คือลำดับของอักขระ มันเป็นมนุษย์อ่านได้ สตริงอักขระไม่สามารถเก็บไว้ในคอมพิวเตอร์ได้โดยตรง แต่ต้องเข้ารหัสก่อน (แปลงเป็นสตริงไบต์) มีการเข้ารหัสหลายผ่านซึ่งเป็นสายอักขระสามารถแปลงเป็นสตริงไบต์เช่นมีและASCII
UTF-8
'I am a string'.encode('ASCII')
รหัสงูใหญ่ดังกล่าวข้างต้นจะเข้ารหัสสตริงโดยใช้การเข้ารหัส'I am a string'
ASCII
ผลลัพธ์ของโค้ดด้านบนจะเป็นสตริงไบต์ หากคุณพิมพ์, Python b'I am a string'
จะแสดงเป็น อย่างไรก็ตามจำไว้ว่าสตริงไบต์ไม่สามารถอ่านได้โดยมนุษย์มันเป็นเพียงแค่ไพ ธ อนถอดรหัสมันASCII
เมื่อคุณพิมพ์มัน ใน Python สตริงไบต์จะถูกแทนด้วย a b
ตามด้วยสตริงไบต์ASCII
แทน
สตริงไบต์สามารถถอดรหัสกลับเป็นสตริงอักขระได้หากคุณรู้ว่าการเข้ารหัสที่ใช้ในการเข้ารหัส
b'I am a string'.decode('ASCII')
'I am a string'
รหัสข้างต้นจะส่งกลับสายเดิม
การเข้ารหัสและถอดรหัสเป็นการดำเนินการผกผัน ทุกอย่างจะต้องได้รับการเข้ารหัสก่อนที่จะสามารถเขียนลงดิสก์ได้และจะต้องถอดรหัสก่อนที่มนุษย์จะสามารถอ่านได้
หมายเหตุ:ฉันจะอธิบายคำตอบของฉันสำหรับ Python 3 ให้ละเอียดยิ่งขึ้นเนื่องจากการสิ้นสุดของ Python 2 ใกล้จะจบลง
ใน Python 3
bytes
ประกอบด้วยลำดับของค่าที่ไม่ได้ลงทะเบียน 8 บิตในขณะที่str
ประกอบด้วยลำดับของจุดรหัส Unicode ที่แสดงถึงตัวละครที่เป็นข้อความจากภาษามนุษย์
>>> # bytes
>>> b = b'h\x65llo'
>>> type(b)
<class 'bytes'>
>>> list(b)
[104, 101, 108, 108, 111]
>>> print(b)
b'hello'
>>>
>>> # str
>>> s = 'nai\u0308ve'
>>> type(s)
<class 'str'>
>>> list(s)
['n', 'a', 'i', '̈', 'v', 'e']
>>> print(s)
naïve
แม้ว่าbytes
และstr
ดูเหมือนจะทำงานในลักษณะเดียวกันกรณีของพวกเขาจะไม่เข้ากันกับแต่ละอื่น ๆ เช่นbytes
และstr
กรณีที่ไม่สามารถใช้ร่วมกันกับผู้ประกอบการเช่นและ>
+
นอกจากนี้โปรดทราบว่าการเปรียบเทียบbytes
และstr
อินสแตนซ์ของความเท่าเทียมกันเช่นการใช้==
จะมีการประเมินเสมอFalse
แม้ว่าจะมีอักขระเหมือนกันทุกประการก็ตาม
>>> # concatenation
>>> b'hi' + b'bye' # this is possible
b'hibye'
>>> 'hi' + 'bye' # this is also possible
'hibye'
>>> b'hi' + 'bye' # this will fail
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't concat str to bytes
>>> 'hi' + b'bye' # this will also fail
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "bytes") to str
>>>
>>> # comparison
>>> b'red' > b'blue' # this is possible
True
>>> 'red'> 'blue' # this is also possible
True
>>> b'red' > 'blue' # you can't compare bytes with str
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'bytes' and 'str'
>>> 'red' > b'blue' # you can't compare str with bytes
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'bytes'
>>> b'blue' == 'red' # equality between str and bytes always evaluates to False
False
>>> b'blue' == 'blue' # equality between str and bytes always evaluates to False
False
ปัญหาอื่นเมื่อจัดการกับbytes
และstr
แสดงเมื่อทำงานกับไฟล์ที่ส่งคืนโดยใช้open
ฟังก์ชันในตัว ถ้าคุณต้องการอ่านหรือเขียนข้อมูลไบนารีไปยัง / จากไฟล์ให้เปิดไฟล์โดยใช้โหมดไบนารีเช่น 'rb' หรือ 'wb' เสมอ ในทางตรงกันข้ามหากคุณต้องการอ่านหรือเขียนข้อมูล Unicode ไปยัง / จากไฟล์ให้ระวังการเข้ารหัสเริ่มต้นของคอมพิวเตอร์ของคุณดังนั้นหากจำเป็นให้ส่งencoding
พารามิเตอร์เพื่อหลีกเลี่ยงความประหลาดใจ
ใน Python 2
str
ประกอบด้วยลำดับของค่า 8 บิตในขณะที่unicode
ประกอบด้วยลำดับของอักขระ Unicode สิ่งหนึ่งที่ต้องเก็บไว้ในใจก็คือว่าstr
และunicode
สามารถใช้ร่วมกันกับผู้ประกอบการถ้าstr
เพียงประกอบด้วยอักขระ ASCI 7 บิต
อาจเป็นประโยชน์ในการใช้ฟังก์ชันตัวช่วยเพื่อแปลงระหว่างstr
และunicode
ใน Python 2 และระหว่างbytes
และstr
ใน Python 3
จากUnicode คืออะไร :
คอมพิวเตอร์จะจัดการกับตัวเลข พวกเขาเก็บตัวอักษรและตัวละครอื่น ๆ โดยการกำหนดหมายเลขสำหรับแต่ละคน
......
Unicode ให้หมายเลขที่ไม่ซ้ำกันสำหรับตัวละครทุกตัวไม่ว่าแพลตฟอร์มใดไม่ว่าจะเป็นโปรแกรมอะไรไม่ว่าจะเป็นภาษาใดก็ตาม
ดังนั้นเมื่อคอมพิวเตอร์แสดงถึงสตริงค้นหาอักขระที่เก็บอยู่ในคอมพิวเตอร์ของสตริงผ่านหมายเลข Unicode ที่ไม่ซ้ำกันและตัวเลขเหล่านี้จะถูกเก็บไว้ในหน่วยความจำ แต่คุณไม่สามารถเขียนสตริงลงดิสก์โดยตรงหรือส่งสตริงบนเครือข่ายผ่านหมายเลข Unicode ที่ไม่ซ้ำกันได้เพราะตัวเลขเหล่านี้เป็นเพียงเลขฐานสิบธรรมดา UTF-8
คุณควรเข้ารหัสสตริงสตริงไบต์เช่น UTF-8
เป็นการเข้ารหัสอักขระที่สามารถเข้ารหัสอักขระที่เป็นไปได้ทั้งหมดและจัดเก็บอักขระเป็นไบต์ (ดูเหมือนว่านี้ ) ดังนั้นสตริงที่เข้ารหัสสามารถใช้ได้ทุกที่เพราะUTF-8
เกือบจะรองรับทุกที่ เมื่อคุณเปิดไฟล์ข้อความที่เข้ารหัสUTF-8
จากระบบอื่นคอมพิวเตอร์ของคุณจะถอดรหัสและแสดงอักขระผ่านหมายเลข Unicode ที่ไม่ซ้ำกัน เมื่อเบราว์เซอร์ได้รับข้อมูลสตริงที่เข้ารหัสUTF-8
จากเครือข่ายเบราว์เซอร์จะถอดรหัสข้อมูลเป็นสตริง (ถือว่าเบราว์เซอร์กำลังUTF-8
เข้ารหัส) และแสดงสตริง
ใน python3 คุณสามารถแปลงสตริงและสตริงไบต์เป็น:
>>> print('中文'.encode('utf-8'))
b'\xe4\xb8\xad\xe6\x96\x87'
>>> print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))
中文
ในคำว่าสตริงสำหรับการแสดงให้มนุษย์ที่จะอ่านบนคอมพิวเตอร์และสตริงไบต์สำหรับการจัดเก็บไปยังดิสก์และการส่งข้อมูล
Unicode เป็นรูปแบบที่ได้ตกลงกันไว้สำหรับการแสดงไบนารีของอักขระและการจัดรูปแบบต่าง ๆ (เช่นตัวพิมพ์เล็ก / ตัวพิมพ์ใหญ่, ขึ้นบรรทัดใหม่, การขึ้นบรรทัดใหม่), และ "สิ่งของ" อื่น ๆ (เช่น emojis) คอมพิวเตอร์ไม่สามารถจัดเก็บการแทนยูนิโค้ดได้ (ชุดของบิต) ไม่ว่าในหน่วยความจำหรือในไฟล์มากกว่าที่จะเก็บการแทน ASCII (ชุดของบิตที่แตกต่างกัน) หรือการแทนอื่น ๆ (ชุดของบิต )
สำหรับการสื่อสารที่จะเกิดขึ้นฝ่ายต่างๆในการสื่อสารจะต้องเห็นด้วยกับสิ่งที่จะใช้ในการเป็นตัวแทน
เนื่องจากยูนิโค้ดพยายามที่จะเป็นตัวแทนของตัวละครที่เป็นไปได้ทั้งหมด (และ "สิ่ง" อื่น ๆ ) ที่ใช้ในการสื่อสารระหว่างมนุษย์และระหว่างคอมพิวเตอร์จึงต้องใช้จำนวนบิตที่มากขึ้นสำหรับการเป็นตัวแทนของอักขระหลายตัว (หรือหลายสิ่ง) พยายามที่จะเป็นตัวแทนของตัวละคร / สิ่งที่ จำกัด เพื่อ "ลดความซับซ้อน" และบางทีเพื่อรองรับการใช้งานในอดีตการแทนยูนิโค้ดเกือบจะถูกแปลงเป็นระบบการแสดงอื่น ๆ (เช่น ascii) เพื่อวัตถุประสงค์ในการจัดเก็บอักขระในไฟล์
มันไม่ได้เป็นกรณีที่ Unicode ไม่สามารถนำมาใช้สำหรับการจัดเก็บตัวอักษรในไฟล์หรือส่งพวกเขาผ่านทางใดช่องทางสื่อสารเพียงแค่ว่ามันเป็นไม่ได้
คำว่า "string" ไม่ได้ถูกกำหนดอย่างแม่นยำ "String" ในการใช้งานทั่วไปหมายถึงชุดอักขระ / สิ่งต่าง ๆ ในคอมพิวเตอร์ตัวละครเหล่านั้นอาจถูกจัดเก็บในรูปแบบที่แตกต่างกันไปในแต่ละบิต "ไบต์สตริง" เป็นชุดของตัวละครที่เก็บไว้โดยใช้การเป็นตัวแทนที่ใช้แปดบิต (แปดบิตถูกเรียกว่าเป็นไบต์) ตั้งแต่วันนี้คอมพิวเตอร์ใช้ระบบ unicode (อักขระที่แสดงด้วยจำนวนตัวแปรไบต์) เพื่อเก็บอักขระไว้ในหน่วยความจำและสตริงไบต์ (อักขระที่แทนด้วยไบต์เดียว) เพื่อเก็บอักขระไว้ในไฟล์การแปลงจะต้องใช้ก่อนแสดงอักขระ ในหน่วยความจำจะถูกย้ายไปเก็บไว้ในไฟล์
มามีสตริงอักขระหนึ่งตัวที่ง่าย'š'
และเข้ารหัสลงในลำดับไบต์:
>>> 'š'.encode('utf-8')
b'\xc5\xa1'
สำหรับจุดประสงค์ของตัวอย่างนี้เราจะแสดงลำดับของไบต์ในรูปแบบไบนารี่:
>>> bin(int(b'\xc5\xa1'.hex(), 16))
'0b1100010110100001'
ตอนนี้มันเป็นไปไม่ได้ที่จะถอดรหัสข้อมูลกลับโดยที่ไม่รู้ว่ามันถูกเข้ารหัสอย่างไร เฉพาะในกรณีที่คุณรู้ว่ามีการใช้การutf-8
เข้ารหัสข้อความคุณสามารถทำตามอัลกอริทึมสำหรับการถอดรหัส utf-8และรับสตริงต้นฉบับ:
11000101 10100001
^^^^^ ^^^^^^
00101 100001
คุณสามารถแสดงเลขฐานสอง101100001
กลับเป็นสตริง:
>>> chr(int('101100001', 2))
'š'
ภาษา Python ประกอบด้วยstr
และbytes
เป็น "มาตรฐานชนิดที่มีอยู่ภายใน" กล่าวอีกนัยหนึ่งพวกเขาทั้งสองเรียน ฉันไม่คิดว่ามันคุ้มค่าที่จะพยายามหาเหตุผลว่าทำไม Python จึงถูกนำไปใช้ในวิธีนี้
ต้องบอกว่าstr
และbytes
มีความคล้ายคลึงกันมาก ทั้งสองวิธีส่วนใหญ่ใช้วิธีเดียวกันร่วมกัน วิธีการต่อไปนี้ไม่ซ้ำกันในstr
ชั้นเรียน:
casefold
encode
format
format_map
isdecimal
isidentifier
isnumeric
isprintable
วิธีการต่อไปนี้ไม่ซ้ำกันในbytes
ชั้นเรียน:
decode
fromhex
hex
str
ประเภทเป็นเช่นเดียวกับbytes
ประเภท; คำตอบนี้เทียบเท่าการเปรียบเทียบunicode
ประเภท (ไม่มีอยู่ใน Python 3) กับstr
ประเภท