- 1. fb3
- 2. Zip-Archiv öffnen
- 3. Fazit
Vor einiger Zeit habe ich ein fb2-Reader-Projekt veröffentlicht, bei dessen Bearbeitung ich herausfand, dass dieses Format veraltet ist. Daher fing ich an, neue Formate zu beherrschen und entschied mich für fb3, das fb2-Empfängerformat. Im Laufe der Arbeit bin ich auf einige Probleme gestoßen, die nicht vollständig gelöst wurden. Darüber hinaus wurde das Format trotz der Tatsache, dass bereits Bücher in fb3 erscheinen, noch nicht endgültig genehmigt. Obwohl Bücher bereits erscheinen. Daher habe ich mich entschlossen, das Programm in seiner jetzigen Form zu veröffentlichen und über meine Erfolge und Misserfolge zu sprechen. Anschließend plane ich eine neue Version mit Unterstützung des epub-Formats.
fb3
Die fb3-Datei ist ein Zip-Container, der Buchelemente enthält. Daher habe ich den folgenden Algorithmus implementiert. Entpacken Sie alle Dateien in einen temporären Ordner und lesen Sie alle notwendigen Elemente daraus.
if(name.endsWith(".fb3")) { QString s = thisName; QString nameUn = QStandardPaths::standardLocations(QStandardPaths::TempLocation).at(0) + "/dmreader/" + s; if(!openerTextFiles::UnZip(name, nameUn)) // распаковка архива qDebug() << "файл " << name << " не открыт"; else { // извлекаем содержимое openerTextFiles::openFBFile(nameUn + "/fb3/body.xml", &text, &content); // помещаем содержимое в окно textBrowser ui->textBrowser->setText(text); ui->textBrowser->verticalScrollBar()->setValue(0); ui->comboBoxContent->insertItems(0, content); ui->comboBoxContent->setCurrentIndex(-1); this->setWindowTitle(content.first()); } }
Die Beispieldatei enthält:
Der fb3-Ordner enthält grundlegende Informationen, insbesondere zwei wichtige body.xml-Elemente - den Text des Buches und description.xml - die Anmerkungen zum Buch, die den Hauptblöcken der fb2-Datei entsprechen. Der Ordner img enthält die Illustrationen des Buches.
Die body.xml-Struktur nach einigen Änderungen an der fb2-Struktur. Die Änderungen zielen darauf ab, die Funktionalität zu erweitern und die Struktur zu vereinfachen. Tags ol, ul, li hinzugefügt, um Listen zu erstellen. blockquote - Anführungszeichen, em - Textakzente (kursiv), pre - Block aus vorformatiertem Text, identisch mit HTML. Die Tags underline (unterstrichen) und space (sparse) können mit den folgenden Ersetzungen implementiert werden:
<span style=\"text-decoration:underline;\"> <span style=\"letter-spacing:5px;\">
Auch das Notensystem wurde leicht modifiziert, darauf gehe ich nicht näher ein.
Deutlich verändert das System der Illustrationen. Im Text mit Tag
Es gibt Links zu den Nummern der Bilder. Um Bilder anzuzeigen, müssen Sie zunächst die Links zu diesen aus der Datei "/_rels/body.xml.rels" auslesen. Dazu erstelle ich ein Array img_fb3 vom Typ QHash
Das img-Tag wird so verarbeitet
if( sr.name().toString() == "img" ) // расположение рисунков fb3 { if(sr.attributes().count() > 0) { if( sr.attributes().at(0).name().toString() == "src" ) book->append("<p align=\"center\"><img src=\"" + filerels + "/" + img_fb3.take( sr.attributes().at(0).value().toString() ) + "\" alt=\"рисунок\"" + "/></p>"); else qDebug() << "img src ошибка"; } break; }
img_fb3 wird so gefüllt
if(sr.name().toString() == "fb3-body") // ссылки на картинки fb3 { QFile fr(filerels + "/_rels/body.xml.rels" ); if (!fr.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "файл body.xml.rels не открыт"; break; } QXmlStreamReader srr(&fr); while( !srr.atEnd() ) { switch( srr.readNext() ) { case QXmlStreamReader::StartElement: if(srr.name().toString() == "Relationship") { QString f, s; for(int i = 0; i < srr.attributes().count(); i++) { if( srr.attributes().at(i).name() == "Id" ) s = srr.attributes().at(i).value().toString(); if( srr.attributes().at(i).name() == "Target" ) f = srr.attributes().at(i).value().toString(); } if(f.indexOf("cover") != -1) { book->append("<p align=\"center\"><img src=\"" + filerels + "/" + f + "\" alt=\"рисунок\"" + "/></p>"); } else img_fb3.insert(s, f); //qDebug() << f; } break; default: ; } } fr.close(); break; }
Außerdem gibt es einige Tags, deren Zweck mir nicht ganz klar ist:
Zip-Archiv öffnen
Ursprünglich hatte ich geplant, das 7z-Programm zum Entpacken zu verwenden. Aber diese Option verschwand, als ich herausfand, dass Sie das Entpacken von Dateien mithilfe der zlib-Bibliothek und Schnittstellen aus den Bibliotheken zipreader_p.h, zipwriter_p.h und zip.cpp implementieren können, die Sie [herunterladen] können (https://github.com/radekp /qt/tree/master/src/gui/text) zusammen mit anderen Qt-Quellen. Am Ende fand ich heraus, dass diese Bibliotheken auch in den Qt Redistributables (gui-private module) enthalten sind. Übrigens hat jedes Hauptmodul ein solches privates Zwillingsmodul. Und wie die Warnung in jeder der privaten Header-Dateien sagt:
(Diese Datei ist nicht Teil der Qt-API. Sie existiert lediglich als Implementierungsdetail. Diese Header-Datei kann sich von Version zu Version ohne Vorankündigung ändern oder sogar entfernt werden).
Die Funktion UnZip(QString name, QString path) fügt also den Inhalt des Namensarchivs in den Pfadordner ein. Als temporären Speicher schlage ich vor, den Ordner "dmreader" zu verwenden, der im Verzeichnis zum Speichern temporärer Dateien QStandardPaths::standardLocations(QStandardPaths::TempLocation).at(0) erstellt wurde.
Implementierung des Entpackens von Archiven
bool openerTextFiles::UnZip(QString zfile, QString path) { QZipReader cZip(zfile); QDir dir(path); if(!dir.exists()) dir.mkpath( path ); //bool b = cZip.extractAll( path ); bool b = extractFiles( cZip , path ); cZip.close(); return b; }
Wenn wir es mit einem Zip-Archiv zu tun hätten, würde es ausreichen, die Funktion extractAll(QString path) der Klasse QZipReader zu verwenden. Das fb3-Archiv hat jedoch eine Funktion, auf die ich hier nicht näher eingehen werde. Ich habe diesen Algorithmus auf meinem Knie in der Funktion extractFiles (QZipReader zip, QString path) hinzugefügt.
bool openerTextFiles::extractFiles(const QZipReader &zip, const QString &destinationDir) { QDir baseDir(destinationDir); QVector<QZipReader::FileInfo> allFiles = zip.fileInfoList(); // create directories first foreach (QZipReader::FileInfo fi, allFiles) { const QString absPath = destinationDir + QDir::separator() + fi.filePath; if (fi.isDir) { if (!baseDir.mkpath(absPath)) return false; if (!QFile::setPermissions(absPath, fi.permissions)) return false; } } // ------------------------ foreach (QZipReader::FileInfo fi, allFiles) { const QString absPath = destinationDir + "/" + fi.filePath; QString d; // для fb3 if(absPath.indexOf("/") != -1) { d = absPath.left(absPath.lastIndexOf("/")); QDir dir(d); if(!dir.exists()){ dir.mkdir(dir.path()); } } } foreach (QZipReader::FileInfo fi, allFiles) { const QString absPath = destinationDir + "/" + fi.filePath; if(absPath.endsWith("/")) { if( !baseDir.exists(fi.filePath) ) { if (!baseDir.mkdir(fi.filePath)) return false; if (!QFile::setPermissions(absPath, fi.permissions)) return false; } } else { QString d; // для fb3 if(absPath.indexOf("/") != -1) { d = absPath.left(absPath.lastIndexOf("/")); QDir dir(d); if(!dir.exists()){ dir.mkdir(dir.path()); } } QFile f(absPath); if (!f.open(QIODevice::WriteOnly)) return false; f.write(zip.fileData(fi.filePath)); f.setPermissions(fi.permissions); f.close(); } } return true; // ------------------------ // set up symlinks foreach (QZipReader::FileInfo fi, allFiles) { const QString absPath = destinationDir + QDir::separator() + fi.filePath; if (fi.isSymLink) { QString destination = QFile::decodeName(zip.fileData(fi.filePath)); if (destination.isEmpty()) return false; QFileInfo linkFi(absPath); if (!QFile::exists(linkFi.absolutePath())) QDir::root().mkpath(linkFi.absolutePath()); if (!QFile::link(destination, absPath)) return false; } } }
Der Quellcode des Programms kann hier heruntergeladen werden.
Fazit
Das geschriebene Programm erhebt keinen Anspruch auf volle Funktionsfähigkeit beim Lesen von fb3-Dateien. Aber um den Text zu öffnen, anzuzeigen und in html zu speichern, das in einer Vielzahl von Editoren verarbeitet werden kann, ist es großartig. Viel Spaß beim Lesen.
Добрый день!
Вы не думали разместить репозиторий проекта на GitHub?
Приветствую!
Я думаю дойдёт и до этого, но пока изучать его у меня нет желания.
Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html