Größe Dateien mittels FileStream in byte[] Puffer lesen.



  • Mit folgendem Code kann ich beliebige Dateien in einen Puffer lesen

            public byte[] BytPuffer;
            public long Laenge;
            public string Dateiname;
    
            private void button1_Click(object sender, EventArgs e)
            {
               if (openFileDialog1.ShowDialog() == DialogResult.OK)
               { Dateiname = openFileDialog1.FileName; }
                
                using (FileStream fs = new FileStream(Dateiname, FileMode.Open, FileAccess.Read))
                {
                    Laenge = fs.Length; // long (Int64)
                    fs.Seek(0, SeekOrigin.Begin); // ( long,..)
                    BytPuffer = new byte[Laenge]; // long
                    fs.Read(BytPuffer, 0, (int)Laenge); // (byte[],int32,int32)
                    fs.Close();
                }
            } 
    
    

    Alle FileStream Funktionen benutzen Long Werte, lediglich fs.Read benötigt Int32 Angaben. Damit ist die Dateilänge auf knapp über 2 GB begrenzt (0x7FFFFFFF).
    Wie liest man eine z.B. 8 GB Datei in den Puffer ?
    fs.Length liefert einen Long-Wert = ok.
    new Byte[Laenge] legt einen Puffer in einer Long-Länge an.
    Beim Read ist aber Schluss mit Long...



  • Mit einer Schleife?



  • @hkdd

    Wie liest man eine z.B. 8 GB Datei in den Puffer ?

    Besser nicht als Ganzes.



  • @Mechanics sagte (/forum/post/2570939):

    Mit einer Schleife?

    Dann müsste aber jeder gelesene Block einen eigenen Puffer haben, weil man ja beim Read zwar das Offset ab Pufferanfang angeben kann, aber leider nur als Int32. Mit Seek kann man per Long-Angabe auf solche Segmente positionieren. Das hilft bei Read aber nicht.
    Man könnte allerdings immer in einen z.B. 2GB Puffer lesen ( n * 2GB + Rest ) und danach jedes mal die gelesenen Bytes in den Datei-Gesamtpuffer übertragen.
    Sollte man nach evtl. Manipulationen dieser Puffer wieder als Datei ausgeben wollen, müsste man das auch in derartigen Segmenten regeln.

    Mir erschließt sich bloß nicht, was die C# Maker sich dabei gedacht haben, beinahe überall bei FileStream mit Long zu arbeiten, nur beim Read und Write nicht.


  • Administrator

    @hkdd sagte in Größe Dateien mittels FileStream in byte[] Puffer lesen.:

    Das hilft bei Read aber nicht.

    Wieso hilft das bei Read nicht? Zudem hast du auch das Property Position.

    Mir erschließt sich bloß nicht, was die C# Maker sich dabei gedacht haben, beinahe überall bei FileStream mit Long zu arbeiten, nur beim Read und Write nicht.

    Weil als C# entstanden ist (Release im Jahr 2000), wohl niemand gedacht hat, dass jemand so wahnsinnig sein möchte und 8 GB im Memory ablegen möchte. Das würde ich sogar heute noch (fast 20 Jahre später) als völlig wahnsinnig bezeichnen und nur in Spezialfällen sinnvoll. Die Idee von Stream ist ja gerade, dass man Stück für Stück verarbeiten kann und man die verschiedenen Streams zusammenketten kann.



  • Es gibt aber auch bei einem C#-Array eine Obergrenze (von 2 bzw. 4 GB), s. die Antworten in What is the maximum length of an array in .NET on 64-bit Windows - und daher macht es keinen Sinn einen long-Wert als Länge bei Read anzugeben.

    PS: Bei new byte[Laenge] wird dementsprechend eine OutOfMemoryExceptiongeworfen, wenn die max. Größe überschritten wird.



  • @Th69, natürlich gibt es immer Grenzen. Ich habe es im konkreten Fall mit einer MP4-Datei getestet, die hat eine Länge von 4.172.381.838 Bytes = 0xF8B17E8E ( 3,88 GB), diese Länge passt noch in 4 Bytes (Int32), wird aber als negative Zahl gedeutet.
    new Byte[Laenge] erzeugt keinen Fehler, bei 9 GB freiem RAM ja auch nicht nötig.

    Bei Bilddateien ist es durchaus üblich, diese im Stück einzulesen.

    Bitmap bitmap = (Bitmap)Image.FromFile("OldFilePath.jpg");
    bitmap.Save("NewFilePath.bmp");
    

    Man kann sie aber auch als FileStream in einen Puffer einlesen, dort auf TAGs o.ä untersuchen, in ein anderes Format konvertieren, anzeigen/abspielen usw.
    Wenn genügend RAM vorhanden ist und man in einem 64bit-System arbeitet, dann muss das nicht "wahnsinnig" sein.



  • Ich finde die Beschränkung auf 32 Bit auch sehr suboptimal. Klar sind es immer Speziallfälle, aber solche Spezialfälle kommen nun mal auch vor, und soo selten sind die wahrscheinlich auch nicht. Vor allem haben viele Server locker 32-128GB Ram.
    @hkdd : Notfalls benutzt du eben einen Zwischenbuffer zum Kopieren.
    ODER du nimmst für solche Anwendungen gleichen C++, wo wir schon in einem C++ Forum sind 😉



  • @Mechanics , ich habe gerade bei c++ nachgeschaut, da ist alles ganz genau so. Read und Write arbeiten mit Int32, alles andere mit long.
    Es scheint also eine Vorgabe der Windows-API zu sein.

    void SetLength(long long laenge)
    long long Seek(long long delta,SeekOrigin bezug)
    int Read(array<Byte>^ puffer,int offset,int anzahl)
    void Write(array<Byte>^ puffer,int offset,int anzahl)
    


  • Du hast ja auch nur die C++/CLI Darstellung derselben .NET Klasse FileStream gepostet.

    @Mechanics meinte die native C++ Funktionalität: std::istream.read(..) (und dann ist streamsize je nach Platform entsprechend gesetzt (also für 64-bit auch verwendbar).



  • @Th69/Mechanics: welche WinAPI-Funktion wird da eigentlich aufgerufen? ReadFile() hat ja auch nur DWORD als Parameter.



  • Das ist so gesehen egal... Müsste man im Code nachschauen.
    Ich hab jetzt keine Lust, in der Microsoft Implementierung zu suchen (vermutlich ist der Code eh nicht verfügbar), aber da ich Qt ganz gut kenne, habe ich da schnell geschaut. Die rufen auch ReadFile auf, und begrenzen sogar die Blockgröße auf max. 32 MB, mit dem Kommentar, dass da sonst eh ERROR_NO_SYSTEM_RESOURCES zurückkommt. Und das machen die in einer Schleife.
    Und da ist der Offset kein Problem, das ist ein Zeiger 😉



  • Konnten Arrays in der ersten .NET Version überhaupt schon > 2^31 Einträge sein?



  • @hkdd sagte in Größe Dateien mittels FileStream in byte[] Puffer lesen.:

    Größe Dateien mittels FileStream in byte[] Puffer lesen.

    Davon abgesehen daß das nix deutsch: Memory-Mapped Files


Anmelden zum Antworten