Custom IO Device/de

From Qt Wiki
< Custom IO Device
Revision as of 13:16, 28 June 2015 by Wieland (talk | contribs) (Wieland moved page Custom IO Device German to Custom IO Device/de: Proper localization)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine.
Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean.

German | English


Wie man ein benutzerdefiniertes I/O-Gerät schreibt

Dies ist eine Portierung des Artikels Qt Quarterly 12 about writing a custom QIODevice

Benutzung:

Der folgende Code-Schnipsel zeigt, wie man das benutzerdefinierte I/O-Gerät benutzen würde, um Daten zu verschlüsseln und das Ergebnis in einer Datei zu speichern:

 QFile file("output.dat");
 CryptDevice cryptDevice(&file)
 QTextStream out(&cryptDevice);
 cryptDevice.open(QIODevice::WriteOnly);
 out << "Hello World";

Zur möglichen Verwendung siehe auch unseren Beispiel-Code in git qtdevnet-wiki-mvc/qtdevnet-custom-iodevice .


Verschlüsselung

 QByteArray dataArray;

QBuffer bufferUsedLikeAFile(&dataArray);
 CryptDevice deviceFilter(&bufferUsedLikeAFile);
 deviceFilter.open(QIODevice::WriteOnly);
 QTextStream stream(&deviceFilter);
 QString szText = rawText->toPlainText();
 stream << szText;


Entschlüsselung

 QBuffer bufferUsedLikeAFile(&dataArray);
 CryptDevice deviceFilter(&bufferUsedLikeAFile);
 deviceFilter.open(QIODevice::ReadOnly);
 QTextStream stream(&deviceFilter);
 QString szText = stream.readAll();
 decryptedText->setPlainText(szText);

Das Beispiel-Bild aus dem Testprogramm:

Test app

Das benutzerdefinierte I/O-Gerät

Das Schreiben eines benutzerdefinierten I/O-Gerätes in Qt 4 umfasst das Erstellen einer von QIODevice abgeleiteten Klasse und das Reimplementieren einiger virtueller Funktionen.

Im Vergleich zu Qt 3 gibt dabei einen großen Unterschied: Man muss nur noch 2 Funktionen neu schreiben:

  • qint64 QIODevice::readData ( char * data, qint64 maxSize )
  • qint64 QIODevice::writeData ( const char * data, qint64 maxSize )

Unsere CryptDevice-Klasse wird ein sequenzielles I/O-Gerät. Ob es synchron oder asynchron arbeitet, hängt vom darunter liegenden QIODevice ab.

Quelltext

Die Klassendefinition sieht folgendermaßen aus:

class CryptDevice : public QIODevice
{
 Q_OBJECT
public:
 CryptDevice(QIODevice* deviceToUse, QObject* parent = 0);
 bool open(OpenMode mode);
 void close();
 bool isSequential() const;
protected:
 qint64 readData(char* data, qint64 maxSize);
 qint64 writeData(const char* data, qint64 maxSize);
private:
 QIODevice* underlyingDevice;
 Q_DISABLE_COPY(CryptDevice)
};

Die Definition des Constructors ist ganz einfach:

CryptDevice::CryptDevice(QIODevice* deviceToUse, QObject* parent) :
 QIODevice(parent),
 underlyingDevice(deviceToUse)
{
}

Weil wir ein sequenzielles Gerät haben wollen, reimplementieren wir isSequential:

bool CryptDevice::isSequential() const
{
 return true;
}

in

open()

öffnen wir das darunter liegende Gerät, falls es nicht schon geöffnet ist, und setzetn den Gerätezustand auf mode.

bool CryptDevice::open(OpenMode mode)
{
 bool underlyingOk;
 if (underlyingDevice->isOpen())
 underlyingOk = (underlyingDevice->openMode() != mode);
 else
 underlyingOk = underlyingDevice->open(mode);

if (underlyingOk)
 {
 setOpenMode(mode);
 return true;
 }
 return false;
}

Das Schließen ist trivial.

void CryptDevice::close()
{
 underlyingDevice->close();
 setOpenMode(NotOpen);
}

Um einen Block zu lesen, rufen wir von dem darunter liegenden Gerät

read()

auf. Am Ende verknüpfen wir alle gelesenen Bytes XOR mit der magischen Konstante 0x5E.

qint64 CryptDevice::readData(char* data, qint64 maxSize)
{
 qint64 deviceRead = underlyingDevice->read(data, maxSize);
 if (deviceRead == 1)
 return -1;
 for (qint64 i = 0; i < deviceRead; +''i)
 data[i] = data[i] ^ 0x5E;

 return deviceRead;
}

Um einen Block zu schreiben, erzeugen wir einen temporären Puffer mit unseren ge-XOR-ten Daten. Eine effizientere Implementierung würde einen 4096-Byte-Puffer auf dem Stack nutzen und

write()

mehrfach aufrufen, wenn die Größe der Daten die des Puffers übersteigt.

qint64 CryptDevice::writeData(const char* data, qint64 maxSize)
{
 QByteArray buffer((int)maxSize, 0);
 for (int i = 0; i < (int)maxSize;''+i)
 buffer[i] = data[i] ^ 0x5E;
 return underlyingDevice->write(buffer.data(), maxSize);
}