पाठ की एन्कोडिंग का निर्धारण कैसे करें?


219

मुझे कुछ पाठ मिला है जो एन्कोडेड है, लेकिन मुझे नहीं पता कि चारसेट का क्या उपयोग किया गया था। क्या पायथन का उपयोग करके टेक्स्ट फ़ाइल के एन्कोडिंग को निर्धारित करने का एक तरीका है? मैं C # के साथ पाठ फ़ाइल सौदों के एन्कोडिंग / कोडपेज का पता कैसे लगा सकता हूं

जवाबों:


225

सही ढंग से एन्कोडिंग का हर समय पता लगाना असंभव है

(चर्डसेट FAQ से :)

हालांकि, कुछ एन्कोडिंग विशिष्ट भाषाओं के लिए अनुकूलित हैं, और भाषाएँ यादृच्छिक नहीं हैं। कुछ चरित्र अनुक्रम हर समय पॉप अप करते हैं, जबकि अन्य अनुक्रम कोई मतलब नहीं रखते हैं। अंग्रेजी में धाराप्रवाह व्यक्ति जो एक अखबार खोलता है और पाता है "txzqJv 2! Dasd0a QqdKjvz" तुरंत पहचान लेगा कि अंग्रेजी नहीं है (भले ही यह पूरी तरह से अंग्रेजी अक्षरों से बना हो)। बहुत सारे "विशिष्ट" पाठ का अध्ययन करके, एक कंप्यूटर एल्गोरिथ्म इस तरह के प्रवाह को अनुकरण कर सकता है और एक पाठ की भाषा के बारे में शिक्षित अनुमान लगा सकता है।

नहीं है chardet पुस्तकालय है कि का उपयोग करता है कि अध्ययन एन्कोडिंग पता लगाने के लिए प्रयास करने के लिए। chardet मोज़िला में ऑटो-डिटेक्शन कोड का एक पोर्ट है।

आप यूनिकोडडैमिट का भी उपयोग कर सकते हैं । यह निम्नलिखित तरीकों की कोशिश करेगा:

  • दस्तावेज़ में खोज की गई एन्कोडिंग: उदाहरण के लिए, XML घोषणा में या (HTML दस्तावेज़ों के लिए) http-equiv META टैग। यदि सुंदर सूप को दस्तावेज़ के भीतर इस तरह के एन्कोडिंग का पता चलता है, तो यह दस्तावेज़ को फिर से शुरू करता है और नए एन्कोडिंग को आज़माता है। एकमात्र अपवाद यह है कि यदि आपने स्पष्ट रूप से एन्कोडिंग निर्दिष्ट किया है, और यह एन्कोडिंग वास्तव में काम करता है: तो यह दस्तावेज़ में किसी भी एन्कोडिंग को अनदेखा करेगा।
  • फ़ाइल के पहले कुछ बाइट्स को देखकर एक एन्कोडिंग सूँघा। यदि इस स्तर पर एन्कोडिंग का पता लगाया जाता है, तो यह UTF- * एन्कोडिंग, EBCDIC, या ASCII में से एक होगा।
  • यदि आपने इसे स्थापित किया है, तो चारडेट लाइब्रेरी द्वारा एक एन्कोडिंग सूँघा जाता है।
  • UTF-8
  • विंडोज़ -1252

1
chardetसंदर्भ के लिए धन्यवाद । अच्छा लगता है, हालांकि थोड़ा धीमा।
क्रेग मैकक्यून

17
@Geomorillo: "एन्कोडिंग मानक" जैसी कोई चीज नहीं है। टेक्स्ट एन्कोडिंग कंप्यूटिंग के रूप में पुराना कुछ है, यह समय और जरूरतों के साथ व्यवस्थित रूप से बढ़ गया, यह योजनाबद्ध नहीं था। "यूनिकोड" इसे ठीक करने का एक प्रयास है।
nosklo

1
और एक बुरा नहीं है, सभी चीजों पर विचार किया जाता है। जो मैं जानना चाहता हूं वह यह है कि मुझे कैसे पता चलेगा कि एक खुली पाठ फ़ाइल को किस एन्कोडिंग के साथ खोला गया था?
होल्डनवेब

2
@dumbledad ने जो कहा, वह यह है कि हर समय इसका सही-सही पता लगाना असंभव है। आप सभी कर सकते हैं एक अनुमान है, लेकिन यह कभी-कभी विफल हो सकता है, यह हर बार काम नहीं करेगा, एन्कोडिंग वास्तव में पता लगाने योग्य नहीं होने के कारण। अनुमान लगाने के लिए, आप एक उपकरण का उपयोग कर सकते हैं जो मैंने उत्तर में सुझाया है
nosklo

