Convert MemoryStream to MemoryStream()

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Convert MemoryStream to MemoryStream()

    Hallo,

    der Code unten führt zum Fehler. Der Compiler will anscheinend ein Array, aber ich bekomms einfach nicht hin. Vielen Dank fürs helfen! :)

    VB.NET-Quellcode

    1. Public Sub Main()
    2. Dim objIOStream As New IO.MemoryStream
    3. Dim generator As New MyGenerator(objIOStream)
    4. generator.Appendo(Of IO.MemoryStream)(objIOStream) 'Der Wert vom Typ "MemoryStream" kann nicht in "MemoryStream()" konvertiert werden
    5. End Sub
    6. Public Class MyGenerator
    7. Public Sub Appendo(Of T)(ByVal elongations() As T)
    8. Dim vtSize As Integer = Runtime.InteropServices.Marshal.SizeOf(tp)
    9. End Sub
    10. Public Sub New(ByVal destination As IO.Stream)
    11. '...
    12. End Sub
    13. End Class

    @vb.net_New Willkommen im Forum. :thumbup:
    Das eine ist ein MemoryStream, das andere ist ein Array von MemoryStreams.
    Aus

    VB.NET-Quellcode

    1. Public Sub Appendo(Of T)(ByVal elongations() As T)
    machst Du

    VB.NET-Quellcode

    1. Public Sub Appendo(Of T)(ByVal elongations As T)
    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!
    Hallo RodFromGermany,

    leider ist die Appendo-Methode deutlich größer und umbauen will ich eigentlich vermeiden, wenn es möglich ist als Array zu übergeben.

    Ein Versuch meinerseits war:

    VB.NET-Quellcode

    1. generator.Appendo(Of MemoryStream)(New MemoryStream() {objStream})


    Eigentlicher Code der Appendo-Methode:

    VB.NET-Quellcode

    1. Public Sub Appendo(Of T)(ByVal elongations() As T)
    2. Dim tp As Type = GetType(T) 'Typ der Arrayelemente
    3. Dim vtSize As Integer = Runtime.InteropServices.Marshal.SizeOf(tp) 'Groesse eines Wertetyps
    4. Dim attributes() As Runtime.InteropServices.StructLayoutAttribute = DirectCast(tp.GetCustomAttributes(GetType(Runtime.InteropServices.StructLayoutAttribute), False), Runtime.InteropServices.StructLayoutAttribute())
    5. If Not tp.IsValueType AndAlso (attributes.Length <> 1 OrElse attributes(0).Value = Runtime.InteropServices.LayoutKind.Auto) Then
    6. 'Layout von T muss klar definiert sein, bzw. T muss ein Wertetyp sein
    7. Throw New ArgumentException("T is not a value type or its System.Runtime.InteropServices.StructLayoutAttribute is not specified in a correct way. System.Runtime.InteropServices.StructLayoutAttribute.Value mustnot be System.Runtime.InteropServices.LayoutKind.Auto.")
    8. Else
    9. If rwfcsChunkSettings.BitsPerSample = vtSize * 8 Then
    10. Dim dataPos As Long = strmStream.Position
    11. Dim data(Buffer.ByteLength(elongations) - 1) As Byte
    12. 'Inhalt aus Elongations in data kopieren, Achtung: keine Arraylaenge ueber Int32.MaxValue moeglich, da
    13. 'System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement keine Int64 als Parameter unterstuetzt
    14. For i As Integer = 0I To elongations.Length - 1I
    15. Runtime.InteropServices.Marshal.Copy(Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(elongations, i), data, vtSize * i, vtSize)
    16. Next
    17. 'Laengen updaten
    18. strmStream.Seek(lngLengthOffset, IO.SeekOrigin.Begin)
    19. bwWriter.Write(intCurrentLength + data.Length + 32I)
    20. strmStream.Seek(lngDataLengthOffset, IO.SeekOrigin.Begin)
    21. bwWriter.Write(intCurrentLength + data.Length)
    22. 'Daten schreiben
    23. strmStream.Seek(dataPos, IO.SeekOrigin.Begin)
    24. bwWriter.Write(data)
    25. Else
    26. Throw New FormatException(String.Format("The current sound generator does not support elongations of the type {0}.", tp.FullName))
    27. End If
    28. End If
    29. End Sub
    Hallo

    Ich denke eher so:

    VB.NET-Quellcode

    1. generator.Appendo(Of MemoryStream)(New MemoryStream() From {objStream})


    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Vielen Dank den Tipp - Samlungsinitalisierer kannte ich noch nicht.

    Leider, aber meldet der Compiler: "Der Typ "MemoryStream" kann nicht mit einem Sammlungsinitialisierer initialisiert werden, weil es sich nicht um einen Sammlungstyp handelt."
    Oh

    Bei mir kompiliert das hier, geht aber sicher besser auch:

    VB.NET-Quellcode

    1. generator.Appendo(Of MemoryStream)(New List(Of MemoryStream) From {New MemoryStream}.ToArray)

    oder auch

    VB.NET-Quellcode

    1. generator.Appendo(New List(Of MemoryStream) From {New MemoryStream}.ToArray)


    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Der Code funktioniert bei der Übergabe. Danke für die Hilfe!

    Eine weitergehende Frage (ggf. mache ich auch gerne einen eigenen Thread auf) habe ich noch: Wieso kann ein MemoryStream nicht gemarshallt werden?

    Fehler wirft:

    VB.NET-Quellcode

    1. Dim vtSize As Integer = Runtime.InteropServices.Marshal.SizeOf(tp)


    Unbehandelte Ausnahme: System.ArgumentException: Es kann keine sinnvolle Größe oder sinnvoller Offset berechnet werden, da der Typ "System.IO.MemoryStream" nicht als nicht verwaltete Struktur gemarshallt werden kann.
    bei System.Runtime.InteropServices.Marshal.SizeOfHelper(Type t, Boolean throwIfNotMarshalable)
    bei System.Runtime.InteropServices.Marshal.SizeOf(Type t)
    bei TidyUp.SoundGenerator.Appendo[T](T[] elongations) in C:\tidyup\TidyUp\TidyUp\Sgen.vb:Zeile 84.
    bei TidyUp.Form1.createStream() in C:\tidyup\TidyUp\TidyUp\Form1.vb:Zeile 37.
    bei TidyUp.Form1.Form1_Load(Object sender, EventArgs e) in C:\tidyup\TidyUp\TidyUp\Form1.vb:Zeile 26.
    bei System.EventHandler.Invoke(Object sender, EventArgs e)
    bei System.Windows.Forms.Form.OnLoad(EventArgs e)
    bei System.Windows.Forms.Form.OnCreateControl()
    bei System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
    bei System.Windows.Forms.Control.CreateControl()
    bei System.Windows.Forms.Control.WmShowWindow(Message& m)
    bei System.Windows.Forms.Control.WndProc(Message& m)
    bei System.Windows.Forms.ScrollableControl.WndProc(Message& m)
    bei System.Windows.Forms.ContainerControl.WndProc(Message& m)
    bei System.Windows.Forms.Form.WmShowWindow(Message& m)
    bei System.Windows.Forms.Form.WndProc(Message& m)
    bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    Hmm - dein Aufruf aus post#3 ist eiglich richtig, könnte man nur noch vereinfachen:

    VB.NET-Quellcode

    1. generator.Appendo({objStream})
    Das müsste kompilieren.
    Wenn du dann noch weitere Fehler bekommst, liegt das zumindest nicht an der Aufrufe-Konvention.



    Na, wenn MemoryStream nicht gemarshalt wern kann, dann ist das wohl so.
    Runtime.InteropServices.Marshal.SizeOf(tp) ist eiglich eine Methode, die von primitiven Strukturen mit fester Größe diese Größe eben angibt.
    Ein MemoryStream hat aber keine feste Größe, sondern ist immer etwas größer als die Summe all dessen, was hineingeschrieben wurde.

    Die Größe eines Streams ruft man üblicherweise über die .Length-Property ab.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()