Text Datei zeichenweise auslesen

Alles rund um die Programmierung mit Qt
Antworten
DyXe
Beiträge: 17
Registriert: 11. Dezember 2009 11:34
Wohnort: Spay bei Koblenz
Kontaktdaten:

Text Datei zeichenweise auslesen

Beitrag von DyXe »

Hallo leute, habe vor ein paar Wochen mit QT angefangen, C++ kenne ich die Grundlagen. Nun habe ich ein Projekt aufgetragen bekommen und bräuchte dabei eine Starthilfe.

folgendes íst die Anforderung (Konsolenanwendung!):

.txt Dateien einlesen und diese in eine SQLite Datenbank schreiben. Dabei sollen verschiedene Sachen aus den .txt Dateien in verschiedene spalten/zeilen geschrieben werden.

Es sollen alle Zeilen, welche mit "<!" beginnen bis zum ">" oder falls vorhanden bis zum letzen "\" der Zeile ausgelesen werden und in eine Spalte geschrieben werden. Der Rest der Zeile in eine andere Spalte.
Darunter die Zeile soll komplett ausgelesen werden und in eine weitere Spalte geschrieben werden. Die 1. Zeile der Textdokumente sollen eine UNIQUE und PRIMARY KEY Spalte sein, damit jedes Textdokument nur 1 mal in der Datenbank sein kann.

Nun habe ich keine Ahnung, wie ich das machen soll >.<

Datei einlesen ist ja klar mit QFile. Nun weiß ich nicht wie ich es zum String umwandle und weiter arbeiten soll. Kann mir jemand von euch helfen? Oder mir vllt sagen welche Klassen ich für mein Vorhaben brauche? Wäre echt nett :)

lg Daniel
Oliver Hom
Beiträge: 33
Registriert: 27. Mai 2009 12:44

Beitrag von Oliver Hom »

Datei auslesen

Code: Alles auswählen

QFile cf (path);
if (!cf.open(QIODevice::ReadOnly | QIODevice::Text)) {
	QMessageBox::critical(0, QString("Header"), QString("Unable to read file!"));
	return;
}
QTextStream in(&cf);
while (!in.atEnd()) 
{
	QString line = in.readLine();
}
Dann mit QRegExp oder den Stringfunktionen die gewünschten Ausschnitte ermitteln und mit

Code: Alles auswählen

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("test.db");
..
db.open();


QSqlQuery query;
query.exec(SQL);

Alles so grob aus Kopf.

Gruß,
Oliver
DyXe
Beiträge: 17
Registriert: 11. Dezember 2009 11:34
Wohnort: Spay bei Koblenz
Kontaktdaten:

Beitrag von DyXe »

okay danke, habe das mit dem Text zurechtschneiden nun hinbekommen.
Jetzt müsste ich nurnoch wissen, wie ich die daten in die datenbankschreibe xD
hier mal mein Quellcode:

Code: Alles auswählen

#include <QtCore/QCoreApplication>
#include <QFile>
#include <iostream>
#include <QTextStream>
#include <QMessageBox>
#include <QtSql>
#include <QString>

using namespace std;

