Binärdatei lesen und speichern die größer als der Arbeitsspeicher ist

  • VB.NET

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von Elephant.

    Binärdatei lesen und speichern die größer als der Arbeitsspeicher ist

    Binärdatei lesen und speichern die größer als der Arbeitsspeicher ist

    Habe Folgendes bei Microsoft gefunden

    VB.NET-Quellcode

    1. Public Sub CopyBinaryFile(ByVal path As String,
    2. ByVal copyPath As String,
    3. ByVal bufferSize As Integer,
    4. ByVal overwrite As Boolean)
    5. Dim inputFile = IO.File.Open(path, IO.FileMode.Open)
    6. If overwrite AndAlso My.Computer.FileSystem.FileExists(copyPath) Then
    7. My.Computer.FileSystem.DeleteFile(copyPath)
    8. End If
    9. ' Adjust array length for VB array declaration.
    10. Dim bytes = New Byte(bufferSize - 1) {}
    11. While inputFile.Read(bytes, 0, bufferSize) > 0
    12. My.Computer.FileSystem.WriteAllBytes(copyPath, bytes, True)
    13. End While
    14. inputFile.Close()
    15. End Sub


    Ich will die Daten natürlich nach den lesen und vor dem schreiben verändern.
    Habe das mal mit einer Datei von 103 Byte und einem bufferSize von 50 probiert.
    Die Zieldatei ist dann 150 Byte groß, mit 47 Byte Müll aus dem Lesevorgang vor dem letzten.
    Man kann natürlich vorher die Dateigröße abfragen, sich ein bufferSize ausrechnen und bei einer Primzahl noch einen letzten Speichervorgang mit dem Rest programmieren.

    Aber da muss es doch etwas Besseres geben?

    CodeTags korrigiert ~VaporiZed

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Elephant schrieb:

    Habe Folgendes bei Microsoft gefunden
    Die schreiben auch so allerlei Zeug, wenn der Tag lang ist...
    Also es funktioniert, was die veröffentlichen, aber oft genug ists ziemlicher Mist.
    So etwa hier: einerseits zum häppchenweisen Einlesen wird ein Stream verwendet, zum Schreiben dann aber mit My.Computer.FileSystem.WriteAllBytes() dieselbe Datei für jedes Häppchen neu öffnen, verlängern, schliessen - was wie gesagt funktioniert - aber fürs File-Management absolut abwegig ist.

    Wie man effizient beliebig grosse Datenmengen bewegt ist hier tutoralisiert: Streams
    @Elephant Und dann gibt es noch die Auslagerungsdatei.
    Ignoriere die Dateigröße fürs Erste und feddich.
    Wenn das dann zu langsam wird, sehen wir weiter.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    @Elephant Wie groß ist denn die Datei?
    Musst Du sie vollständig durchflöhen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Kann zur Größe nichts sagen, denn es geht nicht um eine bestimmte Datei.
    Soll sich nur für jede x-beliebige Datei benutzen lassen.
    Die werden dann auch vollständig durch flöht.

    Wenn man den Microsoft Code berichtigen will, sieht das so aus

    VB.NET-Quellcode

    1. Public Sub CopyBinaryFile(ByVal path As String,
    2. ByVal copyPath As String,
    3. ByVal bufferSize As Integer,
    4. ByVal overwrite As Boolean)
    5. Dim inputFile = IO.File.Open(path, IO.FileMode.Open)
    6. Dim anzahl As Integer
    7. anzahl = My.Computer.FileSystem.GetFileInfo(path).Length
    8. If overwrite AndAlso My.Computer.FileSystem.FileExists(copyPath) Then
    9. My.Computer.FileSystem.DeleteFile(copyPath)
    10. End If
    11. ' Adjust array length for VB array declaration.
    12. Dim bytes = New Byte(bufferSize - 1) {}
    13. Do
    14. If anzahl < bufferSize Then
    15. bufferSize = anzahl
    16. ReDim bytes(anzahl - 1)
    17. End If
    18. anzahl = anzahl - inputFile.Read(bytes, 0, bufferSize)
    19. My.Computer.FileSystem.WriteAllBytes(copyPath, bytes, True)
    20. Loop Until anzahl <= 0
    21. inputFile.Close()
    22. End Sub


    Sinniger ist aber das, was sich im Link von ErfinderDesRades findet

    VB.NET-Quellcode

    1. Private Sub CopyFile(srcName As String, destName As String)
    2. Dim Text As String
    3. Dim enc As New System.Text.ASCIIEncoding()
    4. Using src = New IO.FileStream(srcName, IO.FileMode.Open), dest = New IO.FileStream(destName, IO.FileMode.Create)
    5. Dim buf(1023) As Byte
    6. Dim read = buf.Length
    7. While read = buf.Length
    8. read = src.Read(buf, 0, read)
    9. dest.Write(buf, 0, read)
    10. End While
    11. End Using
    12. End Sub

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Elephant“ ()

    @Elephant Missverständnis: Mit durchflöhen meine ich, dass sich der Inhalt der Datei angesehen wird.
    Deswegen nochmal meine Frage:
    Soll die Datei durchflöht oder ausschließlich kopiert werden?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Elephant schrieb:

    Sinniger ist aber das, was sich im Link von ErfinderDesRades findet


    Öhh, dazu aber noch eine Amerkung von mir. Streams bieten ja bereits eine CopyTo Funktion, die man einfach verwenden kann um die Daten von der einen Seite auf die andere zu kopieren. Hier kann auch die Buffergröße mit angegeben werden, wenn das gewollt ist. Die Implementierung sieht hier so aus:

    C#-Quellcode

    1. byte[] buffer = new byte[bufferSize];
    2. int read;
    3. while ((read = Read(buffer, 0, buffer.Length)) != 0)
    4. destination.Write(buffer, 0, read);

    An diese würde ich mich auch halten, wenn ich das selber implementieren will, um da noch eingreifen zu können.
    Ich sehe hier auch 2 Unterschiede zu deinem Code.

    1. Bei nicht gesetzter Buffergröße ist diese 81920 Byte groß. Das hat folgende Erklärung:

    C#-Quellcode

    1. //We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
    2. // The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
    3. // improvement in Copy performance.


    2. Read wird solange aufgerufen bis es 0 zurück gibt und nicht bis es nicht mehr auf die angeforderte Größe kommt. Das ist auch wichtig, da es so definiert ist. Der Stream kann weniger zurück geben und noch nicht am Ende sein.
    ​Die Gesamtanzahl der in den Puffer gelesenen Bytes. Dies kann weniger als die Anzahl der angeforderten Bytes sein, wenn diese Anzahl an Bytes derzeit nicht verfügbar ist, oder 0, wenn das Ende des Streams erreicht ist.

    Read(Byte[], Int32, Int32)
    Bei einem FileStream ist das in den meisten Fällen zwar so, aber darauf kannst du dich nicht verlassen. Möglicherweise liefert ein gemapptes Netzwerklaufwerk erst weniger Daten, weil gerade noch nicht genug angekommen sind und mach danach ganz normal weiter.
    Ich will nicht nur Kopieren.

    Hatte in meinem ersten Beitrag geschrieben:
    Ich will die Daten natürlich nach den lesen und vor dem Schreiben verändern.

    Das habe ich hier aber ausgespart da man so besser sieht worum es geht.
    Als, wenn da noch x-Zeilen Code dazwischen stehen um die Daten zu verändern.

    Gut auch die Hinweise das eventuell vor dem Ende schon nichts mehr zurückgegeben wird.

    Elephant schrieb:

    da man so besser sieht worum es geht.
    Klar. Dann machst Du eine Kommentarzeile in Deinen Code hier wo steht, dass da was mit getan wird. Dann sieht man das sofort.
    Also:
    Poste eine vollständige und belastbare Aufgabenstellung ohne dabei Code zu verwenden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Klar. Dann machst Du eine Kommentarzeile in Deinen Code hier wo steht, dass da was mit getan wird. Dann sieht man das sofort.
    Also:
    Poste eine vollständige und belastbare Aufgabenstellung ohne dabei Code zu verwenden.


    Ich dachte mit dem Text unter dem Code, hätte ich eine vollständige und belastbare Aufgabenstellung gemacht.
    Aber du hast recht, mit der Kommentarzeile im Code ist es offensichtlicher.
    Gemerkt fürs Nächste mal.
    @Elephant Verliere mal zwei Sätze, was Du mit dem Inhalt der Datei anfangen willst.
    Das ist doch der wesentliche Unterschied zum einfachen Kokpieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Verliere mal zwei Sätze, was Du mit dem Inhalt der Datei anfangen willst.

    Dateien Ver- und Entschlüsseln.
    Habe sowas schonmal vor 20 Jahren programmiert als es noch eine Relevanz hatte.
    Heute gibt es Programme, die besser sind, als meins werden wird.
    Ist also vorwiegend dazu da mich zu beschäftigen.
    Einzige Besonderheit man braucht keinen Schlüssel und doch wird es so sein das selbst, wenn man das Programm hat es niemand gelingen wird die Entschlüsselung zu starten.
    Wie? Du auch nicht?
    Ich bin ja da nur Laie, aber klingt entweder nach dem, worauf viele (inklusive mir, siehe hier) schon lange warten. Oder nach security by obscurity.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    Wie? Du auch nicht?

    Habe ich schlecht formuliert.
    Richtig wäre niemand außer mir.
    Es wird aber einfacher sein die Daten zu entschlüssel als das Programm zur Entschlüsselung zu bewegen.
    Ist aber nichts womit die Allgemeinheit was anfangen kann, sondern wenn nur für einen sehr begrenzten Personenkreis.
    Wie schon geschrieben, ist also vorwiegend dazu da mich zu beschäftigen.

    Elephant schrieb:

    Einzige Besonderheit man braucht keinen Schlüssel und doch wird es so sein das selbst, wenn man das Programm hat es niemand gelingen wird die Entschlüsselung zu starten.

    Und wer das Programm hat, kommt auch an das Verfahren ran. Reverse engineering!

    Es sollte das Kerkhoff'sche Prinzip berücksichtigt werden. https://de.wikipedia.org/wiki/Kerckhoffs%E2%80%99_Prinzip

    Solltest Du ein neues Krypto-Verfahren entwickeln solltest, das auch sicher vor Quanten-Computer ist, nur her damit. Aber bitte nach dem Kerkhoff'schen Prinzip.
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).

    INOPIAE schrieb:

    Und wer das Programm hat, kommt auch an das Verfahren ran. Reverse engineering!

    Natürlich ist Reverse Engineering möglich.
    Das sehe ich aber nicht als "die Entschlüsslung des Programms starten" an.
    Wie schon geschrieben, es wird aber einfacher sein die Daten zu entschlüsseln als das Programm zur Entschlüsselung zu bewegen.
    Es wird auch nicht ein Stein der Weisen werden.
    Es ist vorwiegend dazu da mich zu beschäftigen.