UTF-8 zeichenweise einlesen, verarbeiten und schreiben



  • Hallo,

    ich würde gerne eine UTF-8-Datei zeichenweise einlesen und
    bestimmte Zeichen herausfiltern und in eine andere Datei schreiben.
    Leider arbeiten die Streams der STL mit char.
    Gibt es eine Möglichkeit (fertige Implementierungen) irgendetwas um diese
    Streams zu wrappen um ein komplettes Zeichen auszulesen?
    Also ich vermute mal dann müsste nach lesen eines Zeichens das Zeichen
    als UTF-32(?) im Speicher liegen, da ja ein Zeichen eine konstante Länge haben
    muss.

    Also ich dachte da an etwas wie:

    utf8_istream u_istream(my_istream);
    utf8_ostream u_ostream(my_ostream);
    while(u_istream.good()){
        utf32_char c = stream.get();
        if(u_istream.good() && c!='x'){
            u_ostream.put(c);
        }
    }
    

    Gibt es so etwas in der Art oder wie würdet ihr vorgehen?

    Gruß,
    Mark



  • Mit Qt müsste das möglich sein.



  • Manni66 schrieb:

    Mit Qt müsste das möglich sein.

    Ich bin kein Befürworter von QT 🙄
    Gibt es Alternativen?





  • Für derartige Konvertierungen ist die Facette codecvt zuständig. Wenn eine UTF8-codierte Datei gelesen werden soll, so benötigt man die entsprechende Facette und hängt sie an den Stream - bzw. der gibt sie an den darunterliegenden Streambuf weiter.
    boost hat so eine Facette intern vorliegen (utf8_codecvt_facet). Folgendes sollte im Prinzip funktionieren:

    #define BOOST_UTF8_BEGIN_NAMESPACE \
         namespace my { 
    #define BOOST_UTF8_END_NAMESPACE }
    #define BOOST_UTF8_DECL
    #include <boost/detail/utf8_codecvt_facet.hpp>
    #include <libs/detail/utf8_codecvt_facet.cpp>
    
    #include <fstream>
    #include <iostream>
    
    int main()
    {
        using namespace std;
        wifstream file( "winput.txt" ); // Datei mit UTF8 codierten Zeichen
        file.imbue( locale( file.getloc(), new my::utf8_codecvt_facet() ) );
        // -- ab hier die bereits konvertierten Zeichen (Typ wchar_t) aus dem Stream 'file' lesen
    
        return 0;
    }
    

    Gruß
    Werner



  • Danke Werner, danke theta!

    Ich hab es erst mit der Library, die theta gepostet hat, versucht. Klappt.

    Aber der zweite Ansatz ist schon ziemlich elegant 🙂

    Allerdings krieg ich den nicht zum Laufen

    #include <iostream>
    #include <boost/program_options/detail/utf8_codecvt_facet.hpp>
    #include <fstream>
    
    int main(int argc, char** arg){
            std::wifstream ifs("/Users/Mark/test.txt");
            ifs.imbue( std::locale( ifs.getloc(), new boost::program_options::detail::utf8_codecvt_facet() ) );
            wchar_t c;
            while(ifs >> c){
                    std::cout << (char)c;
            }
            std::cout << std::endl;
    }
    
    /*
    int main(int argc, char** arg){
            std::ifstream ifs("/Users/Mark/test.txt");
            char c;
            while(ifs >> c){
                    std::cout << c;
            }
            std::cout << std::endl;
    }*/
    

    Das untere (auskommentierte) Code-Fragement funktioniert einwandfrei.
    In meiner Datei steht einfach nur "text" drin.

    Das obere Fragment funktionert, solange ich den imbue-Aufruf rausnehme.
    Ansonsten fliegt:

    what(): std::bad_cast
    Abort trap

    In meinem komplexeren Programm war es ein Segmentation fault.
    Also evtl. undefiniertes Verhalten(?).

    Hat jemand eine Idee, was hier falsch läuft?



  • Ich habe noch Konvertierungsfunktionen von und nach UTF-32. Brauchst du die?
    (std::string (was ja nichts anderes als std::basic_string<char> ist) nach std::basic_string<char32_t> und zurück nach UTF-8)



  • wxSkip schrieb:

    Ich habe noch Konvertierungsfunktionen von und nach UTF-32. Brauchst du die?
    (std::string (was ja nichts anderes als std::basic_string<char> ist) nach std::basic_string<char32_t> und zurück nach UTF-8)

    Ich danke dir, aber eigentlich wollte ich auf streams arbeiten.



  • SFML hat auch ein paar Funktionen und Klassen zur Unicode-Behandlung. Ich hab bisher nicht gross mit diesem Teil gearbeitet, aber vielleicht bietet er ja, was du brauchst. Generell ist SFML recht sauber und anfängerfreundlich programmiert.



  • Nexus schrieb:

    SFML hat auch ein paar Funktionen und Klassen zur Unicode-Behandlung. Ich hab bisher nicht gross mit diesem Teil gearbeitet, aber vielleicht bietet er ja, was du brauchst. Generell ist SFML recht sauber und anfängerfreundlich programmiert.

    THX! Werd ich mir mal angucken...



  • UTF-8 schrieb:

    ... Ansonsten fliegt:

    what(): std::bad_cast
    Abort trap

    In meinem komplexeren Programm war es ein Segmentation fault.
    Also evtl. undefiniertes Verhalten(?).

    Hat jemand eine Idee, was hier falsch läuft?

    Ich habe das Programm genau so ausprobiert, es funktioniert tadellos, Ich benutze boost-1.45 und MSVC8.0. Versuch's mit Debuggen und schaue mal, ob es bereits im imbue passiert oder erst später.

    Gruß
    Werner


Anmelden zum Antworten