পাঠ্যের এনকোডিং কীভাবে নির্ধারণ করবেন?


219

আমি এমন কিছু পাঠ্য পেয়েছি যা এনকোড করা আছে তবে আমি জানি না কী চরসেটটি ব্যবহৃত হয়েছিল। পাইথন ব্যবহার করে কোনও পাঠ্য ফাইলের এনকোডিং নির্ধারণ করার কোনও উপায় আছে কি? আমি কীভাবে একটি টেক্সট ফাইলের এনকোডিং / কোডপেজ সি # এর সাথে সনাক্ত করতে পারি

উত্তর:


225

সব সময় এনকোডিংটি সঠিকভাবে সনাক্ত করা অসম্ভব

(চার্ডেট এফএকিউ থেকে :)

তবে কিছু এনকোডিংগুলি নির্দিষ্ট ভাষার জন্য অনুকূলিত হয় এবং ভাষা এলোমেলো নয়। কিছু চরিত্রের ক্রম সমস্ত সময় পপ আপ হয়, অন্য সিকোয়েন্সগুলি কোনও অর্থ দেয় না। ইংরেজিতে সাবলীল একজন ব্যক্তি যিনি একটি সংবাদপত্র খোলেন এবং "txzqJv 2! Dasd0a QqdKjvz" তাত্ক্ষণিকভাবে স্বীকৃতি পাবেন যে এটি ইংরেজি নয় (যদিও এটি পুরোপুরি ইংরেজি অক্ষর দ্বারা রচিত)। প্রচুর "সাধারণ" পাঠ্য অধ্যয়ন করে একটি কম্পিউটার অ্যালগরিদম এই ধরণের সাবলীল অনুকরণ করতে পারে এবং কোনও পাঠ্যের ভাষা সম্পর্কে একটি শিক্ষিত অনুমান করতে পারে।

এখানে চারডেট লাইব্রেরি রয়েছে যা অধ্যয়নটি এনকোডিং সনাক্ত করার চেষ্টা করার জন্য ব্যবহার করে। চারডেট মোজিলায় স্বয়ং-সনাক্তকরণ কোডের একটি বন্দর।

আপনি ইউনিকোডড্যামিটও ব্যবহার করতে পারেন । এটি নিম্নলিখিত পদ্ধতিগুলি চেষ্টা করবে:

  • দস্তাবেজটিতেই একটি এনকোডিং সন্ধান করা হয়েছে: উদাহরণস্বরূপ, কোনও এক্সএমএল ঘোষণায় বা (এইচটিএমএল নথিগুলির জন্য) একটি HTTP সমতুল্য মেটা ট্যাগ। যদি বিউটিফুল স্যুপ নথির মধ্যে এই জাতীয় এনকোডিংটি খুঁজে পায় তবে এটি প্রথম থেকেই দস্তাবেজটিকে বিশ্লেষণ করে নতুন এনকোডিংয়ের চেষ্টা করে। একমাত্র ব্যতিক্রম হ'ল যদি আপনি স্পষ্টভাবে একটি এনকোডিং নির্দিষ্ট করে থাকেন এবং সেই এনকোডিংটি আসলে কাজ করে: তবে এটি নথিতে পাওয়া কোনও এনকোডিংকে উপেক্ষা করবে।
  • ফাইলের প্রথম কয়েকটি বাইট দেখে একটি এনকোডিং স্নিগ্ধ। যদি এই পর্যায়ে কোনও এনকোডিং সনাক্ত করা হয় তবে এটি ইউটিএফ- * এনকোডিংস, ইবিসিডিআইসি বা এএসসিআইআই এর মধ্যে একটি হবে।
  • চার্ডেট লাইব্রেরি দ্বারা স্নিগ্ধ একটি এনকোডিং , যদি আপনি এটি ইনস্টল করেন।
  • হল UTF-8
  • উইন্ডোজ-1252

1
chardetরেফারেন্সের জন্য ধন্যবাদ । কিছুটা ধীর হলেও ভাল লাগছে।
ক্রেগ ম্যাককুইন

