2012-06-28 41 views
8

Tôi hiện đang làm việc trên một dự án sở thích (C/C++) được cho là hoạt động trên cả Windows và Linux, với sự hỗ trợ đầy đủ cho Unicode. Đáng buồn thay, Windows và Linux sử dụng mã hóa khác nhau làm cho cuộc sống của chúng ta khó khăn hơn.Unicode đa nền tảng trong C/C++: Mã hóa nào sẽ sử dụng?

Trong mã của tôi, tôi đang cố gắng sử dụng dữ liệu phổ biến nhất có thể, giúp dễ dàng cho cả Windows và Linux. Trong Windows, wchar_t được mã hóa dưới dạng UTF-16 theo mặc định và UCS-4 trong Linux (đúng với tôi nếu tôi sai).

Phần mềm của tôi mở ({_wfopen, UTF-16, Windows}, {fopen, UTF-8, Linux}) và ghi dữ liệu vào tệp trong UTF-8. Cho đến nay tất cả đều có thể thực hiện được. Cho đến khi tôi quyết định sử dụng SQLite.

Giao diện C/C++ của SQLite cho phép các chuỗi được mã hóa một hoặc hai byte (click). Ofcourse này không hoạt động với wchar_t trong Linux, vì wchar_t trong Linux là 4 byte theo mặc định. Do đó, việc viết và đọc từ sqlite yêu cầu chuyển đổi cho Linux.

Hiện tại, mã đang lộn xộn với các ngoại lệ cho Windows/Linux. Tôi đã hy vọng gắn bó với ý tưởng tiêu chuẩn về lưu trữ dữ liệu trong wchar_t:

  • wchar_t trong Windows: Filepaths không có vấn đề, đọc/ghi vào sqlite mà không gặp vấn đề gì. Việc ghi dữ liệu vào một tệp phải được thực hiện bằng UTF-8.
  • wchar_t trong Linux: Ngoại lệ đối với filepaths do mã hóa UTF-8, chuyển đổi trước khi đọc/ghi thành sqlite (wchar_t) và giống với cửa sổ khi ghi dữ liệu vào tệp.

Sau khi đọc (here) Tôi đã thuyết phục rằng tôi nên dính vào wchar_t trong Windows. Nhưng sau khi nhận được tất cả những gì để làm việc, rắc rối bắt đầu với việc chuyển sang Linux.

Hiện tại tôi đang nghĩ đến việc làm lại tất cả để gắn với đơn giản char (UTF-8) vì nó hoạt động với cả Windows và Linux, lưu ý rằng tôi cần phải 'WideCharToMultiByte' mỗi chuỗi trong Windows để đạt được UTF-8. Sử dụng các chuỗi char * đơn giản sẽ làm giảm đáng kể số lượng ngoại lệ cho Linux/Windows.

Bạn có kinh nghiệm với unicode cho nền tảng chéo không? Bất kỳ suy nghĩ về ý tưởng chỉ đơn giản là lưu trữ dữ liệu trong UTF-8 thay vì sử dụng wchar_t?

+0

Mã hóa ký tự 2byte chắc chắn * không * UTF-16.UTF-16 là 2 đến 4 byte, và UTF-8 là 1 - 4 byte. Windows 'wchar_t' không phải là UTF-16, nó là UCS2. Trong thực tế bạn có thể không nhận thấy sự khác biệt bởi vì UCS2 bao gồm BMP nhưng nếu bao giờ người dùng của bạn quyết định rằng họ phải có dữ liệu trong Ogham hoặc rune ... – user268396

+1

Windows DOES sử dụng UTF-16 và DOES sử dụng 'wchar_t' để giữ UTF-16 dữ liệu, và đã làm như vậy kể từ Windows 2000. –

+3

Trên wchar_t hữu ích như thế nào và cho những gì: http://stackoverflow.com/a/11107667/365496 – bames53

Trả lời

6

UTF-8 trên tất cả các nền tảng, với chuyển đổi chỉ trong thời gian sang UTF-16 cho Windows là một chiến thuật chung cho Unicode đa nền tảng.

+0

Tôi muốn điều chỉnh một chút tuyên bố đó và nói: Mã hóa gốc trên tất cả các nền tảng, với chuyển đổi vừa thực hiện đến/từ UTF-8. Chuyển đổi chỉ trong thời gian đó là bắt buộc, bất cứ khi nào chuỗi ký tự rời khỏi ứng dụng (ví dụ: ghi vào tệp, gửi dữ liệu qua ổ cắm mạng, truyền dữ liệu vào thư viện, v.v.). Tất nhiên, tất cả phụ thuộc vào kịch bản cụ thể. – IInspectable

2

Phần mềm của chúng tôi là nền tảng đa năng và chúng tôi cũng gặp phải các sự cố tương tự. Chúng tôi quyết định rằng mục tiêu của chúng tôi là có số lượng chuyển đổi ít nhất có thể. Điều này có nghĩa là chúng tôi sử dụng wchar_t trên Windows và char trên Unix/Mac.

Chúng tôi thực hiện điều này bằng cách hỗ trợ _TLPCTSTR và tương tự trên Unix và bằng cách có các chức năng chung dễ dàng chuyển đổi giữa std::stringstd::wstring. Chúng tôi cũng có chung số std::basic_string<TCHAR> (tstring) mà chúng tôi sử dụng trong hầu hết các trường hợp.

Cho đến nay công trình này khá tốt. Các hàm cơ bản nhất lấy một số tstring hoặc LPCTSTR và những hàm không chuyển đổi thông số của chúng từ tstring. Điều đó có nghĩa rằng hầu hết thời gian chúng tôi không chuyển đổi chuỗi của chúng tôi và vượt qua hầu hết các thông số.

+2

Đây là một giải pháp có thể có, nhưng vẫn còn một chút hacky. Ngoài ra, từ đọc của tôi, tôi đã học được rằng tôi nên tránh sử dụng TCHAR vì nó đã được giới thiệu để hỗ trợ khả năng tương thích ngược với phần mềm cũ hơn bằng cách chuyển sang MBCS thay vì cờ Unicode. – ErikKou

+0

@Fozi, Làm cách nào để hỗ trợ _T trên Ubuntu Linux? Cảm ơn nhiều. – Frank

+0

@ErikKou, giải pháp khả thi của bạn để mô phỏng macro Windows _T trong Unix hoặc Linux là gì? Cảm ơn bạn. – Frank