2012-04-30 15 views
0

我正在从MS Office Word 2010文件(.docx)中读取数据,然后对其进行处理,然后将数据写入新文件。我添加的唯一字符是在大多数键盘上找到的字符(字母,数字,标点符号......),我也将现有的字符移动一点点。EncoderFallbackException写入文件时

 StreamReader sr = new StreamReader(File.OpenRead("fs.docx")); 
     string foo = sr.ReadToEnd(); 
     sr.Close(); 
     string foo2 = EncryptFile(foo); 
     StreamWriter sw = new StreamWriter(File.Create("sal.docx")); 
     sw.Write(foo2); // THIS IS WHERE THE EXCEPTION HAPPENS 
     sw.Close(); 
     foo = DecryptFile(foo2); 
     StreamWriter sww = new StreamWriter(File.Create("sal2.docx")); 
     sww.Write(foo); 
     sww.Close(); 

    public static string Salt(string Input) 
    { 
     Random rand = new Random(); 
     string Output = ""; 
     string BigSalt = ""; 
     int SaltIncrement = rand.Next(4, 8); 
     for (int i = 0; i < 10; i++) { 
      BigSalt += FindCipherPlainText.Substring(rand.Next(0, FindCipherPlainText.Length), 1); 
     } 
     Input = BigSalt + Input; 

     for (int i = Input.Length; i >= 0; i--) { 
      if ((decimal)i % SaltIncrement == 0) { 
       Input = Input.Insert(i, FindCipherPlainText.Substring(rand.Next(0, FindCipherPlainText.Length), 1)); 
      } 
     } 
     Input += FindCipherPlainText.Substring(rand.Next(0, FindCipherPlainText.Length), 1); 
     Input = ((SaltIncrement + 2) * 8).ToString().Substring(1, 1) + Input + ((SaltIncrement + 2) * 8).ToString().Substring(0, 1) + rand.Next(0, 10).ToString(); 
     return Input; 
    } 

    public static string Mix(string Input) { 
     string Output = ""; 
     if (Input.Length > 1) 
     { 
      if (Input.Length % 2 == 0) 
      { 
       Output = Input.Substring(Input.Length/2); 
       Output += Input.Substring(0, Input.Length/2); 
      } 
      else 
      { 
       Output = Input.Substring((Input.Length - 1)/2); 
       Output += Input.Substring(0, (Input.Length - 1)/2); 
      } 
     } 
     else { 
      return Input; 
     } 
     return Output; 
    } 

    public static string Shift(string Input) { 
     string Output = ""; 
     bool Found = false; 
     for (int i = 0; i < Input.Length; i++) { 
      Found = false; 
      for (int ii = 0; ii < FindCipherPlainText.Length; ii++) { 
       if (Input.Substring(i, 1) == FindCipherPlainText.Substring(ii, 1)) { 
        Output = Output.Insert(0, ReplaceCipherPlainText.Substring(ii, 1)); 
        Found = true; 
        break; 
       } 
      } 
      if (!Found) { 
       Output = Output.Insert(0, Input.Substring(i, 1)); 
      } 
     } 
     return Output; 
    } 

    public static string EncryptFile(string Input) { 
     return Mix( Salt( Shift( Mix( Input)))); 
    } 





System.Text.EncoderFallbackException was unhandled 
    Message=Unable to translate Unicode character \uDF23 at index 428 to specified code page. 
    Source=mscorlib 
    Index=428 

这是我的代码,以及一些例外的细节,我描述aboved什么EncryptFile()和DecryptFile()不加字符,移动它们......没有任何人有任何想法为什么发生这种情况?

+0

请你也发布'EncryptFile'的代码?我认为你的问题的原因是输入数据的按字节操作最终导致无法转换为UTF-8的Unicode代理对无效。 –

+0

完成。我还将Encrypt()更改为EncryptFile(),因为Encrypt()是一个错字 – Oztaco

回答

5

此例外的原因是,字符交换函数最终生成了一个无效的UTF-16字符串surrogate pair。也就是说,至少有一个代码为[DC00-DFFF]的字符,前面没有代码为[D800-DBFF]的字符。此字符串无法写入文件,因为无法在目标编码中表示无效字符。

为了证明一个简单的例子这个问题,这里是一段代码,它模拟了同样的情况:

static void Main(string[] args) 
{ 
    // A perfectly valid surrogate pair with 1st character in the D800-DBFF range, 
    // and 2nd character in the DC00-DFFF range. 
    string validSurrogate = "\uD801\uDC01"; 

    // Creating an invalid surrogate pair just by swapping the two characters in the first string. 
    string invalidSurrogate = validSurrogate.Substring(1, 1) + validSurrogate[0]; 

    // This will work fine. 
    File.WriteAllText("valid.txt", validSurrogate); 

    // --! But this will crash !-- 
    File.WriteAllText("invalid.txt", invalidSurrogate); 
} 

我想提出以下建议:

  • 使用字节数组来代替字符串在所有加密/解密功能中。然后将这些字节数组直接写入文件,而不将它们视为文本。
  • 如果这是一个“真实世界”的应用程序,而不是一门功课或宠物项目,加密使用加密标准(AES,3DES,...),而不是设计自己的密码:)