17
@ জিওমরিলো: "এনকোডিং স্ট্যান্ডার্ড" এর মতো কোনও জিনিস নেই। পাঠ্য এনকোডিং কম্পিউটিংয়ের মতো পুরানো কিছু, এটি সময় এবং প্রয়োজনের সাথে জৈবিকভাবে বৃদ্ধি পায়, এটি পরিকল্পনা করা হয়নি। "ইউনিকোড" এটি ঠিক করার একটি প্রচেষ্টা।
nosklo

1
এবং কোনও খারাপ নয়, সমস্ত বিষয় বিবেচনা করা হয়। আমি যা জানতে চাই তা হল, কীভাবে খোলা পাঠ্য ফাইলটি এনকোডিং দিয়ে খোলা হয়েছিল তা আমি কীভাবে জানতে পারি?
হোল্ডেনওয়েব

2
@ ডাম্বলড্যাড যা আমি বলেছিলাম তা হ'ল এটি সর্বদা সঠিকভাবে সনাক্ত করা অসম্ভব। আপনি যা করতে পারেন তা অনুমান, তবে এটি কখনও কখনও ব্যর্থ হতে পারে, এনকোডিংগুলি সত্যিই সনাক্তযোগ্য না হওয়ার কারণে এটি প্রতিবার কাজ করবে না। অনুমান করতে, আপনি উত্তরে আমি প্রস্তাবিত একটি সরঞ্জাম ব্যবহার করতে পারেন
nosklo

1
@ লাসেকের্ক্কিনে এই উত্তরটির মূল বিষয়টি দেখানো হচ্ছে যে কোর্টলি এনকোডিং সনাক্তকরণ অসম্ভব ; আপনার প্রদত্ত ফাংশনটি আপনার ক্ষেত্রে সঠিক অনুমান করতে পারে তবে অনেক ক্ষেত্রে এটি ভুল।
nosklo

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পাঠ্য ফাইলগুলিতে মানব ভাষা সনাক্তকরণে বিশেষ ভাল নয়। এটি বিভিন্ন ধারক বিন্যাস শনাক্ত করার জন্য দুর্দান্ত, যদিও আপনাকে মাঝে মাঝে এটির অর্থ কী তা জানতে হবে ("মাইক্রোসফ্ট অফিস ডকুমেন্ট" এর অর্থ একটি আউটলুক বার্তা ইত্যাদি হতে পারে)।
ট্রিপলি

ফাইল এনকোডিং রহস্য পরিচালনা করার জন্য একটি উপায় সন্ধান করছি আমি এই পোস্টটি পেয়েছি। দুর্ভাগ্যবশত, উদাহরণস্বরূপ কোড ব্যবহার, আমি গত পেতে পারেন open(): UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 169799: invalid start byte। ফাইল তেজ অনুযায়ী এনকোডিং :set fileencodingহয় latin1
xtian

যদি আমি alচ্ছিক যুক্তি ব্যবহার করি errors='ignore', উদাহরণ কোডটির আউটপুট কম সহায়ক binary
xtian

2
@ xtian আপনাকে বাইনারি মোডে খুলতে হবে, অর্থাত খোলা ("filename.txt", "আরবি")।
এল কর্ক্কিনেন

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এখানে আরও
সেরারিন

23

এখানে chardetএনকোডিংয়ের পূর্বাভাসটি পড়ার এবং গ্রহণের মূল্য গ্রহণের উদাহরণ রয়েছে n_lines, ফাইলটি বড় হওয়াতে এটি পড়া ।

chardetconfidenceএটির একটি এনকোডিং পূর্বাভাস (যেমন ) এর সম্ভাবনাও দেয় (যেমনটি তারা কীভাবে সামনে আসে তা দেখে না) যা এর পূর্বাভাস দিয়ে ফিরে আসে 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']

একটি আপ-ভোট পাওয়ার পরে এটি দেখে এবং এখন দেখুন যে প্রথম লাইনে প্রচুর ডেটা থাকলে এই সমাধানটি ধীর হয়ে যেতে পারে। কিছু ক্ষেত্রে তথ্য আলাদাভাবে পড়া ভাল to
ryanjdillon

