2012-04-05 46 views
6

Tôi lập trình (chỉ thỉnh thoảng) trong C++ với VisualStudio và MFC. Tôi viết một tập tin với fopen và fprintf. Tệp phải được mã hóa bằng UTF8. Có khả năng nào để làm điều này không? Bất cứ điều gì tôi cố gắng, tập tin là một trong hai byte unicode hoặc ISO-8859-2 (latin2) được mã hóa.Cách ghi tập tin UTF-8 với fprintf trong C++

Glanebridge

+1

Xem những bài đăng khác về Unicode trong C++ http://stackoverflow.com/questions/55641/unicode-in-c – Dave

+0

Bạn có thể thử để xem chủ đề này [nhập liên kết mô tả ở đây] [1] [1]: http://stackoverflow.com/questions/2543346/how-to-write-unicode-hello-world-in-c-on-windows – Jepessen

Trả lời

1

Lý thuyết, bạn chỉ cần đặt ngôn ngữ sử dụng UTF-8 làm mã hóa bên ngoài. Sự hiểu biết của tôi - Tôi không phải là lập trình viên Windows - là Windows has no such locale, vì vậy bạn phải sử dụng phương tiện cụ thể hoặc không standard libraries (liên kết từ nhận xét của Dave).

2

Có, nhưng bạn cần Visual Studio 2005 trở lên. Sau đó, bạn có thể gọi fopen với các thông số:

LPCTSTR strText = "абв"; 
FILE *f = fopen(pszFilePath, "w,ccs=UTF-8"); 
_ftprintf(f, _T("%s"), (LPCTSTR) strText); 

Hãy nhớ đây là phần mở rộng của Microsoft, có thể sẽ không hoạt động với gcc hoặc các trình biên dịch khác.

+0

tôi don Không nghĩ rằng điều này sẽ ảnh hưởng đến dữ liệu được ghi vào tập tin bằng cách sử dụng fprintf. – bames53

+0

Bạn cần sử dụng _ftprintf. Xem các thay đổi trong câu trả lời của tôi. – sashoalm

+0

Hoặc chỉ đơn giản là sử dụng fwprintf. Điều gì đang xảy ra là 'ccs = UTF-8' đặt chế độ _O_U8TEXT trên tệp, do đó việc ghi ký tự rộng vào tệp sẽ khiến UTF-8 xuất ra. Viết các ký tự hẹp với bộ chế độ này sẽ dẫn đến lỗi. – bames53

2

Bạn không cần phải đặt ngôn ngữ của mình hoặc đặt bất kỳ chế độ đặc biệt nào trên tệp nếu bạn chỉ muốn sử dụng fprintf. Bạn chỉ cần sử dụng các chuỗi được mã hóa UTF-8.

#include <cstdio> 
#include <codecvt> 

int main() { 
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert; 
    std::string utf8_string = convert.to_bytes(L"кошка 日本国"); 

    if(FILE *f = fopen("tmp","w")) 
     fprintf(f,"%s\n",utf8_string.c_str()); 
} 

Lưu chương trình như UTF-8 với chữ ký hay UTF-16 (ví dụ: không sử dụng UTF-8 mà không cần chữ ký, nếu không VS sẽ không tạo ra chuỗi đúng nghĩa đen). Tệp được viết bởi chương trình sẽ chứa phiên bản UTF-8 của chuỗi đó. Hoặc bạn có thể làm:

int main() { 
    if(FILE *f = fopen("tmp","w")) 
     fprintf(f,"%s\n","кошка 日本国"); 
} 

Trong trường hợp này bạn phải lưu các tập tin như UTF-8 mà không chữ ký, bởi vì bạn muốn trình biên dịch để suy nghĩ bảng mã nguồn là giống như mã hóa thực hiện ... Đây là một chút của một hack dựa trên trình biên dịch, IMO, hành vi bị hỏng. Bạn có thể làm điều tương tự với bất kỳ API nào khác để viết các ký tự hẹp vào một tệp, nhưng lưu ý rằng không có phương pháp nào trong số này hoạt động để viết UTF-8 lên bàn điều khiển Windows. Vì thời gian chạy C và/hoặc bàn điều khiển bị hỏng một chút, bạn chỉ có thể viết UTF-8 trực tiếp vào bàn điều khiển bằng cách thực hiện SetConsoleOutputCP (65001) và sau đó sử dụng một trong các chức năng khác nhau của puts.

Nếu bạn muốn sử dụng ký tự rộng thay vì ký tự hẹp thì phương pháp dựa trên ngôn ngữ và chế độ cài đặt trên bộ mô tả tệp có thể được phát.

#include <cstdio> 
#include <fcntl.h> 
#include <io.h> 

int main() { 
    if(FILE *f = fopen("tmp","w")) { 
     _setmode(_fileno(f), _O_U8TEXT); 
     fwprintf(f,L"%s\n",L"кошка 日本国"); 
    } 
} 

#include <fstream> 
#include <codecvt> 

int main() { 
    if(auto f = std::wofstream("tmp")) { 
     f.imbue(std::locale(std::locale(), 
       new std::codecvt_utf8_utf16<wchar_t>)); // assumes wchar_t is UTF-16 
     f << L"кошка 日本国\n"; 
    } 
} 
+0

Tính năng này chỉ hoạt động với hỗ trợ C++ 11 trong VC10 +. –

+1

@NicolBolas Ví dụ đầu tiên sử dụng wstring_convert từ C++ 11, nhưng bất kỳ phương pháp nào khác có được mã hóa UTF-8 cũng hoạt động, ví dụ: WideCharToMultiByte. Ví dụ cuối cùng sử dụng một khía cạnh codecvt C++ 11 mà không có sẵn, thay thế pre-C++ 11. Hai ví dụ khác không sử dụng C++ 11. – bames53

Các vấn đề liên quan