mọi người cho mình hỏi, khi mình đọc file dạng tiếng việt thế này : ví dụ
file a
trường
sau đó mình đọc file a
để ghi vào file b, thì kết quả thế này:
tr\u01b0\u1eddng
Đây là hiện tượng gì vậy,
Cám ơn mọi người.
mọi người cho mình hỏi, khi mình đọc file dạng tiếng việt thế này : ví dụ
file a
trường
sau đó mình đọc file a
để ghi vào file b, thì kết quả thế này:
tr\u01b0\u1eddng
Đây là hiện tượng gì vậy,
Cám ơn mọi người.
Kí tự ư
mà bạn lưu vào là 1 kí tự unicode. Lookup ngược ra vẫn thấy chữ ư:
mình có test thử thì đúng là vậy, vậy mã hóa “trường” trong file gọi là acsii hay là gì vậy, khoản này mình chưa thật sự rõ, vì trong quá tình xử lý file mình gặp khó trong vấn đề này
Bạn lưu kí tự unicode vào file, kí tự đó cũng có mã số thôi mà
Python 2 không giống như Python 3, khi print ra thay vì hiển thị "trường"
thì hiển thị u"tr\u01b0\u1eddng"
- những kí tự nào trong bảng mã ASCII thì hiển thị rõ ngay, những kí tự khác thì hiển thị mã số.
vậy làm thế nào để mình ghi ra file là “trường” và không phải là “tr\u01b0\u1eddng” , sự khác nhau nó là gì, còn là số thì mình hiểu rồi.
Bạn in ra file rồi đọc lại, rồi in lại ra terminal đúng không? Nếu bạn mở file output bằng text editor thì sẽ thấy chẳng có khác nhau gì cả.
Hoặc nhanh nhất là bạn đổi sang Python 3, Python 2 sắp đến hồi khai tử rồi.
mình xem trên sublimetext thôi, chứ không xem trên terminal, khi lưu thì nó bị như vậy, mình dùng python3
cụ thể là mình đọc ghi file json, không biết có liên gì không?
trên đầu mình có ghi như này:
# -*- coding: utf8 -*-
Bạn đã encode string sang UTF-8 và mở file bằng encoding UTF-8 chưa?
bằng lệnh hay là chỉnh sửa phần mêm đọc file (sublime mình đang dùng) vậy
Xác nhận là do json nhé bạn. Json không lưu được trực tiếp các kí tự unicode mà phải lưu qua mã.
>>> json.dumps({"id":1, "text":"thử cái đã"})
'{"id": 1, "text": "th\\u1eed c\\u00e1i \\u0111\\u00e3"}'
vậy sự khác nhau là 1 cái đã được mã unicode đã được decode và 1 cái chưa được decode hả bạn.
mình có thử search trên mạng, sau khi thêm 2 dòng này thì mình đã làm được:
with open('data_book.json', 'w', encoding='utf-8') as outfile:
for f in data:
tmp = f['id'].split("_")
if(tmp[0] == "BOOK"):
json.dump(f, outfile, ensure_ascii=False)
outfile.write('\n')
thêm
encoding='utf-8'
ensure_ascii=False
lúc thì bạn dùng unicode lúc thì bạn dùng utf-8 mình chưa hiểu lắm
code trên là mình đang ghi vài file (mình cần write)
ngoài ra bạn giải thích cho mình, tại sao khi bạn dùng là unicode, khi bạn lại dùng là utf-8 vậy?
UTF-8 là viết tắt của 8-bit Unicode Transformation Format.
Unicode là…
Thường thì viết kí tự tiếng Việt vào file với encoding UTF-8.
vậy sự khác nhau giữa 2 loại mã utf-8 trên là gì vậy bạn :), mình đọc rồi nhưng chưa biết.
tr\u01b0\u1eddng
và
trường
trường
lưu xuống file vậy là đã có thông qua encoding (utf-8 hoặc utf-16 hoặc ucs-2 hoặc utf-32, v.v…)
tr\u01b0\u1eddng
là lưu ko có encoding. \u01b0
và \u1edd
là Unicode code point, bạn "\u1edd
code point" là ra “LATIN SMALL LETTER O WITH HORN AND GRAVE”
Unicode map mỗi ký tự với 1 số cố định gọi là code point, hiện tại có khoảng hơn 1.1 triệu code point. Các code point này được encode thành n bytes gọi là code value. Mỗi code point được encode thành bao nhiêu byte thì tùy theo encoding gì. Ví dụ:
tuy UCS-2 chỉ lưu được có 65k ký tự nhưng ngoài 65k ký tự này các ký tự khác rất ít khi xài. 65k ký tự đầu tiên này gọi là Basic Multilingual Plane (BMP).
sở dĩ có các encoding này là để tiết kiệm bộ nhớ: lưu trực tiếp code point thì tốn 6 bytes (\uxxxx với x là 1 số hệ 16) hoặc 4 bytes binary (1.1 triệu code points nên xài 32-bit integer), còn lưu nhờ các encoding kia thì tốn ít hơn (1-4 bytes 1 code point)
đừng nhầm lẫn Unicode với các encoding UTF-8 UTF-16 UTF-32 :V Ông nội Windows bị khùng, UCS-2 mà mấy ổng ghi là Unicode nên mới gây nhầm lẫn như vậy. Với người dùng bình thường họ ko biết thì ko sao, MS lừa được họ, còn lập trình viên thì phải biết phân biệt chiêu trò lừa đảo của MS :V :V Unicode ko liên quan gì tới encoding :V
khi lưu:
[ký tự] ----map Unicode----> [code point] ----encode----> [code value] ----write----> [file]
khi đọc:
[file] ----read----> [code value] ----decode----> [code point] ----map Unicode----> [ký tự]
thư viện json
của Python 3 có lẽ vì nó sợ user xài bậy :V lưu file ko có encode utf-8 hoặc encode ucs-2 :V :V nên nó mới mặc đình xài \uxxxx
như vậy, bảo đảm save/load với open(..., 'w')
luôn đúng.
UCS-2 = luôn là 16-bit (Windows)
UTF-8 = 8/16/24/32-bit (thông dụng nhất trên web)
UTF-16 = 16-bit || 32-bit
cám ơn tiền bối, cái gì cũng biết. giờ em mới biết khái niệm ucs-2, có search qua, thì thấy người ta đã bỏ nó rồi. Mà tiền bối viết như trên, em đọc vẫn còn mơ hồ quá.