python - यूनिकोड(यूटीएफ-8) पायथन में फ़ाइलों को पढ़ने और लिखना




unicode utf-8 (9)

मुझे फ़ाइल में पाठ पढ़ने और लिखने में कुछ मस्तिष्क विफलता है (पायथन 2.4)।

# The string, which has an a-acute in it.
ss = u'Capit\xe1n'
ss8 = ss.encode('utf8')
repr(ss), repr(ss8)

("u'Capit \ xe1n '", "कैपिट \ xc3 \ xa1n'")

print ss, ss8
print >> open('f1','w'), ss8

>>> file('f1').read()
'Capit\xc3\xa1n\n'

तो मैं फ़ाइल f2 में, मेरे पसंदीदा संपादक में Capit\xc3\xa1n करता हूं।

फिर:

>>> open('f1').read()
'Capit\xc3\xa1n\n'
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'
>>> open('f1').read().decode('utf8')
u'Capit\xe1n\n'
>>> open('f2').read().decode('utf8')
u'Capit\\xc3\\xa1n\n'

मैं यहाँ क्या समझ नहीं रहा हूँ? जाहिर है जादू के कुछ महत्वपूर्ण बिट (या अच्छी समझ) है कि मैं याद कर रहा हूँ। उचित रूपांतरण प्राप्त करने के लिए टेक्स्ट फ़ाइलों में से कोई क्या टाइप करता है?

मैं वास्तव में यहां घूमने में असफल रहा हूं, यूटीएफ -8 प्रतिनिधित्व का मुद्दा यह है कि यदि आप वास्तव में पाइथन को पहचानने के लिए नहीं पाते हैं, तो यह बाहर से आता है। शायद मुझे सिर्फ जेएसओएन स्ट्रिंग को डंप करना चाहिए, और इसके बजाय इसका उपयोग करना चाहिए, क्योंकि इसका एक असभ्य प्रतिनिधित्व है! इस बिंदु पर, क्या इस यूनिकोड ऑब्जेक्ट का एक ASCII प्रतिनिधित्व है कि फ़ाइल से आने पर पाइथन पहचान और डीकोड करेगा? यदि हां, तो मैं इसे कैसे प्राप्त करूं?

>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'

\ X .. अनुक्रम कुछ ऐसा है जो पायथन के लिए विशिष्ट है। यह एक सार्वभौमिक बाइट एस्केप अनुक्रम नहीं है।

आप वास्तव में यूटीएफ -8-एन्कोडेड गैर-ASCII में कैसे प्रवेश करते हैं, आपके ओएस और / या आपके संपादक पर निर्भर करता है। यहां विंडोज़ में आप इसे कैसे करते हैं । ओएस एक्स के लिए एक तीव्र उच्चारण के साथ प्रवेश करने के लिए आप विकल्प + , फिर , और ओएस एक्स में लगभग सभी पाठ संपादकों को यूटीएफ -8 का समर्थन कर सकते हैं।


अब आपको Python3 में जो कुछ चाहिए वह open(Filename, 'r', encoding='utf-8')

[अनुरोधित स्पष्टीकरण के लिए 2016-02-10 को संपादित करें]

पायथन 3 ने अपने खुले फ़ंक्शन में एन्कोडिंग पैरामीटर जोड़ा। खुले फ़ंक्शन के बारे में निम्न जानकारी यहां से एकत्र की गई है: https://docs.python.org/3/library/functions.html#open

open(file, mode='r', buffering=-1, 
      encoding=None, errors=None, newline=None, 
      closefd=True, opener=None)

एन्कोडिंग फ़ाइल को डीकोड या एन्कोड करने के लिए उपयोग किए जाने वाले एन्कोडिंग का नाम है। इसका उपयोग केवल टेक्स्ट मोड में किया जाना चाहिए। डिफ़ॉल्ट एन्कोडिंग प्लेटफार्म निर्भर है (जो भी locale.getpreferredencoding() रिटर्न), लेकिन पाइथन द्वारा समर्थित कोई भी टेक्स्ट एन्कोडिंग का उपयोग किया जा सकता है। समर्थित एन्कोडिंग की सूची के लिए codecs मॉड्यूल देखें।

