Image zu String, auch für andere (beliebige) Dateien ?

  • VB.NET

Es gibt 41 Antworten in diesem Thema. Der letzte Beitrag () ist von asusdk.

    Image zu String, auch für andere (beliebige) Dateien ?

    Heyho an alle,

    ich hab die durchaus sehr interessante Klasse gefunden mit der es möglich ist Bilder zu einem String und zurück zu convertieren:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class ConvertImage
    2. Public Function ConvertImageToString(ByVal Path As String) As String
    3. Dim Result As String = String.Empty
    4. Try
    5. If IO.File.Exists(Path) Then
    6. Dim img As Image = Image.FromFile(Path)
    7. Using ms As MemoryStream = New MemoryStream
    8. img.Save(ms, img.RawFormat)
    9. Dim Bytes() As Byte = ms.ToArray()
    10. Result = Convert.ToBase64String(Bytes)
    11. End Using
    12. Else
    13. Result = String.Empty
    14. End If
    15. Catch ex As Exception
    16. MessageBox.Show(ex.Message(), "Info")
    17. End Try
    18. Return Result
    19. End Function
    20. Public Function ConvertStringToImage(ByVal Base64String As String) As Image
    21. Dim img As Image = Nothing
    22. Try
    23. Dim Bytes() As Byte = Convert.FromBase64String(Base64String)
    24. img = Image.FromStream(New MemoryStream(Bytes))
    25. Catch ex As Exception
    26. MessageBox.Show(ex.Message(), "Info")
    27. End Try
    28. Return img
    29. End Function
    30. End Class


    jetzt frage ich mich natürlich ob man das so abändern könnte das es für EGAL welche Datei funktioniert. Ich weiss dank meiner bisherigen recherchen, das die meisten auf dem Standpunkt sind, das es doch egal sei und man sollte zu seinem Programm einfach alle benötigten Dateien mitliefern, aber ich habe mit dem Programmieren angefangen mit der Scriptsprache AutoIT, dort konnte man beliebige Dateien in die .exe mit einbinden und das vermisse ich ehrlich gesagt extrem !

    Sämtliche bisher gefundenen und auch ausprobierten Methoden dies zu erreichen sind bisher unzulänglich, daher eben die frage ob man die Umwandlung zu einem String hier nicht eben für ALLE Dateitypen verwenden könnte ?

    Besten Dank im voraus, Greets
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    ja - mit Base64-Codierung kann man aus jederlei Datei einen String machen und zurück (eine Klasse braucht man dafür übrigens nicht - da reichen auch Shared Functions für).
    Vorteil: ist ein String (für den, dens freut)
    Nachteil: 1/3 höherer Platzbedarf, als wenn man die Bytes Bytes sein liesse.
    nochn Nachteil: Ein String lässt sich nicht als Stream verarbeiten, also so ab um 1MB scheint mir das nicht mehr fein.
    @ErfinderDesRades Danke schon einmal für deine schnelle Antwort, könntest du meinem noch nicht so fortgeschrittenem Hirn ein wenig auf die Sprünge helfen ? =)

    wie ich das bewerkstelligen könnte ? denn wenn ich z.b. mal zum testen versucht habe bei der Function "ConvertStringToImage" mal das "As Image" versuchshalber zu "As File" gewandelt habe meckert VS natürlich rum..
    und die Googlesuche nach "vb.net beliebige datei zu string" (oder von String zu Datei), liefert mir leider kein verwendbares Ergebnis.

    Oder natürlich auch gerne die bytes methode wenn du da evtl. einen Link hättest ^^

    Edit: im Prinzip suche ich etwas in der Art: AutoIT-Funktion-FileInstall
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „asusdk“ ()

    Hi
    die allgemeine Vorgehensweise wäre, Daten als Bytes zu lesen und anschließend zu konvertieren. Convert.ToBase64String verwendest du ja bereits im von dir geposteten Teil.
    Wenn du die Daten nicht strikt in einen String einbauen musst, würde ich empfehlen, sie in Form von Bytes zu behalten, ein String dient idR. als Text, d.h. er soll von Menschen gelesen werden.

    Viele Grüße
    ~blaze~
    @~blaze~ hast du denn evtl. ein tutorial oder dergleichen welches ich mir ansehen könnte wie das geht als bytes, und wie speichere ich diese denn dann ab ? kann man in den my.settings das ganze denn als bytes abspeichern ?
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    also einen FileStream kannste ja so in ein Byte-Array einlesen/umwandeln:

    VB.NET-Quellcode

    1. Public Shared Function ReadAllBytes(path As String) As Byte()
    2. Using fs = New IO.FileStream(path, IO.FileMode.Open)
    3. Dim length = CInt(fs.Length)
    4. Dim bytes(length - 1) As Byte
    5. fs.Read(bytes, 0, length)
    6. Return bytes
    7. End Using
    8. End Function

    Und die Convert.ToBase64String(Bytes)-Funktion kennste jetzt ja schon, die kann das Byte() in einen String wandeln.
    Probierma, die Umkehrung dieses Vorgangs mit deim Hirn selber hinzukriegen ;)

    Jo - und mitte Settings haste recht - das ist vlt. wirklich nützlich, weil von Haus aus bieten Settings den Byte()-Datentyp ja nicht an - wohl aber String.
    @ErfinderDesRades Danke dir für den Tipp, werd ich mir gleich mal ansehen, falls es für jemanden relevant ist habe ich aktuell eine gute Möglichkeit gefunden/zusammengeschustert die die Dateien als String sogar noch kleiner abspeichert als die Datei selbst ist

    Die gewählte Date (.exe) hat Standardmäßig: 1,10 MB (1.159.168 Bytes)
    eine .txt mit einem nicht komprimierten base64String: 1,47 MB (1.544.192 Bytes)
    die .txt mit dem komprimierten String: 328 KB (335.872 Bytes)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class ConvertImage
    2. Public Function ConvertFileToCompressedBase64(ByVal FilePathAndName As String) As String
    3. Dim text As String = Convert.ToBase64String(IO.File.ReadAllBytes(FilePathAndName))
    4. Dim buffer() As Byte = Encoding.UTF8.GetBytes(text)
    5. Dim memoryStream = New MemoryStream()
    6. Using gZipStream = New GZipStream(memoryStream, CompressionMode.Compress, True)
    7. gZipStream.Write(buffer, 0, buffer.Length)
    8. End Using
    9. memoryStream.Position = 0
    10. Dim compressedData = New Byte(CInt(memoryStream.Length - 1)) {}
    11. memoryStream.Read(compressedData, 0, compressedData.Length)
    12. Dim gZipBuffer = New Byte(compressedData.Length + 4 - 1) {}
    13. System.Buffer.BlockCopy(compressedData, 0, gZipBuffer, 4, compressedData.Length)
    14. System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gZipBuffer, 0, 4)
    15. Return Convert.ToBase64String(gZipBuffer)
    16. End Function
    17. Public Sub WriteCompressedFile(ByVal CompressedBase64String As String, ByVal FilePathAndName As String)
    18. Dim gZipBuffer() As Byte = Convert.FromBase64String(CompressedBase64String)
    19. Using memoryStream = New MemoryStream()
    20. Dim dataLength As Integer = BitConverter.ToInt32(gZipBuffer, 0)
    21. memoryStream.Write(gZipBuffer, 4, gZipBuffer.Length - 4)
    22. Dim buffer = New Byte(dataLength - 1) {}
    23. memoryStream.Position = 0
    24. Using gZipStream = New GZipStream(memoryStream, CompressionMode.Decompress)
    25. gZipStream.Read(buffer, 0, buffer.Length)
    26. End Using
    27. Dim binaryData() As Byte = Convert.FromBase64String(Encoding.UTF8.GetString(buffer))
    28. Dim fs As New FileStream(FilePathAndName, FileMode.CreateNew)
    29. fs.Write(binaryData, 0, binaryData.Length)
    30. fs.Close()
    31. MessageBox.Show("File restored", "Info")
    32. End Using
    33. End Sub
    34. End Class


    Edit: hm, schade die Compression scheint sich nur bei sehr kleinen Dateien als effektiv zu erweisen, und um eine einzelne Datei mit 75 MB (welche danach 100 hat...) umzuwandeln werden mal schnell 2 GB Ram besetzt 8|
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    Vereinfachung:

    VB.NET-Quellcode

    1. Public Function ConvertFileToCompressedBase64(ByVal FilePathAndName As String) As String
    2. Using fs = New FileStream(FilePathAndName, FileMode.Open), gZipStream = New GZipStream(fs, CompressionMode.Compress), ms = New MemoryStream()
    3. gZipStream.CopyTo(ms)
    4. Return Convert.ToBase64String(ms.ToArray)
    5. End Using
    6. End Function
    (ungetestet)
    Bin etwas unsicher, evtl. musses auch so:

    VB.NET-Quellcode

    1. Public Shared Function ConvertFileToCompressedBase64(ByVal FilePathAndName As String) As String
    2. Using ms = New MemoryStream()
    3. Using fs = New FileStream(FilePathAndName, FileMode.Open), gZipStream = New GZipStream(fs, CompressionMode.Compress)
    4. gZipStream.CopyTo(ms)
    5. End Using
    6. Return Convert.ToBase64String(ms.ToArray)
    7. End Using
    8. End Function
    siehe auch Streams
    ich bin auf der Seite mit dem Tut, muss aber ehrlich gestehen das ich dennoch nicht verstehe was genau du meinst, ich sehe nicht mal ein Beispiel auf der Tutorial Seite das dem Code ähnelt, da verwendest du nirgends "gzipstream.Copyto()"
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    so, hab ich ausprobieren müssen - GzipStream kann zum Dekomprimieren nicht schreiben - nur lesen - sagt der ObjectBrowser, also so:

    VB.NET-Quellcode

    1. Public Shared Function ReadFileToCompressedBase64(ByVal pth As String) As String
    2. Dim ms = New MemoryStream()
    3. Using fs = New FileStream(pth, FileMode.Open), zipper = New GZipStream(ms, CompressionMode.Compress)
    4. fs.CopyTo(zipper)
    5. End Using
    6. Return Convert.ToBase64String(ms.ToArray)
    7. End Function
    8. Public Shared Sub WriteFileFromCompressedBase64(ByVal s64 As String, ByVal pth As String)
    9. Using ms = New MemoryStream(Convert.FromBase64String(s64)), unzipper = New GZipStream(ms, CompressionMode.Decompress), fs = New FileStream(pth, FileMode.Create)
    10. unzipper.CopyTo(fs)
    11. End Using
    12. MessageBox.Show("File restored", "Info")
    13. End Sub
    Aber wie gesagt: Ausser um eine Datei in die Settings zu schieben wüsste ich nicht recht, wozu das gut sein soll.
    Etwa zur Datei-Übertragung muss man dann üblicherweise den Base64String wieder in Bytes wandeln, und da hätte man die Bytes auch gleich Bytes lassen können, oder sogar Stream - das wäre resourcentechnisch das Optimale.

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

    Um für große Dateien effizienter zu sein:
    MemoryStream mit capacity von FS.length initialisieren.
    MemoryStream.GetBuffer verwenden.
    Noch optimaler(AVG)
    MemoryStream capacity initialisieren bei der man davon ausgeht, dass sie größer als die Datei ist. Dann ebenfalls MemoryStream.GetBuffer verwenden, jedoch von Concert.ToBase64 offset von 0 und count von memorystream.length

    Aber abgesehen davon sind die settings wirklich nicht für byte Daten geschweige denn große Datenmengen gedacht. Dafür legt man ganz normal und binär Dateien an
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @ErfinderDesRades Super, genial, so läuft es echt einwandfrei, und die 1.10 MB Datei hat danach schon mal nur 220 kB
    (hab den Memory Stream auch gleich in den Using Block eingebaut, aber davor 1zu1 mit deiner Methode getestet, Danke dir sehr dafür ) :

    VB.NET-Quellcode

    1. Using fs = New FileStream(FilePathAndName, FileMode.Open), ms = New MemoryStream(), zipper = New GZipStream(ms, CompressionMode.Compress)
    2. fs.CopyTo(zipper)
    3. Return Convert.ToBase64String(ms.ToArray)
    4. End Using



    @jvbsl hm, also entweder ich verstehe was an deiner Aussage falsch, oder bei kleinen Dateien erreicht man damit das gegentaeil, hab mal versucht die memoryStream Größe auf die Filestream Größe festzulegen:

    VB.NET-Quellcode

    1. Using fs = New FileStream(FilePathAndName, FileMode.Open), ms = New MemoryStream(New Byte(CInt(fs.Length - 1)) {}), zipper = New GZipStream(ms, CompressionMode.Compress)
    2. fs.CopyTo(zipper)
    3. Return Convert.ToBase64String(ms.ToArray)
    4. End Using


    resultat dabei ist das die 1,10 Mb Datei als String dann sage und schreibe 1,47 Mb hat 8|
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Mein Fehler, wenn du Komprimierung verwendest, dann geht dieser Ansatz nicht, da müsstest du eher den zweiten Ansatz verfolgen(evtl. auch den kombinierten, ist zwar etwas langsamer - sollte immernoch schneller sein als das ganz ursprüngliche, aber dann hast ne Größen Abschätzung).

    Aber wie gesagt

    jvbsl schrieb:

    Aber abgesehen davon sind die settings wirklich nicht für byte Daten geschweige denn große Datenmengen gedacht. Dafür legt man ganz normal und binär Dateien an

    Gilt nach wie vor, ich halte das bei solchen größen für mehr als Unsinn voll.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @ErfinderDesRades
    Aber wie gesagt: Ausser um eine Datei in die Settings zu schieben wüsste ich nicht recht, wozu das gut sein soll.

    @jvbsl

    Ja, wirklich zu 100 Sinnvoll ist es definitiv nicht, aber es gibt einem z.B. die Option das der User evtl. die Möglichkeit bekommt in ein fertiges Programm noch extra Daten einzubauen, ohne das dies neu kompiliert werden muss, es geht aktuell ja nicht darum das ich einen Grund habe dies so zu nutzen in einem Programm, ich möchte einfach nur die diesbezüglichen Möglichkeiten einmal ausprobieren ^^

    das was ich aktuell als am problematischten bei diesem versuch halte ist der Ram-Verbrauch, bei einer 75 MB Datei werden mal schnell 2 GB an Ram verbraten, und auch nach fertiger ausführung leert sich der Ram nicht mehr... (obwohl ich alle streams danach Flushe und dispose)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Dim str As String = ""
    2. Using fs = New FileStream(FilePathAndName, FileMode.Open), ms = New MemoryStream(), zipper = New GZipStream(ms, CompressionMode.Compress)
    3. fs.CopyTo(zipper)
    4. str = Convert.ToBase64String(ms.ToArray)
    5. zipper.Flush()
    6. fs.Flush()
    7. ms.Flush()
    8. zipper.Dispose()
    9. fs.Dispose()
    10. ms.Dispose()
    11. Return str
    12. str = ""
    13. End Using

    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    social.msdn.microsoft.com/Foru…tored?forum=csharpgeneral
    <Profile Directory>\<Company Name>\<App Name>_<Evidence Type>_<Evidence Hash>\<Version>\user.config


    Edit: sorry falsche Settings:
    stackoverflow.com/questions/98…s-settings-default-stored
    %userprofile%\appdata\local or %userprofile%\Local Settings\Application Data

    Das wird also auch einfach nur als Datei auf dem Rechner gespeichert und nicht in die Anwendung eingebaut. Verschiebt man die Anwendung auf nen anderen Rechner sind die in den Settings gespeicherten Daten auf dem anderen Rechner auch nicht vorhanden.^^

    Edit: Zum ram:

    VB.NET-Quellcode

    1. Convert.ToBase64String(ms.GetBuffer(),0,ms.Length)

    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    asusdk schrieb:

    (hab den Memory Stream auch gleich in den Using Block eingebaut, aber davor 1zu1 mit deiner Methode getestet, Danke dir sehr dafür )
    Ich habs jetzt gegengetestet, und es ergeben sich Unterschiede.
    TestCode:

    VB.NET-Quellcode

    1. Public Shared Function ReadFileToCompressedBase64(ByVal pth As String) As String
    2. Dim ms = New MemoryStream()
    3. Using fs = New FileStream(pth, FileMode.Open), zipper = New GZipStream(ms, CompressionMode.Compress)
    4. fs.CopyTo(zipper)
    5. End Using
    6. Return Convert.ToBase64String(ms.ToArray)
    7. End Function
    8. Public Shared Function ReadFileToCompressedBase64_2(ByVal pth As String) As String
    9. Using fs = New FileStream(pth, FileMode.Open), ms = New MemoryStream(), zipper = New GZipStream(ms, CompressionMode.Compress)
    10. fs.CopyTo(zipper)
    11. Return Convert.ToBase64String(ms.ToArray)
    12. End Using
    13. End Function
    14. '-------
    15. Dim fi = New FileInfo("Test.doc")
    16. Dim s = ReadFileToCompressedBase64(fi.FullName)
    17. Dim b = s = ReadFileToCompressedBase64_2(fi.FullName) ' Haltepunkt ergibt: b = False

    Das steht auch im Tut, dass zipStreams (übrigens Crypto - auch, etc.) disposed oder geflusht werden müssen, damit sie auch den letzten DatenBlock in die Ausgabe schreiben.