serialisieren einer Klasse mit Boolean(,)

  • VB.NET

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    serialisieren einer Klasse mit Boolean(,)

    Hallo!

    Hat zufällig jemand eine Seite/Tutorial wo ich mich in die Serialisation reinlesen kann?!?

    Ich möchte eine "List(of _FontCharDATA)" serialisieren, aber ich bekomme die Fehlermeldung "Der Typ ist nicht als serialisierbar gekennzeichnet"

    Geht das überhaupt mit nem BinaryFormatter?!?

    So sieht die Klasse aus:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class _FontCharDATA
    2. Private Shared __dats(,) As Boolean
    3. Public Shared Property _DATA As Boolean(,)
    4. Get
    5. Return __dats
    6. End Get
    7. Set(value As Boolean(,))
    8. __dats = value
    9. End Set
    10. End Property
    11. Private Shared __font As String
    12. Public Shared Property _FontName As String
    13. Get
    14. Return __font
    15. End Get
    16. Set(value As String)
    17. __font = value
    18. End Set
    19. End Property
    20. Private Shared __char As String
    21. Public Shared Property _Character As String
    22. Get
    23. Return __char
    24. End Get
    25. Set(value As String)
    26. __char = value
    27. End Set
    28. End Property
    29. Public Sub New(ByVal _font As String, ByVal _char As String, ByVal _data As Boolean(,))
    30. __font = _font
    31. __char = _char
    32. __dats = _data
    33. End Sub
    34. End Class
    OK, Danke! Keine Fehlermeldung mehr!

    Aber beim deserialisieren bekomme ich keine Ausgabe, also der Debugger läuft zwar für jeden Eintrag aber der Eintrag selbst ist leer!?

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Function SerializeBinary(ByVal obj As Object) As MemoryStream
    2. Dim serializer As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
    3. Dim memStrm As New MemoryStream
    4. serializer.Serialize(memStrm, obj)
    5. Dim file As New FileStream("file.bin", FileMode.Create, FileAccess.Write)
    6. memStrm.WriteTo(file)
    7. file.Close()
    8. memStrm.Close()
    9. Return memStrm
    10. End Function
    11. Private Function DeserializeBinary() As Object
    12. Dim file As New FileStream("file.bin", FileMode.Open, FileAccess.Read)
    13. Dim serializer As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
    14. Dim obj As Object = serializer.Deserialize(file)
    15. file.Close()
    16. Return obj
    17. End Function


    Sind die Funktionen OK?

    Edit: OK nun funzt alles!!
    ​Hatte allerdings vorher
    "Public Shared _FontCharDataList As New List(Of _FontCharDATA)"

    ​da hatte ich immer den selben Eintrag

    ​habs dann zu

    "Public Shared _FontCharDataList As New List(Of _FontCharDATA)()"

    geändert!
    Was bewirken die Klammern am Ende?!?

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

    Die Klammern sollten gar keinen Unterschied machen.
    In VB kann man leere Klammern oft weglassen. Beispiel:

    VB.NET-Quellcode

    1. Function GetRandomNumber() As Integer
    2. Return 4
    3. End Function
    4. Sub Test()
    5. Dim A As Integer
    6. 'Funktioniert wie erwartet:
    7. GetRandomNumber()
    8. A = GetRandomNumber()
    9. 'Hier kann man die Klammern weglassen:
    10. A = GetRandomNumber
    11. 'Hier aber nicht:
    12. GetRandomNumber 'Funktioniert nicht (die IDE fügt die Klammern automatisch ein)
    13. End Sub


    Gleich funktioniert es beim Aufruf eines Konstruktors:

    VB.NET-Quellcode

    1. Dim A As Object
    2. 'Funktioniert wie erwartet:
    3. A = New Object()
    4. 'Funktioniert auch:
    5. A = New Object


    Bei generischen Typen kommt halt eine Klammer (die mit "Of" drin) dazu. Aber der Rest bleibt gleich:

    VB.NET-Quellcode

    1. Dim A As List(Of Object)
    2. 'Funktioniert wie erwartet:
    3. A = New List(Of Object)()
    4. 'Funktioniert auch:
    5. A = New List(Of Object)


    Macht also keinen Unterschied.

    Aber!
    Das gilt nur für den Aufruf von Methoden/Konstruktoren. Bei der Deklaration von Typen sieht's anders aus:

    VB.NET-Quellcode

    1. Dim A As Object 'Nur ein einziges Objekt
    2. Dim B As Object() 'Ein Array von Objekten

    Hier macht die Klammer einen Unterschied. Gleiches Schema bei generischen Typen:

    VB.NET-Quellcode

    1. Dim A As List(Of Object) 'Nur eine einzige Liste
    2. Dim B As List(Of Object)() 'Ein Array von Listen


    Aber New Object ist immer nur ein einziges Object, egal ob mit oder ohne Klammern. Wenn man ein Array instanziieren will, muss man geschwungene Klammern dahinter schreiben, und da braucht man auch die runden Klammern:

    VB.NET-Quellcode

    1. Dim B1 As Object() = New Object() {} 'Ein (leeres) Array von Objekten
    2. Dim B2 As Object() = New Object(4 - 1) {} 'Ein Array von 4 Objekten
    3. Dim B3 As Object() = New Object() {New Object, New Object, New Object, New Object} 'Ein Array von 4 Objekten
    4. Dim B4 As List(Of Object)() = New List(Of Object)() {} 'Ein (leeres) Array von Listen
    5. Dim B5 As List(Of Object)() = New List(Of Object)(4 - 1) {} 'Ein Array von 4 Listen
    6. Dim B6 As List(Of Object)() = New List(Of Object)() {New List(Of Object), New List(Of Object), New List(Of Object), New List(Of Object)} 'Ein Array von 4 Listen



    (Beachte auch, dass Dim A As New Object die Kurzschreibweise von Dim A As Object = New Object ist.)
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    @Morrison Die Member Deiner Klasse sollten nicht Shared sein.
    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!
    @Niko Ortner:

    Aber wo ist der Unterschied?:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private __dats As Boolean(,)
    2. Private __dats(,) As Boolean


    oder:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Sub New(ByVal _data As Boolean(,))
    2. __dats = _data
    3. End Sub
    4. Public Sub New(ByVal _data(,) As Boolean)
    5. __dats = _data
    6. End Sub
    Bei den von Dir gezeigten Beispielen gibt es keinen Unterschied.
    Aber verwende ausschließlich die erste Variante, bei der die Klammern beim Typ stehen!
    VB erlaubt es bei Variablen, Feldern und Parametern (eventuell noch mehr) auch, die Klammern beim Namen der Variable, des Feldes bzw. des Parameters hinzuschreiben. Das ist verwirrend. Siehe dazu auch: Array von mehreren Buffern erstellen
    Macht man das bei Properties, fällt man auf die Nase:

    VB.NET-Quellcode

    1. Public ObjectField As Object 'Nur ein einziges Objekt
    2. Public ObjectArrayField1 As Object() 'Ein Array von Objekten
    3. Public ObjectArrayField2() As Object 'Ein Array von Objekten
    4. Sub Foo(ObjectParameter As Object, _ 'Ein einziges Objekt
    5. ObjectArrayParameter1 As Object(), _ 'Ein Array von Objekten
    6. ObjectArrayParameter2() As Object) 'Ein Array von Objekten
    7. Dim ObjectVariable As Object 'Nur ein einziges Objekt
    8. Dim ObjectVariableField1 As Object() 'Ein Array von Objekten
    9. Dim ObjectVariableField2() As Object 'Ein Array von Objekten
    10. End Sub
    11. 'ABER!
    12. Public Property ObjectProperty As Object 'Nur ein einziges Objekt
    13. Public Property ObjectArrayProperty1 As Object() 'Ein Array von Objekten
    14. Public Property NotAnObjectArrayProperty2() As Object 'NUR EIN EINZIGES OBJEKT!


    Denn man kann Properties Parameter geben. Beispiel:

    VB.NET-Quellcode

    1. Class ArrayList(
    2. Private Items As Object() = ...
    3. Public Default Property Item(Index) As Object
    4. Get
    5. Return Items(Index)
    6. End Get
    7. Set(value As Object)
    8. Items(Index) = value
    9. End Set
    10. End Property
    11. End Class
    12. 'Verwendung:
    13. Sub Test()
    14. Dim Stuff As New ArrayList
    15. Stuff.Add(...)
    16. 'Die 0 in den Klammern wird zum "Index" Parameter in der Property.
    17. Stuff.Items(0) = New Object
    18. Dim Foo = Stuff.Items(0)
    19. End Sub
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Mpf..
    ..ich bekomm nach dem deserialisieren immer das gleiche Zeichen ausgegeben, und beim serialisieren vom Byte() bekomm ich eine Fehlermeldung!

    ​Wenn ich vor dem serialisieren aus der Liste die Daten lese klappt es!

    Ich hab als Anhang mal das Projekt hochgeladen..
    ..vllt. erbarmt sich ja jemand und guckt mal rüber! :/
    Dateien
    Ich rate mal vom kurzen drauf schauen: Weißt du was Referenzen sind? Arrays sind immer Referenztypen, auch wenn nur Booleans drin stecken. Du weist jedem Objekt das selbe _colorDataArray Array zu, müsstest aber eigentlich mit new immer wieder ein neues erzeugen?
    @ErfinderDesRades: Da ist doch überall Option Strict On !!
    @Bluespide: Sowas ähnliches dachte ich mir auch, ich hab vor jeder Schleife " Array.Clear(_colorDataArray, 0, _colorDataArray.Length)​" stehen, reicht das nicht? Muss ich jedes mal ein neues Array generieren?

    ​Das Problem besteht halt darin das nach dem serialisieren die Array Daten alle gleich sind, bzw. gar nicht erst zu verwenden sind.
    ​Ich sammle einmal ein Byte() Array und einmal ein Boolean(,) Array..bei dem Boolean hab ich immer das selbe Bild als Ausgabe und aus dem Byte() lässt sich kein Bild machen, bekomme Fehlermeldung.
    Ich denke es wird da was falsch serialisiert!

    Morrison schrieb:

    @ErfinderDesRades: Da ist doch überall Option Strict On !!


    also inne Projekteinstelluingen isses Off



    Und nochmal meine Frage: Was muss ich tun mit deine Anwendung, um das Problem zu reproduzieren?

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

    Ähm, also nach dem Starten den "Get Data"-Button drücken..dann sammelt er sich für sämtliche Buchstaben von sämtlichen Schriftarten die Daten!
    Diese speichert er in die "file.bin" Datei.

    Danach den "Read Data"-Button und es kommt immer das gleiche Bild als Ausgabe.

    Wichtig wären dann noch die Funktionen:
    SerializeBinary
    DeserializeBinary
    der untere Teil von _getData
    und die <Serializable()>
    Public Class _FontCharDATA

    eig. sollte er in PicBox1 das Byte() Bild anzeigen und in PicBox2 des Boolean(,) Bild.

    Morrison schrieb:

    Danach den "Read Data"-Button und es kommt immer das gleiche Bild als Ausgabe.
    Ah - und das sei wohl nicht richtig.
    Ich hab aber noch ein weiteres Problem: Es gibt einen Laufzeitfehler, wenn ich "GetData" drücke.

    Als nächstes wäre noch interessant, worin die Ausgabe eiglich besteht - wie gesagt - ich komm ja nichtmal so weit.
    Bilder
    • Error.png

      52,18 kB, 864×426, 134 mal angesehen
    Hmm, meine Schriftarten unterstützen alle den Regular-Schnitt..
    ..dann einfach inn nen Try-Catch setzen, oder? :whistling:

    ​Hab mir die Schriftart eben runtergeladen und installiert..bei mir kommt keine Fehlermeldung! ?(

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

    Ja, ich lasse mir ja von den auf ein Bitmap gezeichneten Chars ein Array erstellen..dieses wollte ich speichern und später dann das Array wieder lesen und zu nem Bitmap formen!
    ​Also wäre die Ausgabe insg. zwei Bitmaps..eines vom Boolean(,) Array(schwarz/weiß) und eines vom Byte() Array (Original)..und die dazu gehörigen Bezeichnungen wie Font und Char.
    ​Wichtig ist mir aber nur des Boolean(,)-Array Image als Ausgabe!
    Wo und wie soll ich denn das Boolean(45,45) neu erstellen?

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Shared Sub _getData()
    2. Dim _fFont As Font = Nothing
    3. ' Dim _newRow As DataSet1.dtDatenRow = Nothing
    4. Dim _bmp As New Bitmap(45, 45)
    5. Dim _grey_bmp As UnmanagedImage
    6. Dim blobCounter As New BlobCounter()
    7. Dim rects() As Rectangle
    8. Dim _grey_Filter As New Grayscale(0.2125, 0.7154, 0.0721)
    9. Dim _invert_Filter As New Invert()
    10. Dim thresholdFilter As New Threshold(120)
    11. Dim _unmanagedImage As UnmanagedImage = Nothing
    12. Dim _blobs() As Blob
    13. Dim _active As New List(Of IntPoint)
    14. Dim _left As Integer = 45
    15. Dim _right As Integer = 0
    16. Dim _top As Integer = 45
    17. Dim _bottom As Integer = 0
    18. Dim _width As Integer = 0
    19. Dim _height As Integer = 0
    20. Dim _rect As Rectangle = Nothing
    21. Dim _mycolor As Color = Nothing
    22. Dim ret As Integer = 0
    23. ' Dim _colorDataArray(45, 45) As Boolean
    24. blobCounter.MinHeight = 1
    25. blobCounter.MinWidth = 1
    26. blobCounter.CoupledSizeFiltering = True
    27. blobCounter.FilterBlobs = True
    28. blobCounter.ObjectsOrder = ObjectsOrder.Size
    29. ' Each Font
    30. For Each _font As ListViewItem In Form1.lvFonts.Items
    31. ' Set new Font
    32. _fFont = New Font(_font.Text, 24, FontStyle.Regular)
    33. LV_SelectFocus(Form1.lvFonts, Form1.lvFonts.FindItemWithText(_fFont.Name).Index)
    34. For Each _chr As String In _string
    35. Application.DoEvents()
    36. ' draw Character on Bitmap
    37. _Graphics._draw(_bmp, _chr, _fFont)
    38. _grey_bmp = UnmanagedImage.FromManagedImage(_bmp)
    39. ' use Filters
    40. _unmanagedImage = UnmanagedImage.FromManagedImage(_grey_Filter.Apply(_bmp))
    41. thresholdFilter.ApplyInPlace(_unmanagedImage)
    42. _invert_Filter.ApplyInPlace(_unmanagedImage)
    43. blobCounter = New BlobCounter(_unmanagedImage)
    44. blobCounter.ProcessImage(_unmanagedImage)
    45. rects = blobCounter.GetObjectsRectangles()
    46. _blobs = blobCounter.GetObjectsInformation()
    47. _active = _unmanagedImage.CollectActivePixels()
    48. ' get enclosing Rectangle
    49. _left = 45
    50. _right = 0
    51. _top = 45
    52. _bottom = 0
    53. _width = 0
    54. _height = 0
    55. For Each _point As IntPoint In _active
    56. If _point.X < _left Then
    57. _left = _point.X
    58. End If
    59. If _point.X > _right Then
    60. _right = _point.X
    61. End If
    62. If _point.Y < _top Then
    63. _top = _point.Y
    64. End If
    65. If _point.Y > _bottom Then
    66. _bottom = _point.Y
    67. End If
    68. Next
    69. _rect = New Rectangle(_left - 1, _top - 1, (_right + 3) - _left, (_bottom + 3) - _top)
    70. ' get boolean Array
    71. 'Array.Clear(_colorDataArray, 0, _colorDataArray.Length)
    72. Dim _colorDataArray(45, 45) As Boolean
    73. For x As Integer = 0 To _unmanagedImage.Width - 1
    74. For y As Integer = 0 To _unmanagedImage.Height - 1
    75. _mycolor = _unmanagedImage.GetPixel(x, y)
    76. ' Transform RGB color space to Y (gray scale)
    77. ret = CInt((_mycolor.R * 0.299 + _mycolor.G * 0.578 + _mycolor.B * 0.114))
    78. If ret > 120 Then
    79. _colorDataArray(x, y) = False
    80. '_unmanagedImage.SetPixel(x, y, Color.White)
    81. Else
    82. _colorDataArray(x, y) = True
    83. '_unmanagedImage.SetPixel(x, y, Color.Black)
    84. End If
    85. Next
    86. Next
    87. ' add new FontCharData entry to List
    88. ' _lFontCharData.Add(New _FontCharDATA(_fFont.Name, _chr, _rect, BmpToArray(_bmp), _colorDataArray))
    89. _lFontCharData.Add(New _FontCharDATA(_fFont.Name, _chr, _rect, _colorDataArray))
    90. Next
    91. Next
    92. ' Liste serialisieren
    93. SerializeBinary(_lFontCharData)
    94. End Sub

    VB.NET-Quellcode

    1. 'Array.Clear(_colorDataArray, 0, _colorDataArray.Length)
    2. ReDim _colorDataArray(45, 45)
    Aber insges. recht schlimm, wie ineffizient das geproggt ist.
    Auf meim System entstehen 10350 _FontCharDATA- Objekte, jedes mit einer Bitmap und einem 2116 grossen Bool-Array.

    Das sind ca. 10350 * ((2116 * 4) + 2025) Bytes = 108 MB im Speicher - für was?

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