तो ओपन फ़ंक्शन के पैरामीटर के रूप में encoding='utf-8' जोड़कर, फ़ाइल पढ़ने और लिखने को सभी utf8 के रूप में किया जाता है (जो अब पाइथन में किए गए सब कुछ का डिफ़ॉल्ट एन्कोडिंग भी है।)


आपने एन्कोडिंग के साथ सामान्य समस्या पर ठोकर खाई है: मैं कैसे बता सकता हूं कि फ़ाइल एन्कोडिंग कौन सा है?

उत्तर: आप तब तक नहीं कर सकते जब तक फ़ाइल प्रारूप इस के लिए प्रदान नहीं करता है। एक्सएमएल, उदाहरण के लिए, से शुरू होता है:

<?xml encoding="utf-8"?>

यह हेडर ध्यान से चुना गया था ताकि इसे एन्कोडिंग से कोई फर्क नहीं पड़ता। आपके मामले में, ऐसा कोई संकेत नहीं है, इसलिए न तो आपके संपादक और न ही पायथन को पता है कि क्या हो रहा है। इसलिए, आपको codecs मॉड्यूल का उपयोग करना चाहिए और codecs.open(path,mode,encoding) उपयोग करना चाहिए जो पाइथन में लापता बिट प्रदान करता है।

आपके संपादक के लिए, आपको यह जांचना होगा कि क्या यह फ़ाइल के एन्कोडिंग को सेट करने का कोई तरीका प्रदान करता है या नहीं।

यूटीएफ -8 का बिंदु 21-बिट अक्षरों (यूनिकोड) को 8-बिट डेटा स्ट्रीम के रूप में एन्कोड करने में सक्षम होना चाहिए (क्योंकि यह एकमात्र चीज है जो दुनिया के सभी कंप्यूटर संभाल सकते हैं)। लेकिन चूंकि अधिकांश ओएस यूनिकोड युग की भविष्यवाणी करते हैं, इसलिए उनके पास हार्ड डिस्क पर फ़ाइलों को एन्कोडिंग जानकारी संलग्न करने के लिए उपयुक्त उपकरण नहीं हैं।

अगला मुद्दा पायथन में प्रतिनिधित्व है। यह heikogerlach द्वारा टिप्पणी में पूरी तरह से समझाया गया है । आपको समझना होगा कि आपका कंसोल केवल ASCII प्रदर्शित कर सकता है। यूनिकोड या कुछ भी प्रदर्शित करने के लिए> = charcode 128, इसे भागने के कुछ साधनों का उपयोग करना चाहिए। आपके संपादक में, आपको बच निकले हुए प्रदर्शन स्ट्रिंग को टाइप नहीं करना चाहिए, लेकिन स्ट्रिंग का क्या अर्थ है (इस मामले में, आपको उमलॉट दर्ज करना होगा और फ़ाइल को सहेजना होगा)।

उस ने कहा, आप एक स्ट्रिंग में एक बच निकलने वाली स्ट्रिंग को चालू करने के लिए पाइथन फ़ंक्शन eval () का उपयोग कर सकते हैं:

>>> x = eval("'Capit\\xc3\\xa1n\\n'")
>>> x
'Capit\xc3\xa1n\n'
>>> x[5]
'\xc3'
>>> len(x[5])
1

जैसा कि आप देख सकते हैं, स्ट्रिंग "\ xc3" को एक वर्ण में बदल दिया गया है। यह अब 8-बिट स्ट्रिंग, यूटीएफ -8 एन्कोडेड है। यूनिकोड प्राप्त करने के लिए:

>>> x.decode('utf-8')
u'Capit\xe1n\n'

ने पूछा: मुझे लगता है कि यहां कुछ टुकड़े गायब हैं: फ़ाइल f2 में शामिल हैं: हेक्स:

0000000: 4361 7069 745c 7863 335c 7861 316e  Capit\xc3\xa1n

