C# WPF RichTextBox: Wie komm ich an den formatierten Text?

Bei Visual Studio: Breakpoint bei "Reader.Close()" setzen (Die Exception wird vermutlich erst danach geworfen). Entweder durch klicken auf die graue Spalte links neben der Codezeile oder mit F9. Dann das Programm im Debug-Modus starten (F5). Wenn der Breakpoint erreicht wird, kannst du mit F10 zeilenweise durch den Code durchgehen.
 
OK, werd ich versuchen.
Ergänzung ()

Ich habe das ganze jetzt mal wieder mit kleineren Dateien ausprobiert. Da funktioniert es anstandslos. Jedoch habe ich bei großen Dateien immer noch das Problem und es wird wieder ein OutofMemory Fehler ausgespuckt. Demnach liegt es daran, dass der String zu groß wird.

das mit dem Debuggen hat mir auch nicht viel mehr aufgezeigt.
Der Stringbuilder schaut bei der großen Datei so aus:
Code:
{<FlowDocument PagePadding="5,0,5,0" AllowDrop="True" NumberSubstitution.CultureSource="User" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><Paragraph><Run xml:lang="de-de">123</Run></Paragraph></FlowDocument>+*+++~##EEAD by Chriss000xx.sssd-#+++:8BPS}


und bei der kleinen Datei so:
Code:
{<FlowDocument PagePadding="5,0,5,0" AllowDrop="True" NumberSubstitution.CultureSource="User" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><Paragraph><Run xml:lang="de-de">123</Run></Paragraph></FlowDocument>+*+++~##EEAD by Chriss000xx.sssd-#+++:8BPS}

Also gleich. Jedoch funktioniert alles bei der kleinen Datei. Auch die verschlüsselten Dateien lassen sich öffnen. Nur bei der Großen nicht.
Achso, der decoded string bleibt auch leer.
 
Zuletzt bearbeitet:
Wenn der String zu lang wird, muss du eben häppchenweise decodieren. Da du mehrere Dateien in eine Datei verschlüsselst wird's etwas komplizierter. Du könntest z.B. einen Header einfügen, der die Dateinamen und -Länge enthält, d.h. du weißt, wo du trennen musst. Die ersten 4 Bytes könnten dann die Länge des Headers selbst angeben, damit du weißt, wo der aufhört.

Dass hat dann den Vorteil, dass du nicht die komplett decodierte Datei auf einmal im Speicher hast, und es fallen auch keine teuren String-Operationen (insbesondere das zig-fache Split) mehr an.
 
Aber der Header wird doch auch je nach Anzahl der Dateien länger. Wie soll ich eine Feste Länge für den Header angeben?
 
Du weist doch, welche und wie viele Dateien du verschlüsselst. Damit kannst du die Headergröße berechnen.

Alternativ kannst du die Informationen auch so speichern:
[Länge der Datei 1]
[Länge des Dateinames]
[Dateiname]
[Dateiinhalt]
[Länge der Datei 2]
...

Und das für jede Datei.
 
Nein, weiß ich nicht. Das Programm soll auf beliebig viele und große Dateien anwendbar sein.
 
Dann nimm den Alternativvorschlag. Damit kannst du einfach die Dateien an die bestehende Datei anhängen.
 
Chriss000 schrieb:
Nein, weiß ich nicht. Das Programm soll auf beliebig viele und große Dateien anwendbar sein.

Doch weißt du :) Du hast das Prinzip nur nicht verstanden.
Ein etwas ausführlicheres Beispiel:

Du speicherst alle Dateien in einem Container.
Was du nun tun kannst ist folgendes:

Wenn du den Container anlegst, schreibst du einen Header rein, bevor du überhaupt irgendwas anderes reinschreibst.

z.B.:
4 byte deiner Wahl, an denen du deinen Container identifizieren kannst.
32 byte für einen Password Hash, damit kannst du am beim Laden des Containers direkt prüfen, ob der jenige, der ihn läd, auch was damit anfangen kann. Nur einen Hash, nicht das PW mit dem du die Dateien verschlüsselt hast.

Ab jetzt fängst du an die Dateien reinzuschreiben.
Allerdings schreibst du für jede Datei wieder einen Header.
Zuerst:
8 byte für die Länge der Datei (sizeof(long))
512 byte für den Dateinamen. Klingt viel, brauchst du aber. Windows unterstützt 256 Zeichen für eine Datei. Ich empfehle dir hier eine UTF16 Encodierung wegen der konstanten Länge.

Nun schreibst du die eigentliche Datei in den Container.
Für jede weitere Datei machst du genau das Gleiche. Erst die Länge, dann den Namen, dann die Daten.

Das ganze würde für 3 Dateien so aussehen:

4B + 32B + 8B + 512B + xB + 8B + 512B + xB + 8B + 512B + xB.


Beim öffnen deines Containers musst du dann nicht erst alles lesen, bevor du irgendwas über den Inhalt sagen kannst. Mit diesen Header könntest du auch eine bestimmte Datei wieder Entschlüsseln ohne vorher den ganzen Container zu bearbeiten.


Zu deinem Problem mit der OutOfMemoryException.
Du liest den ganzen Container, das ist offensichtlich zu viel. Was du tun kannst, ist einen Buffer von z.B. 4kB Größe zu verwenden. D.h. du liest immer nur 4kB aus dem Container und übergibst sie dem CryptStream, dann wieder 4kB usw. bis du alles gelesen hast.
 
Achso. Jetzt hab ich verstanden. Danke, werd ich versuchen.:)
@Darlis: Sry, hab ich überlesen.