1
@ LasseKärkkäinen उस उत्तर के बिंदु को यह दिखाना है कि एन्कोडिंग का पता लगाना असंभव है ; आपके द्वारा प्रदान किया जाने वाला फ़ंक्शन आपके मामले के लिए सही अनुमान लगा सकता है, लेकिन कई मामलों के लिए गलत है।
13

67

एन्कोडिंग को काम करने के लिए एक अन्य विकल्प कामेच्छा का उपयोग करना है (जो फ़ाइल कमांड के पीछे कोड है )। अजगर बाँधने की एक उपलब्धियाँ उपलब्ध हैं।

पायथन बाइंडिंग जो फ़ाइल स्रोत ट्री में रहते हैं, अजगर-जादू (या पायथन 3-मैजिक ) डेबियन पैकेज के रूप में उपलब्ध हैं। यह फ़ाइल के एन्कोडिंग को निर्धारित कर सकता है:

import magic

blob = open('unknown-file', 'rb').read()
m = magic.open(magic.MAGIC_MIME_ENCODING)
m.load()
encoding = m.buffer(blob)  # "utf-8" "us-ascii" etc

पीपीआई पर एक नाम से पहचाना जाने वाला, लेकिन असंगत, अजगर-जादू पाइप पैकेज है जो भी उपयोग करता है libmagic। यह कर कर एन्कोडिंग भी प्राप्त कर सकता है:

import magic

blob = open('unknown-file', 'rb').read()
m = magic.Magic(mime_encoding=True)
encoding = m.from_buffer(blob)

5
libmagicवास्तव में एक व्यवहार्य विकल्प है chardet। और नाम के अलग पैकेज पर बढ़िया जानकारी python-magic! मुझे यकीन है कि यह अस्पष्टता कई लोगों को काटती है
MestreLion

1
fileपाठ फ़ाइलों में मानव भाषा की पहचान करने में विशेष रूप से अच्छा नहीं है। यह विभिन्न कंटेनर प्रारूपों की पहचान करने के लिए उत्कृष्ट है, हालांकि आपको कभी-कभी यह जानना होगा कि इसका क्या मतलब है ("Microsoft Office दस्तावेज़" का अर्थ आउटलुक संदेश, आदि हो सकता है)।
त्रिकाल

फ़ाइल एन्कोडिंग रहस्य को प्रबंधित करने के तरीके की तलाश में मुझे यह पोस्ट मिली। दुर्भाग्य से, उदाहरण के कोड का उपयोग कर, मैं नहीं पिछले प्राप्त कर सकते हैं open(): UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 169799: invalid start byte। फ़ाइल vim के के अनुसार एन्कोडिंग :set fileencodingहै latin1
xtian

यदि मैं वैकल्पिक तर्क का उपयोग करता हूं errors='ignore', तो उदाहरण कोड का आउटपुट कम सहायक है binary
xtian

2
@xtian आपको बाइनरी मोड में खोलना होगा, यानी ओपन ("फ़ाइलनाम.टेक्स्ट", "आरबी")।
एल। कर्णकिनेन

31

कुछ एन्कोडिंग रणनीतियाँ, कृपया स्वाद के लिए असहज हों:

#!/bin/bash
#
tmpfile=$1
echo '-- info about file file ........'
file -i $tmpfile
enca -g $tmpfile
echo 'recoding ........'
#iconv -f iso-8859-2 -t utf-8 back_test.xml > $tmpfile
#enca -x utf-8 $tmpfile
#enca -g $tmpfile
recode CP1250..UTF-8 $tmpfile

आप फ़ाइल को लूप के रूप में खोलकर और पढ़कर एन्कोडिंग की जाँच करना पसंद कर सकते हैं ... लेकिन आपको पहले फ़ाइलों की जाँच करने की आवश्यकता हो सकती है:

encodings = ['utf-8', 'windows-1250', 'windows-1252' ...etc]
            for e in encodings:
                try:
                    fh = codecs.open('file.txt', 'r', encoding=e)
                    fh.readlines()
                    fh.seek(0)
                except UnicodeDecodeError:
                    print('got unicode error with %s , trying different encoding' % e)
                else:
                    print('opening the file with encoding:  %s ' % e)
                    break              