codecs.open('f2','rb', 'utf-8') , उदाहरण के लिए, उन्हें एक अलग वर्ण (अपेक्षित) में पढ़ता है क्या एएससीआईआईआई में एक फ़ाइल को लिखने का कोई तरीका है जो काम करेगा?

उत्तर: यह आपके मतलब पर निर्भर करता है। ASCII पात्रों का प्रतिनिधित्व नहीं कर सकता> 127. तो आपको "अगले कुछ पात्रों का मतलब कुछ विशेष" कहने के लिए कुछ तरीका चाहिए, जो अनुक्रम "\ x" करता है। यह कहता है: अगले दो अक्षर एक ही चरित्र का कोड हैं। "\ u" यूनिकोड को 0xFFFF (65535) तक एन्कोड करने के लिए चार अक्षरों का उपयोग करता है।

तो आप सीधे यूनिकोड को ASCII में नहीं लिख सकते हैं (क्योंकि ASCII में केवल वही वर्ण नहीं होते हैं)। आप इसे स्ट्रिंग एस्केप के रूप में लिख सकते हैं (जैसा कि f2 में); इस मामले में, फ़ाइल ASCII के रूप में प्रदर्शित किया जा सकता है। या आप इसे यूटीएफ -8 के रूप में लिख सकते हैं, इस मामले में, आपको 8-बिट सुरक्षित स्ट्रीम की आवश्यकता है।

decode('string-escape') का उपयोग करके आपका समाधान काम करता है, लेकिन आपको अवगत होना चाहिए कि आप कितनी मेमोरी का उपयोग करते हैं: codecs.open() का उपयोग करने की मात्रा तीन गुणा।

याद रखें कि एक फ़ाइल केवल 8 बिट्स के साथ बाइट्स का अनुक्रम है। न तो बिट्स और न ही बाइट्स का अर्थ है। यह आप हैं जो कहते हैं "65 मतलब 'ए'"। चूंकि \xc3\xa1 "à" बनना चाहिए, लेकिन कंप्यूटर को जानने का कोई मतलब नहीं है, आपको फ़ाइल लिखते समय उपयोग किए गए एन्कोडिंग को निर्दिष्ट करके इसे बताना होगा।


इसलिए, मुझे जो भी ढूंढ रहा है उसके लिए मुझे एक समाधान मिला है, जो है:

print open('f2').read().decode('string-escape').decode("utf-8")

यहां कुछ असामान्य कोडेक हैं जो यहां उपयोगी हैं। यह विशेष पढ़ने से किसी को पाइथन के भीतर से यूटीएफ -8 प्रस्तुतियों को लेने की अनुमति मिलती है, उन्हें एक ASCII फ़ाइल में कॉपी करें, और उन्हें यूनिकोड में पढ़ा जाए। "स्ट्रिंग-एस्केप" डीकोड के तहत, स्लेश को दोगुना नहीं किया जाएगा।

यह उस दौर की यात्रा के लिए अनुमति देता है जिसे मैं कल्पना कर रहा था।


खैर, आपके पसंदीदा टेक्स्ट एडिटर को यह एहसास नहीं है कि \xc3\xa1 को अक्षर अक्षर होना चाहिए, लेकिन यह उन्हें टेक्स्ट के रूप में व्याख्या करता है। यही कारण है कि आपको अंतिम पंक्ति में डबल बैकस्लैश मिलते हैं - यह अब आपकी फ़ाइल में एक असली बैकस्लैश + xc3 , आदि है।

यदि आप पाइथन में एन्कोडेड फ़ाइलों को पढ़ना और लिखना चाहते हैं, तो सबसे अच्छा codecs मॉड्यूल का उपयोग करें।

टर्मिनल और अनुप्रयोगों के बीच पाठ चिपकाना मुश्किल है, क्योंकि आप नहीं जानते कि कौन सा प्रोग्राम आपके टेक्स्ट को एन्कोडिंग का उपयोग करके व्याख्या करेगा। आप निम्न कोशिश कर सकते हैं:

