Hiển thị kí tự tiếng Việt chính xác mà không hiển thị mã Unicode

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.

1 Like

Kí tự ư mà bạn lưu vào là 1 kí tự unicode. Lookup ngược ra vẫn thấy chữ ư:

https://unicodelookup.com/#0x01b0/1

3 Likes

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

1 Like

Bạn lưu kí tự unicode vào file, kí tự đó cũng có mã số thôi mà :confused:

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ố.

3 Likes

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.

1 Like

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.

4 Likes

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 -*-
2 Likes

Bạn đã encode string sang UTF-8 và mở file bằng encoding UTF-8 chưa?

3 Likes

bằng lệnh hay là chỉnh sửa phần mêm đọc file (sublime mình đang dùng) vậy

1 Like

1 Like

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"}'
4 Likes

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.

1 Like

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

1 Like

code trên là mình đang ghi vài file (mình cần write)

2 Likes

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?

1 Like

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.

3 Likes

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

trường
1 Like

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\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ụ:

  • UTF-8 thì các code point được encode thành 1,2,3, hoặc 4 bytes tùy theo giá trị code point đó.
  • UTF-16 thì các code points được encode thành 2 hoặc 4 bytes.
  • UTF-32 thì các code points được encode thành 4 bytes.
  • UCS-2 thì chỉ encode các code points thành đúng 2 bytes, tức là ko lưu trữ được hết 1.1 triêu code points vì 2 bytes chỉ lưu tối đa được 65536 code points mà thôi :V

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.

4 Likes

UCS-2 = luôn là 16-bit :smiley: (Windows)
UTF-8 = 8/16/24/32-bit (thông dụng nhất trên web)
UTF-16 = 16-bit || 32-bit :slight_smile:

4 Likes

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á.

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?