Datentyp besser als List(of Byte)?

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Dodo.

    Datentyp besser als List(of Byte)?

    Moinsen,

    bei meiner HttpPostRequestLib ist mir eben ein Problem aufgefallen.
    Dort stelle ich den Content mittels einer List(Of Byte) zusammen, hierbei kommt natürlich auch die Datei mit hinein, sieht in etwa so aus

    VB.NET-Quellcode

    1. Dim bData As List(Of Byte)
    2. bData.AddRange(StringToByte("--" & Boundary))
    3. bData.AddRange(StringToByte("Content-Disposition: form-data; name=""" & sFile.VarName & """; filename=""" & sFile.Filename & """"))
    4. bData.AddRange(StringToByte("Content-Type: " & sFile.MIMEType))
    5. bData.AddRange(StringToByte("Content-Transfer-Encoding: binary"))
    6. bData.AddRange(StringToByte(""))
    7. bData.AddRange(sFile.Data) ' <---- hier das Problem
    8. bData.AddRange(StringToByte(""))


    Mit einer ~88Mb großen Datei funktioniert das noch, aber mit einer ~230Mb Datei nicht mehr, dann kommt OutOfMemory-Exception.
    Nun dachte ich ein Array zu nehmen, nur lässt sich das nicht so schön händeln wie eine Liste und mit ReDim möchte ich nur ungern arbeiten, zudem würde dies ziemlich kompliziert umzusetzten glaube ich.

    Nun wäre meine Frage ob es was besseres gibt als die Liste (außer Array)?
    Hi
    Recht viel anders dürfte es nicht gehen. Du kannst noch direkt über Memory arbeiten und durch geeignete Api-Aufrufe die Datei auslesen oder du musst fast mit Arrays arbeiten. Statt ReDim kann man auch Array.Resize verwenden. Geschickter wäre es allerdings, erst die Länge des Arrays zu berechnen und es dann zu füllen. Das sollte mit System.Text.Encoding.GetByteCount kein Problem sein und man kann bei einer der Überladungen von System.Text.Encoding.GetBytes auch direkt ins Array lesen.

    Gruß
    ~blaze~
    Das Problem mit der Berechnung ist eben folgendes.

    Der obere Code wird in einer Schleife aufgerufen und somit eben mehrere Dateien in den Content geladen. Die Länge der Dateien ist bekannt, das ist kein Problem, aber die Strings sind eben Variabel zum Teil und somit würde mir keine Möglichkeit einfallen die Vorher zu berechnen, mit der Encoding.GetBytes schaue ich mir mal an, hört sich prinzipiell so an was ich benötige.

    Edit:
    okay das mit den GetBytes() war erfolgreich, ich konnte mir da eine funktion zusammen wurschteln die das macht was ich brauche, falls jemand mal sowas bräuchte.

    VB.NET-Quellcode

    1. Private Function AddText(ByVal Text As String, ByRef bytes() As Byte, ByVal offset As Integer) As Integer
    2. Array.Resize(bytes, bytes.Length + Text.Length)
    3. Return System.Text.Encoding.UTF8.GetBytes(Text, 0, Text.Length, bytes, offset) + offset
    4. End Function
    5. Private Function AddBytes(ByVal data() As Byte, ByRef bytes() As Byte, ByVal offset As Integer) As Integer
    6. Array.Resize(bytes, bytes.Length + data.Length)
    7. For i As Integer = 0 To data.Length - 1
    8. bytes(offset + i) = data(i)
    9. Next
    10. Return bytes.Length
    11. End Function


    Damit kann ich automatisch Strings und ByteDaten zu einem Array hinzuaddieren.

    Edit2:
    Verdammt, auch beim Array kommt da eine OutOfMemory-Exception. Muss ich nun doch mal mit dem MemoryStream probieren -.-

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

    Also ein Problem ist, dass bei jedem Array.Resize der Speicherplatz vom Array neu angelegt werden muss und das Array weiterhin im Memory verfügbar ist. Also entweder das alte Array freigeben oder das Array bereits mit der benötigten Größe erstellen. Problematisch ist halt, dass zum Kopieren der alten Arraydaten auch das Array solange im Speicher bestehen muss. Werden die Daten nach und nach eingegeben? Dann könntest du die Daten erst abschließend in das Array schreiben. Du kannst ja den Dateistream schon mal öffnen und dann offen halten.

    Besser ist übrigens, die Anzahl der Bytes per Encoding.GetByteCount zu ermitteln, da nicht bei jedem Encoding die Bytezahl pro Buchstabe 1 beträgt.

    Gruß
    ~blaze~
    Nun, irgendwie liegt es an der großen Datei die reingeladen werden soll, aber hierzu mache ich noch einen anderen Thread auf, weil das im prinzip dann nichts hiermit zu tun hat.

    PS: selbiges Problem habe ich übrings mit den MemoryStream.
    gibts bei sonem Request-Dings nicht einen RequestStream?
    da müsste man doch endlos hineinschreiben können.

    Also ich kenne das nur vom (TCP-)NetworkStream - der hat keine Größenbeschränkung, denn wenn der interne Puffer die eingestellte Blockgröße erreicht, dann wird halt ein Paket abgeschickt.
    Also in einen Networkstream kannste unendlich .Write(byteArray) reinschreiben - von einem RequestStream erwarte ich eiglich dasselbe Verhalten - dafür sind Streams doch erfunden worden.
    Das Problem ist, dass ich die größe des Contents vorher wissen muss, damit ich sie im Header angeben kann und dann muss ja ERST der Header gesendet werden und erst danach der Content, deswegen muss ich den Content vorher vorbereiten und das bringt bei mir eben die Probleme mit sich wenn ich versuche den Content erstmal in ein Array zu schreiben.

    Ich habe mir jedoch nun was anderes überlegt, vlt. funktioniert das ja.

    Dodo schrieb:

    Das Problem ist, dass ich die größe des Contents vorher wissen muss

    ist das zwingend erforderlich oder ginge es zur not auch ohne? Bei meine FTP-Versuche fand ich immer die angabe ContentLength=-1 - daher vermute ich, es gibt auch FTP-Sender, die da einfach nix eintragen.