2013-11-25 17 views
5

Tôi đang viết trình thu thập dữ liệu web để tìm nạp một số tệp web Trung Quốc. Các tệp được tìm nạp được mã hóa bằng utf-8. Và tôi cần phải đọc những tệp đó để thực hiện một số phân tích cú pháp, chẳng hạn như trích xuất các URL và Ký tự Trung Quốc. Nhưng tôi thấy rằng khi tôi đọc các tập tin vào một std :: string biến và đầu ra nó vào giao diện điều khiển, các ký tự Trung Quốc đã trở thành ký tự rác. Tôi áp dụng tăng :: regex vào biến std :: string và có thể trích xuất tất cả các URL nhưng ký tự Trung Quốc.Cách đọc tệp được mã hóa UTF-8 có chứa các ký tự tiếng Trung và xuất chúng chính xác trên bảng điều khiển?

Tôi có thể giải quyết những vấn đề đó như thế nào?

P.S. Các tệp CPP của tôi được mã hóa như ANSI theo mặc định, hệ điều hành là Win8 bằng tiếng Trung Quốc;

+0

Có vẻ như bạn cần thay đổi 'trang mã' từ UTF-8 thành bất kỳ trang mã nào mà bảng điều khiển của bạn sử dụng cho ký tự tiếng Trung. Gọi MultiByteToWideChar để thay đổi từ UTF-8 sang Unicode, theo sau là WideCharToMultiByte để thay đổi từ Unicode sang trang mã cục bộ của bạn. – john

+0

Hầu hết có thể là lỗi của bàn điều khiển. Hãy thử '>' 'ing vào một tập tin. Nếu nó hóa ra là hợp lệ UTF-8 với các ký tự Trung Quốc, thì chương trình của bạn hoạt động tốt và đây là một câu hỏi của Windows. (Tất nhiên, bạn vẫn có thể cần phải thay đổi chương trình của bạn để làm việc xung quanh Windows, nhưng bạn sẽ biết ai là người có lỗi.) – aib

+0

@aib Có, khi tôi chuyển hướng biến chuỗi std :: thành một tệp khác, nội dung vẫn hợp lệ UTF-8 với các ký tự Chiese. Trang mã của giao diện điều khiển của tôi là "936 (ANSI/OEM - 简体 中文 GBK)" '. –

Trả lời

7

Mã này có thể giúp (được biên dịch với VC++ 2010). Tôi đã thử nghiệm nó với một tập tin UTF-8 có chứa các ký tự không phải latin và nó có vẻ làm việc, nhưng tôi không biết nếu nó sẽ làm việc tốt với các ký tự Trung Quốc. Kiểm tra các liên kết sau để biết thêm thông tin: _setmodecodecvt_utf8.

#include <iostream> 
#include <fstream> 
#include <string> 
#include <locale> 
#include <codecvt> 
#include <fcntl.h> 
#include <io.h> 

using namespace std; // Sorry for this! 

void read_all_lines(const wchar_t *filename) 
{ 
    wifstream wifs; 
    wstring txtline; 
    int c = 0; 

    wifs.open(filename); 
    if(!wifs.is_open()) 
    { 
     wcerr << L"Unable to open file" << endl; 
     return; 
    } 
    // We are going to read an UTF-8 file 
    wifs.imbue(locale(wifs.getloc(), new codecvt_utf8<wchar_t, 0x10ffff, consume_header>())); 
    while(getline(wifs, txtline)) 
     wcout << ++c << L'\t' << txtline << L'\n'; 
    wcout << endl; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    // Console output will be UTF-16 characters 
    _setmode(_fileno(stdout), _O_U16TEXT); 
    if(argc < 2) 
    { 
     wcerr << L"Filename expected!" << endl; 
     return 1; 
    } 
    read_all_lines(argv[1]); 
    return 0; 
} 

Nếu ký tự Trung Quốc không giống như mong đợi, hãy đảm bảo bảng điều khiển đang sử dụng phông chữ hỗ trợ UTF-16 (ví dụ: không sử dụng phông bitmap).

+1

Giải pháp của bạn có hoạt động trên nền tảng khác hoặc chỉ VC trong Windows? –

1

Nói chung, sử dụng w biến thể, (wstring, wfstream, wcout), thiết lập miền địa phương của bạn để phù hợp với yêu cầu, treo một L trên mặt trước của xâu. locale::global(locale("")) thiết lập để phù hợp với môi trường mặc định, sau đó trên mỗi luồng không chạy theo mặc định, ví dụ: wcout.imbue(locale("Chinese_China.936"))might be Microsoft's name cho cài đặt ngôn ngữ của thiết bị đầu cuối của bạn. Điều này luôn đủ để làm những gì tôi muốn, hy vọng nó hoạt động tốt cho bạn.

#include <iostream> 
#include <locale> 
using namespace std; 
int main() { 
    locale::global(locale("")); 
    wstring word; 
    while (wcin >>word) 
    wcout<<word<<'\n'; 
    wcout<<L"好運n"; 
} 
0

nếu bạn cần hiển thị ký tự chính xác, bạn có thể sử dụng libiconv từ GNU. nếu bạn chỉ cần xử lý url, std :: string hoạt động tốt. vấn đề là trang mã của cửa sổ giao diện điều khiển, chứ không phải chính chuỗi đó. sử dụng ngôn ngữ phụ thuộc vào việc triển khai os và stdC++ lib, vì vậy tôi không khuyến khích sử dụng.

MultiByteToWideChar của cửa sổ có thể hữu ích, nhưng bạn cần phải kiểm tra thông số kỹ thuật của MS về cách các chức năng thực hiện chuyển đổi trên chuỗi.

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