int main(int argc, char *argv[])
{

	//----------------Textdokument einlesen----------------
	QFile filelist ("./filelist.txt");	//weist 'filelist' den Pfad der Textdatei zu
	if (!filelist.open(QIODevice::ReadOnly | QIODevice::Text)) 
	{ 
	   QMessageBox::critical(NULL, QString("Header"), QString("Datei auslesen fehlgeschlagen!")); 
	   return 0; 
	} 

	//----------------String Verarbeitung & Ausgabe----------------
	QTextStream in(&filelist); //weist 'in' den Text von 'filelist' zu

	QString revision = in.readLine();

	while (!in.atEnd()) 
	
	{ 
		QString zeile = in.readLine();		//liest Zeilen aus und weist sie 'zeile' zu
		if (zeile.startsWith("<"))
		{
			QString gesuchtes = "\\";
			QString dateiName = zeile.mid(zeile.lastIndexOf(gesuchtes)+1);	//weist 'dateiName' alle Buchstaben 'gesuchtes'+1 bis zum Ende der Zeile zu
			QString dateiPfad = zeile.left(zeile.lastIndexOf(gesuchtes)+1);	//weist 'dateiPfad' alle Buchstaben bis 'gesuchtes'	
			std::string dateiNameAusgabe = dateiName.toAscii().data();		//wandelt QString 'dateiName' zu String 'dateiNameAusgabe' um
			std::string dateiPfadAusgabe = dateiPfad.toAscii().data();		//wandelt QString 'dateiPfad' zu String 'dateiPfadAusgabe' um
			cout << "Dateiname: " << dateiNameAusgabe << endl;;				//gibt dateiNameAusgabe aus
			cout << "Dateipfad: " << dateiPfadAusgabe << endl;;				//gibt dateiPfadAusgabe aus
		}
		else
		{
			QString hash = zeile;	//weist 'HASH' die komplette Zeile zu
			std::string hashAusgabe = hash.toAscii().data();				//wandelt QString 'hash' zu String 'hashAusgabe' um
			cout << "HASH: " << hashAusgabe << endl;;						//gibt hashAusgabe aus
			cout << "\n";
		}
	}

/*	//----------------Datenbank----------------
	QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); //erstellt eine Datenbank 'db'
	db.setDatabaseName("test.db");							//gibt der Datenbank den namen "test.db"
	db.open();												//öffnet die Datenbank

	QSqlQuery query; 
//	query.exec(SQL);
*/
	QCoreApplication a(argc, argv);
	return a.exec();
}
Die 'cout' habe ich nur gemacht, damit ich überprüfen kann ob alles stimmt :)
Verbesserungsvorschläge zu meinem Programmierstil sind willkommen ^^
wie gesagt, stehe noch am Anfang meiner Ausbildung und möchte ja später mal ein guter Programmierer werden :lol:
Wäre nett wenn mir da jemand bei helfen könnte :)

lg Daniel
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Verwende statt cout, qDebug, dann kannst du dir die ganzen Umwandlung in std::string sparen.

Dann eigne dir die Grundlagen von SQL an, dann kannst du dir auch die passende Query für die Inserts schreiben.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

1. entscheide dich für einen Applikationstyp (Konsole oder GUI)
QCoreApplication (Konsolenprogramm) beisst sich mit QMessageBox (GUI)

2. Die Applikationsinstanz (Q(Core)Application) ist wichtig! Erst mit dieser können Widgets angezeigt und Qt-Plugins verwendet werden. Diese kommt also als erstes, nicht als letztes..

3. verwende qDebug() anstelle cout.. das nimmt dir viel ab (edit: zu spät :wink: )

4. auskommentierter (Datenbank)Code funktioniert nicht..

hth...
Oliver Hom
Beiträge: 33
Registriert: 27. Mai 2009 12:44

Beitrag von Oliver Hom »

Schau dir mal die Doku zu den folgenden Klassen an:

QSqlDatabase
QSqlError
QSqlQuery

Mit dem Codestück solltes du eigentlich Daten in eine vorhandene sqlite bekommen.
Datenbankname und SQL müssen natürlich noch geändert werden.

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("namederdatenbank.db");
QString sSQL = "Insert into tbl (fields....) values (....)";
QSqlQuery query;
query.exec(sSQL);
db.close ();

Die Datenbank kannst du ganz einfach per Konsole mit sqlite3 erzeugen und mit create table Tabellen hinzufügen.

SQL Hilfe:
http://www.sql-und-xml.de/sql-tutorial/ ... daten.html
http://www.sql-und-xml.de/sql-tutorial/ ... eilen.html
http://www.sqlite.org/lang_createtable.html