EDIT: Gibt es nicht noch irgendeine andere Möglichkeit. Müsste jetzt nämlich mein kompletten Programm umschreiben. :(
Kann man nicht mit Virtuellen Laufwerken arbeiten? Aber nicht so wie Truecrypt. Sondern nur für das Programm.
Oder gibt es irgendeinen Datentyp, der extra für sowas gemacht ist? Wie wärs, dass man komplett mit Byte[]s arbeitet. Funktioniert das, oder erhalte ich da auch einen OutOfMemory Fehler?
 
Zuletzt bearbeitet:
Du möchtest beliebig viele und beliebig große Dateien ver- und entschlüsseln, dabei aber alle Daten im Speicher vorhalten. Auch wenn du auf String-Operationen verzichtest, wirst du früher oder später die nächste OutOfMemoryException bekommen. Also ja, du musst das Programm überarbeiten.

Was soll den mit den entschlüsselten Dateien passieren? Warum müssen die Daten im Speicher bleiben?
 
@Darlis: Ok... Das muss ich wohl oder über das Programm überarbeiten.:(
 
Beim Header-Schreiben habe ich ein Problem, bzw. eine Frage. Bleibt die Anzahl an Bytes einer Datei vor und nach dem Verschlüsseln gleich?
 
Ich denke nicht, da Rijndahl ein Blockchiffre ist. Die Anzahl der Bytes in der verschlüsselten Datei ineterssieren dich aber nicht, da du die Datei vor dem verabeiten ja wieder entschlüsselst. Also etwa so:
Code:
                FileStream file = new FileStream(path, FileMode.Open);

                cstream = new CryptoStream(file, _rijndael.CreateDecryptor(_rijndael.Key, _rijndael.IV), CryptoStreamMode.Read);

                /* 4 Byte ID lesen und prüfen, ob es sich um unseren Container handelt */
                Byte[] containerId = new Byte[4];
                cstream.Read(containerId, 0, 4)

                /* 32 Byte Passwort-Hash lesen um das Passwort zu prüfen */
                Byte[] pwHash= new Byte[32];
                cstream.Read(pwHash, 0, 32)
 
Zuletzt bearbeitet:
Ich glaub ich steh gerad aufm Schlauch. Der Header wird doch so aufgebaut:

id (4b) + hash(32b) + LängedesFlowDoc(16b) + FlowDoc(?b)
+ AnzahlderDateien(10b)

+Datei1Name(256b)
+Datei1Anfangsposition(32b) //Gibt an wo "Datei1Data" beginnt
+Datei1Endposition(32b) /Gibt an wo "Datei1Data" endet


+Datei2Name(256b)
+Datei2Anfangsposition(32b)
+Datei2Endposition(32b)


usw.

+ Datei1Data + Datei2Data usw.

Bei den Rot markierten Stellen weiß ich nun nicht, wie ich das hin bekomme, da ich ja den Header eigentlich erst nach der Verschlüsslung schreiben kann, da ich erst dann die Positionen bestimmen kann.
 
Du kennst doch die Reihenfolge und die Länge der Dateien also kannst du dir die Positionen berechnen. Die verschlüsselten Positionen interessieren dich nicht, da der CryptoStream eh entschlüsselt liest.
Die Anfangsposition ist doch immer die Endpositon der letzten Datei + Länge des Dateinamen + 1.
Die Endposition ist Anfang + Länge des Inhalts.
 
OK, ich werd es nachher mal probieren. :)
 
TheCadillacMan schrieb:
Die Anfangsposition ist doch immer die Endpositon der letzten Datei + Länge des Dateinamen + 1.
Der Dateiname steht ja im Header, also ist die Anfangposition nur die Endpositon der letzten Datei + 1.

@Chriss000: Speicher lieber die Länge der Datei, nicht die Endposition, sonst kommst du noch in Versuchung, die Datei wieder komplett einzulesen ;)

Die Größen, die du verwendest sehen etwas komisch aus. 256 Bit für einen Dateinamen ist viel zu wenig, 32 Byte für eine Dateigröße ist erheblich zu viel. Mit 8 Byte kommst du schon auf 16 Mio. Terrabyte.
 
Die Größen, die du verwendest sehen etwas komisch aus. 256 Bit für einen Dateinamen ist viel zu wenig, 32 Byte für eine Dateigröße ist erheblich zu viel. Mit 8 Byte kommst du schon auf 16 Mio. Terrabyte.
Sry, Ich meinte eigentlich 256 Bytes nicht Bits. ;) Oh, 16 Mio. tb :D War wohl etwas viel. :rolleyes:
Ergänzung ()

Heute Abend habe ich keine Zeit mehr. Leider. Mal sehen, ob ich morgen Zeit finde.
 
Zurück
Oben