Verschiedene Tokenisierungsmöglichkeiten

Für den Kurs habe ich einmal fünf verschiedene Methoden für eine Texttokenisierung zusammengestellt. Eine Textzeile kann dann tokenisiert werden anhand von Leerzeichen. Das Ergebnis wird (call-by-reference) an einen Word-Vector übergeben. Später kann dieser Wort- Vector die darin enthaltenen Wörter dementsprechend von Punktuierungszeichen bereinigen.

Hinweis: Es wird in den Klassen/ abgeleiteten Klasse von Tokenizer mit Templates gearbeitet. Die Klassen sind somit string bzw. wide-string fähig, bzw. alles was basic_string ähnlich ist, sollte damit funktionieren!

Basisklasse: Tokenizer.hpp

Die Basisklasse enthält u.a. die Methode rm_punct_word() welche den Wort-Vector bereinigt.

BOOSTTokenizer

template<typename T>
class BOOSTTokenizer: public Tokenizer<T> {
public:
 void tokenize(const T &line);
};

Der Boost-Tokenizer benutzt für das Aufsplitten einer Zeile die split()-Methode aus Boost. Konkret wird die Zeile übergeben, aus dieser Zeile enthält man dann einen neuen Vektor, den man an den Wort-Vector hinzufügen muss.

OwnTokenizer

template<typename T>
class OwnTokenizer: public Tokenizer<T> {
public:
 void tokenize(const T &line);
};

Die OwnTokenizer-Klasse implementiert eine eigene Tokenisierungsfunktion, die die Zeile buchstabenweise durchgeht und somit nur "gültige" Buchstaben im Wort zulässt. Desweiteren wird ein spezialisiertes Template für wide-strings verwendet, da wint_t für das Durchgehen bzw. die iswspace-Methode dann verwendet werden muss.

StringStreamTokenizer

template<typename T>
class StringStreamTokenizer: public Tokenizer<T> {
public:
 void tokenize(const T &line);
};

Die StringStreamTokenizer-Klasse verwendet für das Aufsplitten einen gewöhnlichen std::wstringstream. Per Ausgabeoperator erhält man somit duch leerzeichengetrennte Wörter in einer Zeile. Auch hier wird ein spezialisiertes Template für wide-string verwendet, weil dabei zwingend ein wide-stringstream benutzt werden muss.

StringTokenizer

template<typename T>
class StringTokenizer: public Tokenizer<T> {
public:
 void tokenize(const T &line);
};

Die StringTokenizer-Klasse verwendet als spezialisiertes Template wchar_t-Pointer und die wcstok()-Methode (Gegenstück zu strtok für "normale" Strings) um Wörter anhand eines Delimiters (hier das Leerzeichen) aus der Zeile zu bekommen.

SubStringTokenizer

template<typename T>
class SubStringTokenizer: public Tokenizer<T> {
public:
 void tokenize(const T &line);
};

Die SubStringTokenizer-Klasse holt sich die Wörter aus einer Zeile mittels substring()-Methode bzw. anhand der damit verbundenen Berechnungen/ Suchen innerhalb der Zeile.

Benutzung

Die verschiedenen Tokenizer-Klassen können relativ einfach in ein Programm integriert werden. Neben dem Einbinden der Header:

#include "StringTokenizer.hpp"
#include "BOOSTTokenizer.hpp"
#include "OwnTokenizer.hpp"
#include "StringStreamTokenizer.hpp"
#include "SubStringTokenizer.hpp"

Jetzt muss eine Tokenizermethode gewählt werden. Da das ganze mit Templates implementiert wurde, gibt man den dementsprechenden Datentyp an, zum Beispiel string, wide-string etc.:

SubStringTokenizer<std::wstring > tok;

Als Strategie für das Tokenisieren von großen Textdateien (> 500 MB) findet sich ein Beispiel in der main.cpp. Dabei wird die Datei zeilenweise eingelesen, dann tokenisiert und bereinigt. Nachdem das für die jeweils aktuelle Zeile geschehen ist, geht man den Word-Vector durch und schreibt das Ergebnis in eine Datei. Danach löscht/cleart man den Wort-Vector und dasgleiche wird mit den übrigen Zeilen des Dokumentes gemacht. Das hat den großen Vorteil, dass nicht alle Wörter später im Wort-Vector gespeichert sind. Bei einer Textdatei mit ca. 1GB liegt der RAM-Verbrauch bei ungefähr 10-11 GB (!!!). Dafür ist diese Methode, die Wörter im Speicher zu halten die Schnellste. Wird das Ergebnis gleich in eine Datei geschrieben, so dauert der Tokenisierungsvorgang ca. 7 Mal so lang!

Kompilierung

Die Tokenizer-Klassen verwenden Sprachfeatures aus dem neuen C++11-Standard, deswegen muss der Compilerflag std=c++0x angegeben werden. Für den Boost-Tokenizer muss natürlich Boost installiert sein, ggf. muss es dementsprechend gelinkt werden beim Kompilieren.

Quellen

Alle Quelltexte sind hier verfügbar:

Historie

Lizenz

Die Quelltexte stehen unter der GPL 2 Lizenz.