Gruß,
Oliver
DyXe
Beiträge: 17
Registriert: 11. Dezember 2009 11:34
Wohnort: Spay bei Koblenz
Kontaktdaten:

Beitrag von DyXe »

sooo, nun trägt er alles richtig in die Datenbank ein =)
an dieser stelle schonmal vielen Dank :)

Nun hätte mein Chef noch gerne, dass er mehrere Text dateien einlesen kann und nicht nur eine. Also dass man in der Konsole eingeben kann, welche Datei/en eingelesen werden sollen und er diese dann einliest. Jemand ne Ahnung wie das geht? :)

Hier mein bisheriger Quellcode

Code: Alles auswählen

#include <QtCore/QCoreApplication>
#include <QFile>
#include <iostream>
#include <QTextStream>
#include <QMessageBox>
#include <QtSql>
#include <QString>
#include <QSqlDatabase>

using namespace std;

int main(int argc, char *argv[])
{

	//----------------Textdokument einlesen----------------
	QFile filelist ("./filelist.txt");	//weist 'filelist' den Pfad der Textdatei zu
	if (!filelist.open(QIODevice::ReadOnly | QIODevice::Text)) 
	{ 
	   QMessageBox::critical(NULL, QString("Header"), QString("Datei auslesen fehlgeschlagen!")); 
	   return 0; 
	} 

	//----------------String Verarbeitung & Ausgabe & Datenbank----------------
	QTextStream in(&filelist); //weist 'in' den Text von 'filelist' zu

	QString revision = in.readLine();

	QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); // Datenbank erstellen
	qDebug() << "Datenbank wurde erstellt\n\n";
	db.setDatabaseName("Datenbank.db");						// Datenbank einen Namen zuweisen
	qDebug() << "Datenbankname wurde zugewiesen\n\n";
	db.open();												// Datenbank öffnen
	qDebug() << "Datenbank wurde geoeffnet\n\n";
	QSqlQuery query;
	QString tabelleRevision = "CREATE TABLE Revision (ID INT, Revision INT);"; // Tabelle "Revision" erstellen
	query.exec(tabelleRevision); //fügt die Tabelle "Revision" ein
	cout << "Tabelle 'Revision' wurde erstellt\n\n";
	QString tabelleFiles = "CREATE TABLE Files (ID INT, HASH TEXT,  Ort TEXT, Filename TEXT);"; // Tabelle "Files" erstellen
	query.exec(tabelleFiles);	 //fügt die Tabelle "Files" ein
	qDebug() << "Tabelle 'Files' wurde erstellt\n\n\n";
	QString datenRevision = "INSERT INTO Revision VALUES (1, '"+revision+"');"; // Werte in "Revision" eintragen
	query.exec(datenRevision);	 //fügt die Daten der Tabelle "Revision" ein
	qDebug() << "Tabelle 'Revision' wurden folgende Werte zugewiesen:\n\tID\t\t 1 \n\tRevision " << "\t" << revision << "\n";

	while (!in.atEnd()) 
	
	{ 
		QString dateiName;
		QString dateiPfad;
		QString hash;
		QString gesuchtes;
		QString zeile = in.readLine();		//liest Zeilen aus in ein und weist sie 'zeile' zu
		if (zeile.startsWith("<"))			//beginnt die Zeile mit "<"?
		{
			if ((zeile.contains("\\") == true))	//enthält die Zeile "\"?
				gesuchtes = ("\\");				
			else
				gesuchtes = (">");
			dateiName = zeile.mid(zeile.lastIndexOf(gesuchtes)+1);	//weist 'dateiName' alle Buchstaben 'gesuchtes'+1 bis zum Ende der Zeile zu
			dateiPfad = zeile.left(zeile.lastIndexOf(gesuchtes)+1);	//weist 'dateiPfad' alle Buchstaben bis 'gesuchtes'	
			QString zeile = in.readLine();
			hash = zeile;	//weist 'HASH' die komplette Zeile zu
		}

		QString datenFiles = "INSERT INTO Files VALUES (1, '"+hash+"', '"+dateiPfad+"', '"+dateiName+"');"; // Werte in "Files" eintragen
		query.exec(datenFiles);		 //fügt die Daten der Tabelle Files ein
		qDebug() << "Tabelle 'File' wurden folgende Werte zugewiesen\n\tID\t\t 1 \n\tHASH " << "\t\t" << hash << " \n\tDateipfad "  << "\t" << dateiPfad << " \n\tDateiname "  << "\t" << dateiName << "\n";	
	}
	db.close (); //Datenbank schließen

	QCoreApplication a(argc, argv);
	return a.exec();
}
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