आप इसका उपयोग भी कर सकते हैं io, जैसे io.open(filepath, 'r', encoding='utf-8'), जो अधिक सुविधाजनक है, क्योंकि codecsयह \nपढ़ने और लिखने पर स्वचालित रूप से परिवर्तित नहीं होता है । HERE
Searene

23

यहाँ पढ़ने और अंकित मूल्य पर chardetएन्कोडिंग भविष्यवाणी लेने का एक उदाहरण है , n_linesउस घटना में फ़ाइल से पढ़ना ।

chardetआपको इसकी संभावना (यानी confidence) एन्कोडिंग भविष्यवाणी देता है (यह नहीं देखा कि वे कैसे उस के साथ आते हैं), जो कि इसकी भविष्यवाणी के साथ वापस आ गया है chardet.predict(), ताकि आप किसी भी तरह से काम कर सकें।

def predict_encoding(file_path, n_lines=20):
    '''Predict a file's encoding using chardet'''
    import chardet

    # Open the file as binary data
    with open(file_path, 'rb') as f:
        # Join binary lines for specified number of lines
        rawdata = b''.join([f.readline() for _ in range(n_lines)])

    return chardet.detect(rawdata)['encoding']

अप-वोट प्राप्त करने के बाद इसे देखते हुए और अब देखें कि पहली पंक्ति में बहुत अधिक डेटा होने पर यह समाधान धीमा हो सकता है। कुछ मामलों में डेटा को अलग तरीके से पढ़ना बेहतर होगा।
ryanjdillon

2
मैंने इस फ़ंक्शन को इस तरह से संशोधित किया है: def predict_encoding(file_path, n=20): ... skip ... and then rawdata = b''.join([f.read() for _ in range(n)]) पायथन 3.6 पर इस फ़ंक्शन की कोशिश की गई है, "एस्की", "cp1252", "utf-8", "यूनिकोड" एन्कोडिंग के साथ पूरी तरह से काम किया है। तो यह निश्चित रूप से upvote है।
n158

1
यह विभिन्न स्वरूपों के साथ छोटे डेटासेट को संभालने के लिए बहुत अच्छा है। यह मेरी जड़ dir पर पुनरावर्ती परीक्षण किया और यह एक इलाज की तरह काम किया। धन्यवाद दोस्त।
दत्तनोविस

4
# Function: OpenRead(file)

# A text file can be encoded using:
#   (1) The default operating system code page, Or
#   (2) utf8 with a BOM header
#
#  If a text file is encoded with utf8, and does not have a BOM header,
#  the user can manually add a BOM header to the text file
#  using a text editor such as notepad++, and rerun the python script,
#  otherwise the file is read as a codepage file with the 
#  invalid codepage characters removed

import sys
if int(sys.version[0]) != 3:
    print('Aborted: Python 3.x required')
    sys.exit(1)

def bomType(file):
    """
    returns file encoding string for open() function

    EXAMPLE:
        bom = bomtype(file)
        open(file, encoding=bom, errors='ignore')
    """

    f = open(file, 'rb')
    b = f.read(4)
    f.close()

    if (b[0:3] == b'\xef\xbb\xbf'):
        return "utf8"

    # Python automatically detects endianess if utf-16 bom is present
    # write endianess generally determined by endianess of CPU
    if ((b[0:2] == b'\xfe\xff') or (b[0:2] == b'\xff\xfe')):
        return "utf16"

    if ((b[0:5] == b'\xfe\xff\x00\x00') 
              or (b[0:5] == b'\x00\x00\xff\xfe')):
        return "utf32"

    # If BOM is not provided, then assume its the codepage
    #     used by your operating system
    return "cp1252"
    # For the United States its: cp1252


def OpenRead(file):
    bom = bomType(file)
    return open(file, 'r', encoding=bom, errors='ignore')


#######################
# Testing it
#######################
fout = open("myfile1.txt", "w", encoding="cp1252")
fout.write("* hi there (cp1252)")
fout.close()

fout = open("myfile2.txt", "w", encoding="utf8")
fout.write("\u2022 hi there (utf8)")
fout.close()

# this case is still treated like codepage cp1252
#   (User responsible for making sure that all utf8 files
#   have a BOM header)
fout = open("badboy.txt", "wb")
fout.write(b"hi there.  barf(\x81\x8D\x90\x9D)")
fout.close()

# Read Example file with Bom Detection
fin = OpenRead("myfile1.txt")
L = fin.readline()
print(L)
fin.close()

# Read Example file with Bom Detection
fin = OpenRead("myfile2.txt")
L =fin.readline() 
print(L) #requires QtConsole to view, Cmd.exe is cp1252
fin.close()