>>> s = file("f1").read()
>>> print unicode(s, "Latin-1")
Capitán

फिर इस स्ट्रिंग को अपने संपादक में पेस्ट करें और सुनिश्चित करें कि यह लैटिन -1 का उपयोग करके इसे संग्रहीत करता है। धारणा के तहत कि क्लिपबोर्ड स्ट्रिंग को खराब नहीं करता है, राउंड ट्रिप काम करना चाहिए।


नोटेशन में

u'Capit\xe1n\n'

"\ xe1" केवल एक बाइट का प्रतिनिधित्व करता है। "\ x" आपको बताता है कि "ई 1" हेक्साडेसिमल में है। जब आप लिखते हैं

Capit\xc3\xa1n

आपकी फ़ाइल में आपके पास "\ xc3" है। वे 4 बाइट हैं और आपके कोड में आप उन्हें सब पढ़ते हैं। जब आप उन्हें प्रदर्शित करते हैं तो आप इसे देख सकते हैं:

>>> open('f2').read()
'Capit\\xc3\\xa1n\n'

आप देख सकते हैं कि बैकस्लैश बैकस्लैश से बच निकला है। तो आपके स्ट्रिंग में चार बाइट हैं: "\", "x", "c" और "3"।

संपादित करें:

जैसा कि अन्य ने अपने उत्तरों में बताया है, आपको केवल संपादक में पात्रों को दर्ज करना चाहिए और आपके संपादक को यूटीएफ -8 में रूपांतरण को संभालना चाहिए और इसे सहेजना चाहिए।

यदि आपके पास वास्तव में इस प्रारूप में एक स्ट्रिंग है तो आप स्ट्रिंग_स्केप कोडेक को सामान्य स्ट्रिंग में डीकोड करने के लिए उपयोग कर सकते हैं:

In [15]: print 'Capit\\xc3\\xa1n\n'.decode('string_escape')
Capitán

नतीजा एक स्ट्रिंग है जो यूटीएफ -8 में एन्कोड किया गया है जहां उच्चारण वर्ण दो बाइट्स द्वारा \\xc3\\xa1 गया है जो मूल स्ट्रिंग में \\xc3\\xa1 लिखा गया था। यदि आप एक यूनिकोड स्ट्रिंग चाहते हैं तो आपको यूटीएफ -8 के साथ फिर से डीकोड करना होगा।

आपके संपादन में: आपके पास आपकी फ़ाइल में यूटीएफ -8 नहीं है। वास्तव में यह देखने के लिए कि यह कैसा दिखाई देगा:

s = u'Capit\xe1n\n'
sutf8 = s.encode('UTF-8')
open('utf-8.out', 'w').write(sutf8)

आपके संपादक के साथ सहेजी गई फ़ाइल की सामग्री के लिए फ़ाइल utf-8.out की सामग्री की तुलना करें।


यूनिकोड स्ट्रिंग में पढ़ने के लिए और फिर HTML पर भेजें, मैंने यह किया:

fileline.decode("utf-8").encode('ascii', 'xmlcharrefreplace')

पायथन संचालित http सर्वर के लिए उपयोगी।


codecs.open() को छोड़कर, कोई यूनिकोड फ़ाइल पढ़ने / लिखने के लिए Python2 या Python3 के साथ काम करने के लिए io.open() का उपयोग कर सकता है

उदाहरण

import io

text = u'á'
encoding = 'utf8'

with io.open('data.txt', 'w', encoding=encoding, newline='\n') as fout:
    fout.write(text)

with io.open('data.txt', 'r', encoding=encoding, newline='\n') as fin:
    text2 = fin.read()

assert text == text2

# -*- encoding: utf-8 -*-

# converting a unknown formatting file in utf-8

import codecs
import commands

file_location = "jumper.sub"
file_encoding = commands.getoutput('file -b --mime-encoding %s' % file_location)

file_stream = codecs.open(file_location, 'r', file_encoding)
file_output = codecs.open(file_location+"b", 'w', 'utf-8')

for l in file_stream:
    file_output.write(l)

file_stream.close()
file_output.close()






io