Standardowo QT przechowuje w QStringach znaki kodowane z użyciem UTF-16 co pozwala na użycie praktycznie dowolnego znaku bez żadnych problemów. Niestety często napotykamy pliki, które zawierają dane tekstowe zapisane z pomocą innych kodowań.
Wygodne przetwarzanie danych z użyciem QT jest możliwe dopiero wtedy kiedy przetworzymy tekst zawarty w pliku na UTF16. Żeby rozpocząć ten proces musimy najpierw wczytać dane do tablicy znaków QByteArray a dopiero potem wykorzystać tą tablicę do odbróbki zwartych w niej danych.
void openFile()
QString fileName = QFileDialog::getOpenFileName(this, "Otwieranie");
QFile file(fileName);
if(file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return;
}
numberOfLinesInFile = 0;
contentOfFileQByteArray = 0;
while(!file.atEnd()) {
QByteArray chunk = file.readLine();
contentOfFileQByteArray += chunk;
numberOfLinesInFile++;
}
W ten sposoób otrzymujemy tablicę QByteArray wypełnioną tekstem z pliku i mamy informacje o ilości linii.
QTextCodec jest klasą, która wymusza użycie części bibliotem z QT5 - w pliku projektu należy dodać QT += core5compat żeby móc z niej skorzystać
Klasa ta umożliwia stworzenie subklasy, która pozwoli zaimplementować kodowanie, którego nie dodali twórcy QT. Standardowo dostępne są kodowania, które często się wykorzystuje i mają oznaczenia:
Konwersji dokonujemy w następujący sposób (zmiana z CP1250 na UTF-8):
void changeEncoding() {
QString sourceEncoding = "CP1250";
QTextCodec *codec = QTextCodec::codecForName(sourceEncoding.toUtf8());
utf8QString = codec->toUnicode(contentOfFileQByteArray);
}
W QString utf8QString otrzymujemy tekst przetworzony z kodowaniem UTF-8.
Dodanie możliwości przetwarzania nietypowego kodowania wymaga stworzenie subklasy dla QTextCodec i zaimplementowania w niej poniższych funkcji:
Poniżej przykładowy nowy konwerter w postaci subklasy dla QTextCodec
: public QTextCodec {
public:
mzCodec();
~mzCodec();
QByteArray name() const;
QList<QByteArray> aliases() const;
int mibEnum() const;
QByteArray convertFromUnicode(const QChar *input, int number, QTextCodec::ConverterState *state) const;
QString convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state) const;
};
mzCodec::mzCodec() {
}
mzCodec::~mzCodec() {
}
QByteArray mzCodec::name() const {
QByteArray name("mz");
return name;
}
QList<QByteArray> mzCodec::aliases() const {
QList<QByteArray> aliasy;
aliasy.append("mz");
return aliasy;
}
int mzCodec::mibEnum() const {
return 9998;
}
QByteArray mzCodec::convertFromUnicode(const QChar *input, int number, QTextCodec::ConverterState *state) const {
return QByteArray("a");
}
QString mzCodec::convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state) const {
return QString("b");
To czy nasza klasa została podpięta do QTextCodec i jest dostępna jako konwerter można sprawdzić za pomocą:
QTextCodec* codec = QTextCodec::codecForName("mz");
if (codec)
{
qDebug() << "found ";
qDebug() << codec->name() << '\n';
}
Istotnym jest by wcześniej została utworzona instancja naszego konwertera, ponieważ wowołanie konstruktora powoduje podpięcie konwertera do listy dostępnych w QTextCodec.