# Read CP1252 with a few undefined chars without barfing
fin = OpenRead("badboy.txt")
L =fin.readline() 
print(L)
fin.close()

# Check that bad characters are still in badboy codepage file
fin = open("badboy.txt", "rb")
fin.read(20)
fin.close()

2

आपके प्लेटफ़ॉर्म के आधार पर, मैं सिर्फ लिनक्स शेल fileकमांड का उपयोग करने का विकल्प चुनता हूं । यह मेरे लिए काम करता है क्योंकि मैं इसे एक स्क्रिप्ट में उपयोग कर रहा हूं जो विशेष रूप से हमारे एक लिनक्स मशीन पर चलता है।

जाहिर है कि यह एक आदर्श समाधान या उत्तर नहीं है, लेकिन इसे आपकी आवश्यकताओं के अनुसार संशोधित किया जा सकता है। मेरे मामले में मुझे यह निर्धारित करने की आवश्यकता है कि कोई फ़ाइल UTF-8 है या नहीं।

import subprocess
file_cmd = ['file', 'test.txt']
p = subprocess.Popen(file_cmd, stdout=subprocess.PIPE)
cmd_output = p.stdout.readlines()
# x will begin with the file type output as is observed using 'file' command
x = cmd_output[0].split(": ")[1]
return x.startswith('UTF-8')

एक नई प्रक्रिया की आवश्यकता नहीं है। पायथन कोड पहले से ही एक प्रक्रिया के अंदर चलता है, और एक नई प्रक्रिया को लोड करने के ओवरहेड के बिना उचित सिस्टम फ़ंक्शन को कॉल कर सकता है।
vdboor

2

यह मददगार हो सकता है

from bs4 import UnicodeDammit
with open('automate_data/billboard.csv', 'rb') as file:
   content = file.read()

suggestion = UnicodeDammit(content)
suggestion.original_encoding
#'iso-8859-1'

1

सिद्धांत रूप में, सामान्य रूप से पाठ फ़ाइल की एन्कोडिंग को निर्धारित करना असंभव है। तो नहीं, आपके लिए ऐसा कोई मानक पायथन पुस्तकालय नहीं है।

यदि आपके पास पाठ फ़ाइल (जैसे कि यह XML है) के बारे में अधिक विशिष्ट ज्ञान है, तो पुस्तकालय कार्य हो सकते हैं।


1

यदि आप फ़ाइल की कुछ सामग्री जानते हैं तो आप इसे कई एन्कोडिंग के साथ डिकोड करने का प्रयास कर सकते हैं और देख सकते हैं कि कौन गायब है। सामान्य तौर पर कोई रास्ता नहीं है क्योंकि एक पाठ फ़ाइल एक पाठ फ़ाइल है और वे बेवकूफ हैं;)


1

इस साइट में ascii को पहचानने के लिए python कोड है, boms के साथ एन्कोडिंग, और कोई बम नहीं utf8: https://unicodebook.readthedocs.io/guess_encoding.html । फ़ाइल को बाइट ऐरे (डेटा) में पढ़ें: http://www.codecodex.com/wiki/Read_a_file_into_a_byte_array । यहाँ एक उदाहरण है। मैं ऑक्स में हूं।

#!/usr/bin/python                                                                                                  

import sys

def isUTF8(data):
    try:
        decoded = data.decode('UTF-8')
    except UnicodeDecodeError:
        return False
    else:
        for ch in decoded:
            if 0xD800 <= ord(ch) <= 0xDFFF:
                return False
        return True

def get_bytes_from_file(filename):
    return open(filename, "rb").read()

filename = sys.argv[1]
data = get_bytes_from_file(filename)
result = isUTF8(data)
print(result)


PS /Users/js> ./isutf8.py hi.txt                                                                                     
True

किसी समाधान का लिंक स्वागत योग्य है, लेकिन कृपया सुनिश्चित करें कि आपका उत्तर इसके बिना उपयोगी है: लिंक के चारों ओर संदर्भ जोड़ें ताकि आपके साथी उपयोगकर्ताओं को कुछ पता चले कि यह क्या है और यह क्यों है, तो आप जिस पृष्ठ का सबसे प्रासंगिक हिस्सा उद्धृत करते हैं ' लक्ष्य पृष्ठ अनुपलब्ध होने की स्थिति में पुनः लिंक करना। ऐसे लिंक जो किसी लिंक से बहुत कम हैं उन्हें हटाया जा सकता है।
डबल बीप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.