2
আমি এই ফাংশনটি এইভাবে সংশোধন করেছি: def predict_encoding(file_path, n=20): ... skip ... and then rawdata = b''.join([f.read() for _ in range(n)]) পাইথন ৩.6 এ এই ফাংশনটি চেষ্টা করে দেখেছি, "এসকিআই", "সিপি 1252", "ইউটিএফ -8", "ইউনিকোড" এনকোডিংগুলির সাথে পুরোপুরি কাজ করেছেন। সুতরাং এটি অবশ্যই upvote।
n158

1
এটি বিভিন্ন ফরমেটের সাথে ছোট ডেটাসেটগুলি পরিচালনা করার জন্য খুব ভাল। এটি আমার রুট দির উপর পুনরাবৃত্তভাবে পরীক্ষা করা হয়েছে এবং এটি ট্রিটের মতো কাজ করেছে। ধন্যবাদ, বন্ধু.
দাতানোভিস

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কমান্ডটি ব্যবহার করতে পছন্দ করি । এটি আমার পক্ষে কাজ করে যেহেতু আমি এটি কোনও স্ক্রিপ্টে ব্যবহার করছি যা একচেটিয়াভাবে আমাদের লিনাক্স মেশিনগুলির মধ্যে চলে runs

স্পষ্টতই এটি আদর্শ সমাধান বা উত্তর নয়, তবে এটি আপনার প্রয়োজন অনুসারে পরিবর্তন করা যেতে পারে। আমার ক্ষেত্রে আমাকে কেবল ফাইলটি ইউটিএফ -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')

একটি নতুন প্রক্রিয়া forking প্রয়োজন হয় না। পাইথন কোডটি ইতিমধ্যে একটি প্রক্রিয়াটির অভ্যন্তরে চলে এবং কোনও নতুন প্রক্রিয়া লোড করার ওভারহেড ছাড়াই সঠিক সিস্টেমটিকে নিজে কল করতে পারে।
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

নীতিগতভাবে, সাধারণ ক্ষেত্রে কোনও পাঠ্য ফাইলের এনকোডিং নির্ধারণ করা অসম্ভব। সুতরাং না, এটি করার জন্য কোনও পাইথন লাইব্রেরি নেই।

আপনার যদি পাঠ্য ফাইলটি সম্পর্কে আরও নির্দিষ্ট জ্ঞান থাকে (উদাহরণস্বরূপ এটি এটি এক্সএমএল), গ্রন্থাগারের কার্যকারিতা থাকতে পারে।


1

আপনি যদি ফাইলটির কিছু সামগ্রী জানেন তবে আপনি এটি বেশ কয়েকটি এনকোডিং দিয়ে ডিকোড করার চেষ্টা করতে পারেন এবং এটি অনুপস্থিত রয়েছে তা দেখতে পারেন। সাধারণত কোনও উপায় নেই যেহেতু একটি পাঠ্য ফাইল একটি পাঠ্য ফাইল এবং সেগুলি বোকা;)


1

এই সাইটে অ্যাসিআইকে স্বীকৃতি দেওয়ার জন্য, বোমগুলির সাথে এনকোডিং করার জন্য এবং অ বোফ নম্বরের জন্য পাইথন কোড রয়েছে: 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

একটি সমাধানের একটি লিঙ্ক স্বাগত, তবে দয়া করে আপনার উত্তরটি কার্যকর না হওয়া নিশ্চিত করুন: লিঙ্কটির চারপাশে প্রসঙ্গটি যুক্ত করুন যাতে আপনার সহ ব্যবহারকারীদের কিছু ধারণা থাকতে পারে এটি কী এবং কেন সেখানে রয়েছে, তবে আপনি পৃষ্ঠার সর্বাধিক প্রাসঙ্গিক অংশটি উদ্ধৃত করুন লক্ষ্য পৃষ্ঠাটি অনুপলব্ধ ক্ষেত্রে লিঙ্কটি পুনরায় সংযুক্ত করুন। লিঙ্কের চেয়ে সামান্য বেশি উত্তরগুলি মুছতে পারে।
ডাবল-বীপ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.