Đọc ký tự từ tệp bằng Python


102

Trong một tệp văn bản, có một chuỗi "Tôi không thích điều này".

Tuy nhiên, khi tôi đọc nó thành một chuỗi, nó sẽ trở thành "I don \ xe2 \ x80 \ x98t like this". Tôi hiểu rằng \ u2018 là đại diện unicode của "'". tôi sử dụng

f1 = open (file1, "r")
text = f1.read()

lệnh để đọc.

Bây giờ, có thể đọc chuỗi theo cách mà khi nó được đọc vào chuỗi, nó là "Tôi không thích điều này", thay vì "Tôi không thích xe2 \ x80 \ x98t như thế này như thế này"?

Chỉnh sửa thứ hai: Tôi đã thấy một số người sử dụng ánh xạ để giải quyết vấn đề này, nhưng thực sự, không có chuyển đổi tích hợp nào thực hiện loại chuyển đổi ANSI sang unicode (và ngược lại) này?


Một số nhận xét: Tôi đã thấy một số người sử dụng ánh xạ để giải quyết vấn đề này, nhưng thực sự, không có chuyển đổi tích hợp nào thực hiện loại chuyển đổi ANSI sang unicode (và ngược lại)? Cảm ơn!
Graviton

Không có, bởi vì có hàng trăm nghìn điểm mã Unicode. Bạn sẽ quyết định cái nào nên được ánh xạ tới những ký tự ASCII nào?
John Millikin 29-08

2
btw, tệp văn bản của bạn bị hỏng! U + 2018 là "ĐÁNH GIÁ DUY NHẤT TRÁI", không phải dấu nháy đơn (phổ biến nhất là U + 0027).

