Chỉ vì chuỗi tuyên bố là UTF-8 không có nghĩa là nó là UTF-8. \ xe9
là é
trong ISO-8859-1
(AKA Latin-1) nhưng nó không hợp lệ trong UTF-8; tương tự, \ xf1
là ñ
trong ISO-8859-1 nhưng không hợp lệ trong UTF-8. Điều đó cho thấy rằng chuỗi thực sự được mã hóa theo ISO-8859-1 chứ không phải UTF-8. Bạn có thể khắc phục sự cố này bằng sự kết hợp của force_encoding
để khắc phục sự nhầm lẫn của Ruby về mã hóa hiện tại và mã hóa
để mã hóa lại nó thành UTF-8:
> "Tweets en Ingl\xE9s y en Espa\xF1ol".force_encoding('iso-8859-1').encode('utf-8')
=> "Tweets en Inglés y en Español"
Vì vậy, trước khi gửi chuỗi đó đến cơ sở dữ liệu, bạn muốn:
name = name.force_encoding('iso-8859-1').encode('utf-8')
Thật không may, không có cách nào để phát hiện mã hóa thực của một chuỗi một cách đáng tin cậy. Các mã hóa khác nhau chồng chéo lên nhau và không có cách nào để biết được è
( \ xe8
trong ISO-8859-1) hoặc č
( \ xe8
trong ISO-8859-2) là ký tự phù hợp mà không cần kiểm tra sự tỉnh táo thủ công.