Bestimmte Anzahl an Bytes lesen



  • Hallo,

    ich habe für ein Programm genau 30 verschiedene Bilder in eine .dat-Datei gepackt. Nur weiß ich jetzt nicht wie ich die einzelnen Biler bitweise einlesen kann. Praktisch dem Programm z.B. sagen, von 0 und 90Bytes ist das 1.Bild, von 90 und 151Bytes das 2. usw... (Die Position der Bilder ist mir bekannt). Wenn es geht bitte auch noch posten, wie das mit einer Textdatei funktioniert. 😉



  • Wie wird der Text denn gespeiochert UTF-8, -16, Sonstwie Unicode oder Ascii?
    Meinst du wirklich bitweise ?

    Die Bilder hintereinander liegen, musst du nur Read mit einem entsprechend großem Array aufrufen.

    Falls die in der Datei durcheinander liegen, dann noch vorher Seek.

    Nun hast die einzelnen Bytes: Wenn du daraus ein BitArray erstellt kannst du am einfachsten auf die einzelnen Bits zugreifen.



  • Rhombicosidodecahedron schrieb:

    Wie wird der Text denn gespeiochert UTF-8, -16, Sonstwie Unicode oder Ascii?
    ?

    Ich speichere den Text normal mit ANSI.

    Könntest du vielleicht kurz ein simples Beispiel geben, wie ein solcher Lesevorgang einer Bilddatei bis zur einer verwendbaren Bitmap-Instanz ungefähr auszusehen hat? Ich kann mir nicht wirklich vorstellen wie so etwas gemacht wird.



  • Wenn ich jetzt die Bytes aus der Bilddatei auslese, in einem <unsigned char> array speichere und mir ausgeben lasse, erhalte ich nur einige Zahlen, aber wie wird daraus jetzt eine verwendbare Bitmap? (Textdatei auslesen klappt wunderbar).



  • In .net geht das über einen Memory-Stream, ungefähr wie hier:
    http://www.codeproject.com/KB/recipes/ImageConverter.aspx



  • Danke schonmal allen für die Hilfe! 😃

    Der Kompilierer zeigt zwar keine Fehler an, aber dennoch kann ich die Bitmap nicht verwenden, da sie den Wert NULL hat. 🙄

    Das ist mein bisheriger Code:

    array<unsigned char> ^ Array1 = gcnew array<unsigned char>(Größe);
    
    //"Größe" stellt eine beliebige Zahl dar
    
    System::IO::FileStream ^ reader = gcnew System::IO::FileStream(Dateiname, System::IO::FileMode::Open);
    
    reader->Read(Array1, Anfang, Größe);
    
    System::IO::MemoryStream ^ memorystream = gcnew System::IO::MemoryStream(Array1);
    Bitmap ^ bmp = gcnew Bitmap(memorystream);
    
    ...
    
    System::Void Form1_Paint(System::Object^  sender, System::Windows::Forms::PaintEventArgs^  e)
    {
    e->Graphics->DrawImage(bmp, 10, 10);
    }
    

    Wo genau liegt der Fehler?



  • ich fürchte, dass du zuerst die Bitmap zuerst versuchst zu zeichnen und dann lädst. Du kannst ja vorher abfangen, ob bmp != nullptr ist, bevor du es zeichnest.



  • Rhombicosidodecahedron schrieb:

    ich fürchte, dass du zuerst die Bitmap zuerst versuchst zu zeichnen und dann lädst. Du kannst ja vorher abfangen, ob bmp != nullptr ist, bevor du es zeichnest.

    Stimmt, das war der Fehler. Ich habe die Bitmap im Konstruktor deklariert, anstatt sie als Instanzvariable zu deklarieren, weshalb die Bitmap-Variable in der Paint-Methode nicht referenziert ist. Hab jetzt die Bitmap-Deklaration außerhalb des Konstruktor deklariert, jetzt funktioniert alles wunderbar 😃 . Danke für die Hilfe! 😉



  • Eine Frage hätte ich aber noch, wenn ich besonders große Dateien lade (1,5GB ist die Grenze, da dann der Arbeitsspeicher voll ist), und ich die Bytes dem MemoryStream übergeben habe, wie gebe ich dann den Speicherplatz der <unsigned char> arrays wieder frei? Ich habe es schon mit delete, delete[] , ->Clear() und ->Rezise() probiert, allerdings klappt keine einzige dieser Methoden, da kein bisschen Arbeitsspeicher freigegeben wird.



  • Eigentlich sollte es egal sein wie groß die Datei ist, da reader nur ein "Pointer" / Handle auf die aktuelle Position in der Datei ist und erst bei Bedarf eingelesen, wenn read aufgerufen, wird.

    Array1 kannst du nicht vergrößern oder verkleinern, nur neu zuweise. Sonst kannst mal in System::Array und System::Buffer nachschauen ob da sinnvolle Funktionen vorhanden sind.



  • Naja, je mehr ich lesen will, desto größer muss auch die Größe des <unsigned char> array sein. Und da ich lediglich 2GB Arbeitsspeicher habe, kommt bei

    array<unsigned char> ^ Array1 = gcnew array<usigned char>(1600000000)
    

    eine entsprechende Exception, dass der Arbeitsspeicher nicht ausreichen würde, wenn dieses Array erstellt würde. Was heißt, dass ich lediglich ca 1500000000 Bytes lesen kann = 1,5GB:

    Eine nicht behandelte Ausnahme des Typs "System.OutOfMemoryException" ist in ***.exe aufgetreten.

    Was aber nicht wirklich ein Problem darstellt, weil ich eigentlich keine so großen Dateien benutze

    Aber ein wirkliches Problem hätte ich noch:

    Was mache ich, wenn ich nicht bei 0 Bytes anfangen möchte zu lesen? Wenn ich von Byte 500 an 1000 Bytes lesen möchte, brauche ich trotzdem 1500 Elemente in meinem Array. Wenn ich das ganze jetzt dem MemoryStream übergebe, haben Array1[0] - Array1[499] den Wert 0, was jetzt beim Erstellen der Bitmap eine Exception gibt:

    Eine nicht behandelte Ausnahme des Typs "System.ArgumentException" ist in System.Drawing.dll aufgetreten.

    Zusätzliche Informationen: Ungültiger Parameter.



  • Taeli schrieb:

    Was mache ich, wenn ich nicht bei 0 Bytes anfangen möchte zu lesen? Wenn ich von Byte 500 an 1000 Bytes lesen möchte, brauche ich trotzdem 1500 Elemente in meinem Array. Wenn ich das ganze jetzt dem MemoryStream übergebe, haben Array1[0] - Array1[499] den Wert 0, was jetzt beim Erstellen der Bitmap eine Exception gibt:

    Wenn du nicht von Byte 500 an 1000 Bytes lesen möchtest, dann mach das und verschiebe die Position mittels seek und du kannst wieder von Byte 0 lesen.
    Sonst kannst du mit einem anderen Konstruktor angeben, welchen Bereich von Array1 in memoryStream angezeigt werden soll.

    Taeli schrieb:

    Naja, je mehr ich lesen will, desto größer muss auch die Größe des <unsigned char> array sein. Und da ich lediglich 2GB Arbeitsspeicher habe, kommt bei

    Was würde passieren, wenn du dann Bitmap ^ bmp = gcnew Bitmap(reader); schreibst, wenn du schon reader an die richtige Stelle gebracht hast?



  • Rhombicosidodecahedron schrieb:

    Sonst kannst du mit einem anderen Konstruktor angeben, welchen Bereich von Array1 in memoryStream angezeigt werden soll.

    Perfekt, wenn ich einen neuen Konstruktor benutze, klappt es 😃 . Vielen Dank für deine Hilfe/Geduld! 😃


Log in to reply