解码Base64字符串时无法将“ñ”字符打印到文件

时间:2013-09-20 09:36:24

标签: .net vb.net encoding character-encoding base64

我正在尝试制作一个CLI应用来保护/取消保护文本文档, 我所做的是简单的2次Base64编码/解码。

当我尝试将包含特殊字符的文档编码为“ñ”“ç”或“áéíóúàèìòùäëïöü,文档采用ANSI编码,然后当我解码之前编码的base64字符串时,我得到一个”? “字符而不是原始的”ñ“字符或其他拉丁字符。

我使用默认的ANSI编码来获取字节字符并写入文本文件,我不明白为什么我遇到麻烦因为如果我尝试编码/解码msgbox中的“ñ”字符只是为了测试然后解码的base64字符串被打印为“ñ”字符好,可能问题是在“List(Of String)”对象中可能存储坏的解码字符串?

我如何解决这个问题并使其更适用于角色类型?

这是VS2012中针对FW 4.0编写的完整源代码:

Module Main

#Region " Variables "

    ' Stores the file information
    Dim INFO As IO.FileInfo

    ' Stores the TextFile Content
    Private Content As String()

    ' Stores the Result Text
    Private Result As New List(Of String)

    ' Error messages
    Private ErrorMessages As New Dictionary(Of Integer, String) From { _
        {1, "Insuficient arguments"}, _
        {2, "Too many arguments"}, _
        {3, "File does not exist"}, _
        {4, "Unrecognized parametter. Valid parametters are: /P, /Protect, /U, /Unprotect"}}

    Dim Logo As String = <a><![CDATA[
 D""""""'DDD          CC'""""'cCC                              dP   
 D  dddd. `D          C' .ccc. `C                              88   
 D  DDDDD  D .d8888b. C  CCCCCccC 88d888b. dP    dP 88d888b. d8888P 
 D  DDDDD  D 88'  `88 C  CCCCCccC 88'  `88 88    88 88'  `88   88   
 D  dddd' .D 88.  .88 C. `ccc' .C 88       88.  .88 88.  .88   88   
 D       .DD `88888P' CC.     .dC dP       `8888P88 88Y888P'   dP   
 DDDDDDDDDDD          CCCCCCCCCCC               .88 88              
                                            d8888P  dP             
 By Elektro H@cker
]]></a>.Value



    Dim Syntax As String = <a><![CDATA[   

[+] Syntax:

    DoCrypt.exe [Switch] [TextFile]


[+] Switches:

    /P (or) /Protect   | Protect text file.
    /U (or) /Unprotect | Unprotect text file.


[+] Usage examples:

    # Protect file:
    DoCrypt.exe /P "Document.txt"

    # Unprotect file:
    DoCrypt.exe /U "Protected Document.txt"

]]></a>.Value

#End Region

    Sub Main()


        ' My.Computer.Clipboard.SetText(Encrypt_String("ñ"))
        ' MsgBox(Decrypt_String("OFE9PQ=="))

        Console.WriteLine(Logo)
        Parse_Arguments()
        Environment.Exit(0)
    End Sub

    ' Pase commandline arguments
    Private Sub Parse_Arguments()

        Select Case My.Application.CommandLineArgs.Count

            Case 0
                Help()

            Case Is < 2 ' Insuficcient arguments
                PrintError(1)

            Case Is > 2 ' Too many arguments
                PrintError(2)

            Case 2

                If Not IO.File.Exists(My.Application.CommandLineArgs.Item(1)) Then
                    PrintError(3)
                Else
                    INFO = New IO.FileInfo(My.Application.CommandLineArgs.Item(1))
                End If

                Try
                    Content = IO.File.ReadAllLines(INFO.FullName)
                Catch ex As Exception
                    Console.WriteLine(ex.Message)
                End Try

        End Select

        Select Case My.Application.CommandLineArgs.Item(0).ToLower

            Case "/p", "/protect"

                For Each line As String In Content
                    Result.Add(Encrypt_String(line))
                    Console.WriteLine(Result.Last)
                Next

                If Not String.IsNullOrEmpty(INFO.Extension) Then
                    IO.File.WriteAllLines(String.Format("{0} Encrypted{1}", _
                                          INFO.FullName.Substring(0, INFO.FullName.LastIndexOf(".")), INFO.Extension), _
                                          Result, System.Text.Encoding.Default)
                Else
                    IO.File.WriteAllLines(INFO.FullName & " Encrypted.txt", Result, System.Text.Encoding.Default)
                End If

            Case "/u", "/unprotect"

                For Each line As String In Content
                    Result.Add(Decrypt_String(line))
                    Console.WriteLine(Result.Last)
                Next

                If Not String.IsNullOrEmpty(INFO.Extension) Then
                    IO.File.WriteAllLines(String.Format("{0} Decrypted{1}", _
                                          INFO.FullName.Substring(0, INFO.FullName.LastIndexOf(".")), INFO.Extension), _
                                          Result, System.Text.Encoding.Default)
                Else
                    IO.File.WriteAllLines(INFO.FullName & " Decrypted.txt", Result, System.Text.Encoding.Default)
                End If

            Case Else
                PrintError(4)

        End Select

        Environment.Exit(0)

    End Sub

    ' Prints Help syntax
    Private Sub Help()
        Console.WriteLine(Syntax)
        Environment.Exit(1)
    End Sub

    ' Prints An ErrorMessage
    Private Sub PrintError(ByVal Errormessage As Short)
        Console.WriteLine("[X] Error: " & ErrorMessages(Errormessage))
        Environment.Exit(1)
    End Sub

    ' Encrypt String
    Public Function Encrypt_String(ByVal str As String) As String
        Return Convert.ToBase64String(System.Text.Encoding.Default.GetBytes( _
               Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(str))))
    End Function

    ' Decrypt String
    Private Function Decrypt_String(ByVal str As String) As String
        Return System.Text.Encoding.Default.GetString(Convert.FromBase64String( _
                System.Text.Encoding.Default.GetString(Convert.FromBase64String(str))))
    End Function

End Module

1 个答案:

答案 0 :(得分:0)

我不确定您测试此代码的确切条件,但它应该可以正常工作。您所引用的错误很可能是通过在读/写时选择了错误的编码方法而引起的。在任何情况下,使用默认配置和使用您的代码我都没有发现任何问题:

Result.Add(Encrypt_String("ñ")) 'Result(0) = "OFE9PQ=="
System.IO.File.WriteAllText("file path", Result(0))
Dim out As String = Decrypt_String(System.IO.File.ReadAllText("file path").Trim()) 'out = "ñ"

请告诉您遇到此问题的具体条件。

<强>更新

当用ReadAllText替换第一行时(从只写“ñ”的文件中),我什么都没得到(空字符串)。我必须将编码设置为Default以使其按上述方式工作:

Result.Add(Encrypt_String(System.IO.File.ReadAllText("file path", System.Text.Encoding.Default).Trim()))

默认编码(System.Text.Encoding.Default.EncodingName)的名称为Western European (Windows)

因此,在读取文件时选择正确的编码是一个问题,而不是使用.NET变量。奇怪的是, ReadAllText默认情况下不会考虑Encoding.Default (!)。