da empfiehlt sich argc und argv ....
DyXe
Beiträge: 17
Registriert: 11. Dezember 2009 11:34
Wohnort: Spay bei Koblenz
Kontaktdaten:

Beitrag von DyXe »

mhh versuche schon 2 stunden rum aber komme nicht weiter =/
könne mir jemand von euch dazu noch ein paar tipps geben oder einen kleinen anschupser an code?

also es soll immer nur 1 datei pro aufruf einlesen. Die Datei soll man selbst wählen können. Jede Textdatei die man einliest soll eine eigene ID in der Datenbank haben. Bei einem aufruf von einer anderen datei soll diese automatisch eine neue ID bekommen. An der Revisionsnummer in der 1. Zeile jedes textdokumentes kann man überprüfen ob es das dokument/die id schon gibt.

lg Daniel :)
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

DyXe hat geschrieben: also es soll immer nur 1 datei pro aufruf einlesen.
Willst du jetzt nur eine Datei einlesen, oder "dass er mehrere Text dateien einlesen kann und nicht nur eine"?

Ausserdem: Einfach die Revisionsnummer in der Datenbank speichern, und vor der Verarbeitung einer Textdatei per select prüfen, ob selbige schon drin steht, dürfte doch einfach sein, oder?
DyXe
Beiträge: 17
Registriert: 11. Dezember 2009 11:34
Wohnort: Spay bei Koblenz
Kontaktdaten:

Beitrag von DyXe »

eine datei pro aufruf
wenn man öfter aufruft und andere .txt dateien angibt, soll er die daten in die vorhandene datenbank schreiben
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Also nimmst du einfach die Datei, die dem Programm als Parameter übergeben wird, oder wie lautet genau die Frage?
DyXe
Beiträge: 17
Registriert: 11. Dezember 2009 11:34
Wohnort: Spay bei Koblenz
Kontaktdaten:

Beitrag von DyXe »

Ich habe es nun mal so gemacht:

Code: Alles auswählen

	QStringList arguments = QCoreApplication::arguments();
	if(arguments.size() == 2)
	{
		QString src = arguments.at(1);
		
		//----------------Textdokument einlesen----------------
		QFile filelist (src);	//weist 'filelist' den Pfad der Textdatei zu 
		if (!filelist.open(QIODevice::ReadOnly | QIODevice::Text)) 
		{ 
		   QMessageBox::critical(NULL, QString("Header"), QString("Datei auslesen fehlgeschlagen!")); 
		   return 0; 
		} 
aber irgendwie klappts nicht, wenn ich über die Konsole das eingebe =/
DyXe
Beiträge: 17
Registriert: 11. Dezember 2009 11:34
Wohnort: Spay bei Koblenz
Kontaktdaten:

Beitrag von DyXe »

sooo, habe das projekt nun fast fertig, muss nurnoch eine log datei erstellt werden beim ausführen des programms :)
Vielen Dank für eure Hilfe =)

lg Daniel
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

Messagehandler installieren, in den in nen File schreiben und sonst wie gehabt qDebug() qCritical qWarning würd ich vorschlagen
Antworten