Hi In meinem C# Programm lese ich zurzeit u.a. Mp3 Dateien ein, die intern nach Wave konvertiert werden. Das ganze Programm soll die Datei dann über einen MemoryStream benutzen. Das Problem ist nur, dass z.B. der BinaryReader den BaseStream schließt sobald er freigegeben wird. Damit ist mein MemoryStream weg. Kann man das irgendwie verhindern? Die Notlösung wäre den Stream zu kopieren, aber das kostet gerade bei längeren Mp3-Dateien viel zu viel Ram.
avr schrieb: > Das Problem ist nur, dass z.B. der > BinaryReader den BaseStream schließt sobald er freigegeben wird Bei einem der Konstruktoren kann man angeben ob er das tun soll. (Warum bei mp3s nicht einfach nen FileStream nehmen?)
Warum lässt Du Dir vor dem Schließen des BinaryReaders nicht den Buffer des MemoryStream-Objekts geben, sei es über Read oder besser ToArray? Dann kann der Stream Disposed werden und Du hast trotzdem Deine Daten zur Verfügung und könntest Damit auch wieder einen neuen MemoryStream öffnen. Grüße Markus
bluppdidupp schrieb: > Bei einem der Konstruktoren kann man angeben ob er das tun soll. Danke das funktioniert zwar, aber anscheinend nur bei .NET 4.5. Markus Volz schrieb: > Warum lässt Du Dir vor dem Schließen des BinaryReaders nicht den > Buffer > des MemoryStream-Objekts geben, sei es über Read oder besser ToArray? An dieser Lösung gefällt mir nicht, dass kurzzeitig die Daten doppelt im Ram stehen, d.h. das Programm benötigt doppelt so viel Speicher. Und Große Wave-Dateien im Ram sind sowieso schon recht groß.
Man könnte sich vermutlich auch ne Klasse "FakeStream" oder so basteln, die intern auf dem echten Stream arbeitet, aber bei .Close() einfach nichts tut - und den FakeStream gibt man dann dem BinaryReader.
avr schrieb: > An dieser Lösung gefällt mir nicht, dass kurzzeitig die Daten doppelt im > Ram stehen, d.h. das Programm benötigt doppelt so viel Speicher. Hast du nachgeprüft, daß das MemoryStream-Objekt kopiert wird?
ich kenne jetzt nur Java und C# nicht besonders, aber sollte man nicht einfach mit newStream = new MemoryStream(oldStream.getBuffer()) sich ein 2. Memory Stream Objekt machen können, das das gleiche darunter liegende ByteArray benutzt. Dadurch dürfte eigentlich kein Speicher dupliziert werden wenn ich die Doku beim Überfliegen richtig verstanden habe. Nachtrag: Ich würde dann sogar soweit gehen und immer einen 2tes Streamobjekt auf den Buffer erzeugen das zum Lesen benutzt wird. So bleibt das Original das beim Konvertieren erzeugt wurde solange bestehen bis du es explizit wegwirfst.
:
Bearbeitet durch User
avr schrieb: > An dieser Lösung gefällt mir nicht, dass kurzzeitig die Daten doppelt im > Ram stehen, d.h. das Programm benötigt doppelt so viel Speicher. Und > Große Wave-Dateien im Ram sind sowieso schon recht groß. Für solche Infos gibt's die MSDN Doku. ;-) Dort steht ganz klar: GetBytes() liefert den über die Konstruktoren übergebenen bzw. den intern erzeugten Buffer falls keiner übergeben wurde. Dagegen liefert ToArray eine Kopie des Buffers. Bei GetBuffer ist allerdings das Problem, dass der dieser i.d.R. größer ist, als er Daten enthält. Das läßt sich aber durch die Properties Position bzw. Length lösen. Alle anderen Lösungen mit Stream offen halten usw. sind Krampf, da man bei IDisposable-Objekten (also u.a. bei Streams) unbedingt dafür Sorge tragen muss, dass diese ordnungsgemäß Disposed werden. Das geht idealerweise so:
1 | byte[] memoryBuffer; |
2 | long memoryBufferLength; |
3 | using (var memStream = new MemoryStream(...)) |
4 | {
|
5 | ...
|
6 | // irgendwas mit memStream veranstalten
|
7 | ...
|
8 | memoryBuffer = memStream.GetBiffer(); |
9 | memoryBufferLength = memStream.Position; // wenn Position am Ende des Stream ist! |
10 | }
|
11 | ...
|
12 | // hier kann man dann das Byte-Array weiterverarbeiten
|
13 | // und z.B. einen neuen MemoryStream erzeugen
|
14 | using(var memStream = new MemoryStream(memoryBuffer,0,memoryBufferLength)) |
15 | {
|
16 | ...
|
17 | }
|
Viel Erfolg! Markus
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.