john, nhận xét của bạn là sai, ít nhất là theo nghĩa chung. iconv lib có thể được sử dụng để chuyển các ký tự unicode sang ascii (thậm chí phụ thuộc vào ngôn ngữ. $ python -c 'print u "\ u2018" .encode ("utf-8")' | iconv -t 'ascii // translateit' | xxd 0000000: 270a

vấn đề là bạn cần phải chuyển đổi UNICODE sang ASCII (không phải ngược lại).
hasen

Câu trả lời:


157

Tham khảo: http://docs.python.org/howto/unicode

Do đó, việc đọc Unicode từ một tệp rất đơn giản:

import codecs
with codecs.open('unicode.rst', encoding='utf-8') as f:
    for line in f:
        print repr(line)

Cũng có thể mở tệp ở chế độ cập nhật, cho phép cả đọc và ghi:

with codecs.open('test', encoding='utf-8', mode='w+') as f:
    f.write(u'\u4500 blah blah blah\n')
    f.seek(0)
    print repr(f.readline()[:1])

CHỈNH SỬA : Tôi giả định rằng mục tiêu dự định của bạn chỉ là có thể đọc tệp đúng cách thành một chuỗi bằng Python. Nếu bạn đang cố chuyển đổi sang chuỗi ASCII từ Unicode, thì thực sự không có cách nào trực tiếp để làm như vậy, vì các ký tự Unicode sẽ không nhất thiết tồn tại trong ASCII.

Nếu bạn đang cố gắng chuyển đổi thành chuỗi ASCII, hãy thử một trong các cách sau:

  1. Thay thế các ký tự unicode cụ thể bằng các ký tự tương đương ASCII, nếu bạn chỉ muốn xử lý một số trường hợp đặc biệt, chẳng hạn như ví dụ cụ thể này

  2. Sử dụng unicodedatamô-đun normalize()string.encode()phương pháp để chuyển đổi tốt nhất có thể sang tương đương ASCII gần nhất tiếp theo (Tham khảo https://web.archive.org/web/20090228203858/http://techxplorer.com/2006/07/18/converting- unicode-to-ascii-using-python ):

    >>> teststr
    u'I don\xe2\x80\x98t like this'
    >>> unicodedata.normalize('NFKD', teststr).encode('ascii', 'ignore')
    'I donat like this'
    

3
codecsmô-đun không xử lý đúng chế độ dòng mới phổ quát. io.open()Thay vào đó, hãy sử dụng trên Python 2.7+ (nó là bản dựng sẵn open()trên Python 3).
jfs

15

Có một số điểm cần xem xét.

Ký tự \ u2018 chỉ có thể xuất hiện dưới dạng một đoạn đại diện của chuỗi unicode trong Python, ví dụ: nếu bạn viết:

>>> text = u'‘'
>>> print repr(text)
u'\u2018'

Bây giờ, nếu bạn chỉ muốn in chuỗi unicode một cách thủ công, chỉ cần sử dụng encodephương thức của unicode :

>>> text = u'I don\u2018t like this'
>>> print text.encode('utf-8')
I dont like this

Để đảm bảo rằng mọi dòng từ bất kỳ tệp nào sẽ được đọc dưới dạng unicode, tốt hơn bạn nên sử dụng codecs.openhàm thay vì chỉ open, cho phép bạn chỉ định mã hóa của tệp:

>>> import codecs
>>> f1 = codecs.open(file1, "r", "utf-8")
>>> text = f1.read()
>>> print type(text)
<type 'unicode'>
>>> print text.encode('utf-8')
I dont like this

6

Nhưng nó thực sự là "Tôi không thích điều này" chứ không phải "Tôi không thích điều này". Ký tự u '\ u2018' là một ký tự hoàn toàn khác với "'" (và về mặt hình ảnh, sẽ tương ứng nhiều hơn với' '').

Nếu bạn đang cố gắng chuyển đổi mã unicode được mã hóa thành ASCII thuần túy, bạn có thể giữ ánh xạ dấu câu unicode mà bạn muốn dịch sang ASCII.

punctuation = {
  u'\u2018': "'",
  u'\u2019': "'",
}
for src, dest in punctuation.iteritems():
  text = text.replace(src, dest)

Tuy nhiên, có rất nhiều ký tự dấu câu trong unicode , nhưng tôi cho rằng bạn chỉ có thể tin tưởng vào một vài ký tự trong số chúng thực sự được sử dụng bởi bất kỳ ứng dụng nào đang tạo tài liệu bạn đang đọc.


1
thực ra, nếu bạn tạo ánh xạ dict ánh xạ thứ tự Unicode thành thứ tự Unicode ({0x2018: 0x27, 0x2019: 0x27}), bạn chỉ có thể chuyển toàn bộ dict tới text.translate () để thực hiện tất cả việc thay thế trong một lần.
Thomas Wouters 29/09/08

5

Cũng có thể đọc tệp văn bản được mã hóa bằng phương pháp đọc python 3:

f = open (file.txt, 'r', encoding='utf-8')
text = f.read()
f.close()

Với biến thể này, không cần nhập bất kỳ thư viện bổ sung nào


3

Bỏ qua thực tế rằng tệp văn bản của bạn bị hỏng (U + 2018 là dấu ngoặc kép bên trái, không phải dấu nháy đơn): iconv có thể được sử dụng để chuyển các ký tự unicode sang ascii.

Bạn sẽ phải tìm kiếm "iconvcodec" vì mô-đun này dường như không được hỗ trợ nữa và tôi không thể tìm thấy trang chủ chuẩn cho nó.

>>> import iconvcodec
>>> from locale import setlocale, LC_ALL
>>> setlocale(LC_ALL, '')
>>> u'\u2018'.encode('ascii//translit')
"'"

Ngoài ra, bạn có thể sử dụng iconvtiện ích dòng lệnh để xóa tệp của mình:

$ xxd foo
0000000: e280 980a                                ....
$ iconv -t 'ascii//translit' foo | xxd
0000000: 270a                                     '.

2

Có khả năng bằng cách nào đó bạn có một chuỗi không phải unicode với các ký tự thoát unicode, ví dụ:

>>> print repr(text)
'I don\\u2018t like this'

Điều này thực sự đã xảy ra với tôi một lần trước đây. Bạn có thể sử dụng unicode_escapecodec để giải mã chuỗi thành unicode và sau đó mã hóa nó thành bất kỳ định dạng nào bạn muốn:

>>> uni = text.decode('unicode_escape')
>>> print type(uni)
<type 'unicode'>
>>> print uni.encode('utf-8')
I dont like this

1

Đây là cách Pythons hiển thị cho bạn các chuỗi được mã hóa unicode. Nhưng tôi nghĩ rằng bạn sẽ có thể in chuỗi trên màn hình hoặc ghi nó vào một tệp mới mà không gặp bất kỳ sự cố nào.

>>> test = u"I don\u2018t like this"
>>> test
u'I don\u2018t like this'
>>> print test
I dont like this

1

Trên thực tế, U + 2018 là đại diện Unicode của ký tự đặc biệt '. Nếu muốn, bạn có thể chuyển đổi các phiên bản của ký tự đó thành U + 0027 bằng mã này:

text = text.replace (u"\u2018", "'")

Ngoài ra, bạn đang sử dụng gì để ghi tệp? f1.read()sẽ trả về một chuỗi trông giống như sau:

'I don\xe2\x80\x98t like this'

Nếu nó trả về chuỗi này , thì tệp đang được ghi sai:

'I don\u2018t like this'

Lấy làm tiếc! Như bạn đã nói, nó đang trả về 'I don \ xe2 \ x80 \ x98t như thế này'
Graviton

'I don \ xe2 \ x80 \ x98t like this' mà bạn đang thấy là những gì Python sẽ gọi là str. Có vẻ như đây là mã hóa utf-8 của u'I don’t like this ', là một phiên bản unicode trong Python. Hãy thử gọi .decode ('utf-8') trên cái trước hoặc .encode ('utf-8') trên cái sau.
Logan

@hop: oops, quên ord () trả về thập phân thay vì hex. Cảm ơn bạn đã bắt.
John Millikin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.