Announcement

Collapse
No announcement yet.

Unicode-Text in eine Datei schreiben

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Unicode-Text in eine Datei schreiben

    Guten Abend Community


    Ich hab ein Problem zum Filestream.

    Ich besitze eine String mit lauter asiatschen Zeichen wie "晚上好社區". Dieser String kann bis zu 2000000 Zeichen lang sein. Damit das ein bisschen zügig vor sich geht, möchte ich über folgende Variante vorgehen. (siehe Code)

    Leider entspricht der Inhalt der Datei nicht meinem String. Ist es irgendwie möglich die erstellte Datei nicht unter ANSI sondern Unicode abzuspeichern, und wie müsste ich ms.Read(bytText, 0, blockSize)) umändern damit ich in der Datei auch die gleichen "Zeichen" vorfinde? Ich habe es bis jetzt einfach nicht hingekriegt. Vielleicht Streamwriter?


    Danke für die Hilfe.


    Freundliche Grüsse

    exc-jdbi


    [highlight=vbnet]
    Option Strict On
    Option Explicit On
    Imports System.IO

    Module Module1

    Sub Main()
    Dim txt As String = "晚上好社區"
    Dim filename As String = IO.Path.GetTempFileName
    If ToolsVaribles.WriteInFileUnicode(txt, filename) Then
    Stop
    End If
    End Sub

    End Module

    Public Class ToolsVaribles
    Public Shared Function WriteInFileUnicode(ByVal txt As String, ByVal fileName As String) As Boolean
    Dim numBytes As Integer = 0
    Dim bytText As Byte() = Nothing
    Const blockSize As Integer = 1024
    Dim ue As System.Text.UnicodeEncoding = Nothing
    WriteInFileUnicode = False
    Dim intL As Integer = txt.Length
    Try
    ue = New System.Text.UnicodeEncoding
    If File.Exists(fileName) Then
    File.Delete(fileName)
    Using ms As New MemoryStream
    Using bw As New BinaryWriter(ms, ue)
    bw.Write(txt)
    ms.Flush() : ms.Position = 0
    If ms.Length > 0 Then
    bytText = New Byte(blockSize - 1) {}
    Using fs As FileStream = File.OpenWrite(fileName)
    ms.Flush() : ms.Position = 0
    While (CheckValue(numBytes, ms.Read(bytText, 0, blockSize))) > 0
    fs.Write(bytText, 0, numBytes)
    End While
    fs.Flush()
    WriteInFileUnicode = True
    End Using
    End If
    End Using
    End Using
    End If
    Catch ex As Exception

    End Try
    End Function
    Private Shared Function CheckValue(Of T)(ByRef target As T, value As T) As T
    target = value
    Return value
    End Function
    End Class
    [/highlight]

  • #2
    Ja Streamwriter wäre auch meine Wahl. Öffne die Zieldatei mit einem Streamwriter und gib dem das gewünschte Encoding mit. Mit einer der Überladungen der Write Methoden kannst du dann einfach string(s) wegschreiben. Die landen dann schon richtig encodiert in der Datei. Bist du dir sicher das du UnicodeEncoding willst? Das entspricht utf-16. utf-8 wäre üblicher.

    Comment


    • #3
      Hallo Ralf Jansen

      Danke für die schnelle Antwort.

      Ich habe UnicodeEncoding gewählt, weil ich, wenn ich ehrlich sein soll keine Ahnung habe, was sonst noch für Zeichen im String sein könnten. Würdest du mir eher UTF16 empfehlen?

      Ich werde es heute Abend mit Streamwriter ausprobieren. Das Problem ist nur, es sollte wirklich so schnell wie auch nur möglich sein. Ist Vorgabe.

      Freundliche Grüsse

      exc-jdbi

      Comment


      • #4
        Ich habe UnicodeEncoding gewählt, weil ich, wenn ich ehrlich sein soll keine Ahnung habe, was sonst noch für Zeichen im String sein könnten.
        (Fast) Alle Zeichen sind in jedem Unicode Encoding darstellbar. Von daher wäre es egal was du nimmst. Du mußt dir die Datei nur dann halt auch im richtigen Encoding ansehen. Und utf-8 (ok utf-16 eigentlich auch) erkennen Editoren sehr gut.
        Was für ein Encoding hat den die Datenquelle? Wenn du das nicht weißt hast du eh kaum eine Chance es richtig zu machen.

        Comment


        • #5
          Hallo Ralf Jansen

          Hab nachgeschaut: Sowie ich ds erkennenkann ist die Datenquelle im Unicode (UnicodeEncoding). Wäre ich sicher auf der richtigen Seite


          Danke nochmals

          Comment


          • #6
            so ... hab es mit Streamwriter gemacht, und dann auch noch eine Schnelligkeitmessen dazugefügt. Für 100 Durchläufe werden bei mir 1.6 s benötigt.
            Mir würde dies reichen, jedoch frag ich mich, ob es noch schneller geht. Weiss vielleicht jemand eine bessere Variante oder Verbesserungsvorschläge.

            Danke und freundliche Grüsse

            exc-jdbi


            [highlight=vbnet]
            Option Strict On
            Option Explicit On
            Imports System.IO
            Imports System.Windows.Forms
            Imports System.Text


            Module Module1

            Sub Main()
            Dim txt As String = StringIncrease("晚上好社區", 400000)
            Dim filename As String = IO.Path.GetTempFileName
            Dim lstMessung As List(Of String) = Nothing
            Dim sw As System.Diagnostics.Stopwatch = Nothing
            Dim sw2 As System.Diagnostics.Stopwatch = Nothing

            Application.DoEvents()
            lstMessung = New List(Of String)()
            sw = New Stopwatch()
            sw2 = New Stopwatch()
            sw2.Start()
            For aa1 As Integer = 0 To 100
            sw.Start()
            If ToolsVaribles.WriteInFileUnicode2(txt, filename) Then
            lstMessung.Add(sw.ElapsedMilliseconds.ToString & "--WriteInFileUnicode " & aa1.ToString("00000"))
            sw.Reset()
            End If
            Next
            sw2.Stop()
            Stop
            End Sub
            Private Function StringIncrease(ByVal s As String, ByVal i As Integer) As String
            Dim sb As New StringBuilder
            For aa1 As Integer = 0 To i : sb.Append(s.Trim) : Next
            Return sb.ToString
            End Function
            End Module

            Public Class ToolsVaribles
            Public Shared Function WriteInFileUnicode2(ByVal txt As String, ByVal fileName As String) As Boolean
            WriteInFileUnicode2 = False
            Try
            Dim ue As New System.Text.UnicodeEncoding
            If File.Exists(fileName) Then
            File.Delete(fileName)
            Using sw As New StreamWriter(fileName, False, ue, 3 * 1024)
            sw.Write(txt)
            Return True
            End Using
            End If
            Catch ex As Exception

            End Try
            End Function
            End Class
            [/highlight]
            Zuletzt editiert von Exc-JDBI; 19.12.2013, 00:28. Reason: Fehler korrigiert

            Comment


            • #7
              Durch anders coden wird man da wohl nicht groß was an der Performance ändern können. Das Bewegung der Daten auf die Platte ist da der relevante Zeitfaktor.

              Aber wenn du schon weiß wie groß der string ist solltest du den Buffer auch so groß wählen. Hast du die 3K irgendwie geraten?
              Das neu erzeugen des Encodings missfällt mir. Die Encoding Klasse verwaltet wunderbar Instanzen für alle wichtigen Encodings. Wirf ue weg und gib da wo du ein Encoding brauchst einfach z.B Encoding.Unicode an.

              Der leere catch Block ist hoffentlich natürlich nur zu Testzwecken.

              Comment


              • #8
                Hallo Ralf Jansen

                Danke für die Ratschläge.

                Leider weiss ich die genaue Puffergrösse und die genaue Stringgrösse (die ist eh variablisch) nicht. Ich hab's nur angenommen. Den Catchblock werde ich noch ausfüllen.

                Freundliche Grüsse

                exc-jdbi

                Comment

                Working...
                X