2013-11-25 10 views
5

Ich schreibe einen Web-Crawler, um einige chinesische Web-Dateien zu holen. Die abgerufenen Dateien sind in utf-8 codiert. Und ich muss diese Datei lesen, um etwas zu analysieren, wie das Extrahieren der URLs und chinesischen Schriftzeichen. Aber ich fand, dass, wenn ich die Datei in eine std :: string-Variable las und es in die Konsole ausgab, die chinesischen Zeichen zu Müllzeichen wurden. Ich habe den boost :: regex in die Variable std :: string angewendet und kann alle URLs außer chinesischen Zeichen extrahieren.Wie lese ich eine UTF-8-kodierte Datei mit chinesischen Schriftzeichen und gebe sie korrekt auf der Konsole aus?

Wie kann ich diese Probleme lösen?

P.S. Meine CPP-Dateien sind standardmäßig als ANSI codiert, das Betriebssystem ist Win8 in chinesischer Sprache;

+0

Klingt so, als müssten Sie die 'Codepage' von UTF-8 in jede Codepage ändern, die Ihre Konsole für chinesische Zeichen verwendet. Rufen Sie MultiByteToWideChar auf, um von UTF-8 in Unicode zu wechseln, gefolgt von WideCharToMultiByte, um von Unicode zu Ihrer lokalen Codepage zu wechseln. – john

+0

Wahrscheinlich ist die Konsole schuld. Probieren Sie '>' 'in eine Datei aus. Wenn es sich um gültiges UTF-8 mit chinesischen Schriftzeichen handelt, funktioniert Ihr Programm gut und das ist eine Windows-Frage. (Natürlich müssen Sie Ihr Programm möglicherweise noch ändern, um Windows zu verwenden, aber Sie werden wissen, wer die Schuld trägt.) – aib

+0

@aib Ja, wenn ich die Variable std :: string in eine andere Datei umleite, ist der Inhalt immer noch gültig UTF-8 mit Chiese-Zeichen. Die Codepage meiner Konsole ist '" 936 (ANSI/OEM - 简体 中文 GBK) "'. –

Antwort

7

Dieser Code kann helfen (es wurde mit VC++ 2010 kompiliert). Ich habe es mit einer UTF-8-Datei getestet, die nicht-lateinische Zeichen enthält, und es scheint zu funktionieren, aber ich weiß nicht, ob es mit chinesischen Schriftzeichen gut funktioniert. Überprüfen Sie die folgenden Links für weitere Informationen: _setmode und codecvt_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; 
} 

Wenn die chinesischen Schriftzeichen nicht wie erwartet aussehen, stellen Sie sicher, dass die Konsole eine Schriftart verwendet, die UTF-16 (dh. Nicht Bitmap-Fonts verwenden) unterstützt.

+1

Funktionierte Ihre Lösung in einer anderen Plattform oder nur VC unter Windows? –

1

In der Regel verwenden die w Varianten (wstring, wfstream, wcout), stellen Sie Ihre Schauplätze, die Anforderungen zu entsprechen, ein L auf der Vorderseite Stringliterale hängen. locale::global(locale("")) wird so eingerichtet, dass es dem Standard der Umgebung entspricht, und dann bei jedem Stream, der nicht gemäß diesem Standard ausgeführt wird, z. wcout.imbue(locale("Chinese_China.936"))might be Microsoft's name für die Gebietsschemaeinstellungen Ihres Terminals. Das war immer genug, um zu tun, was ich will, hoffe es funktioniert auch gut für dich.

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

Wenn Sie Zeichen korrekt anzeigen müssen, können Sie libiconv von GNU verwenden. Wenn Sie nur URLs verarbeiten müssen, funktioniert std :: string einwandfrei. Das Problem ist die Codepage der Windows-Konsole, nicht die Zeichenfolge selbst. use locale hängt von der Implementierung von os und stdC++ lib ab, weshalb ich die Verwendung nicht ermutige.

Fenster MultiByteToWideChar kann helfen, aber Sie müssen MS-Spezifikationen überprüfen, wie dort Funktionen Konvertierungen an Strings durchführen.