1

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

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

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

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

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

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
4

1 回答 1

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(!)。

于 2013-09-20T10:24:52.990 回答