2010-10-04 112 views
5

我試圖找出一種方法來從一個較大的字符串解析出一個base64字符串。確定一個字符串是否包含它內部的base64字符串

我有字符串"Hello <base64 content> World",我希望能夠解析出base64內容並將其轉換回字符串。 "Hello Awesome World"

C#首選答案。

編輯:更新了一個更真實的例子。

--abcdef 
\n 
Content-Type: Text/Plain; 
Content-Transfer-Encoding: base64 
\n 
<base64 content> 
\n 
--abcdef-- 

這是取自1個樣本。問題在於內容....從一個記錄到下一個記錄有很大不同。

+1

以任何方式限定以base64內容? – jball 2010-10-04 18:22:19

+1

這是一個XY問題。真正的問題是X:你是怎麼得到這樣一個字符串的。 – 2010-10-04 19:18:26

+0

@Hans Passant我同意,我試圖編寫一個工具來修復某些首先損壞的數據。我們已經修復了製作損壞數據的部分,但現在我們必須在大約300萬條記錄上修復它。 – Adam 2010-10-04 20:39:17

回答

4

總之表,您可以:

  • 分割上是無效的base64數據或填充任何字符的字符串
  • 嘗試每個令牌
  • 轉換,如果轉換成功,調用替換上原始的字符串以與轉換的值

切換令牌在代碼:

var delimiters = new char[] { /* non-base64 ASCII chars */ }; 
var possibles = value.Split(delimiters, StringSplitOptions.RemoveEmptyEntries); 
//need to tweak to include padding chars in matches, but still split on padding? 
//maybe better off creating a regex to match base64 + padding 
//and using Regex.Split? 

foreach(var match in possibles) 
{ 
    try 
    { 
     var converted = Convert.FromBase64String(match); 
     var text = System.Text.Encoding.UTF8.GetString(converted); 
     if(!string.IsNullOrEmpty(text)) 
     { 
      value = value.Replace(match, text); 
     } 
    } 
    catch (System.ArgumentNullException) 
    { 
     //handle it 
    } 
    catch (System.FormatException) 
    { 
     //handle it 
    } 
} 

儘管沒有分隔符,但您最終可能會將非base64文本轉換爲base64編碼文本。在你試圖"Hello QXdlc29tZQ== World"轉換爲"Hello Awesome World"上述算法可以很容易地通過嘗試從BASE64整個字符串轉換因爲是平原和編碼的文本之間沒有分隔符產生類似"ée¡Ý•Í½µ」¢¹]"例如

展望。

更新(基於評論):

如果沒有'\n' S IN以base64內容,它總是由"Content-Transfer-Encoding: base64\n"前面,那麼還有一個辦法:

  • 各執'\n'
  • 迭代所有令牌,直到令牌結束"Content-Transfer-Encoding: base64"
  • 下一個令牌(如果有的話)應該被解碼(如果可能的話),然後替換應該是ma德在原始字符串
  • 返回迭代,直到出令牌

在代碼:

private string ConvertMixedUpTextAndBase64(string value) 
{ 
    var delimiters = new char[] { '\n' }; 
    var possibles = value.Split(delimiters, 
           StringSplitOptions.RemoveEmptyEntries); 

    for (int i = 0; i < possibles.Length - 1; i++) 
    { 
     if (possibles[i].EndsWith("Content-Transfer-Encoding: base64")) 
     { 
      var nextTokenPlain = DecodeBase64(possibles[i + 1]); 
      if (!string.IsNullOrEmpty(nextTokenPlain)) 
      { 
       value = value.Replace(possibles[i + 1], nextTokenPlain); 
       i++; 
      } 
     }     
    } 
    return value; 
} 

private string DecodeBase64(string text) 
{ 
    string result = null; 
    try 
    { 
     var converted = Convert.FromBase64String(text); 
     result = System.Text.Encoding.UTF8.GetString(converted); 
    } 
    catch (System.ArgumentNullException) 
    { 
     //handle it 
    } 
    catch (System.FormatException) 
    { 
     //handle it 
    } 
    return result; 
} 
+2

最後一部分是棘手的部分。例如,如果你分割並獲得「aaBG」作爲你的字符串,你會怎麼做?這是「i F」的base64表示。你需要一些啓發式來決定你真正想要的是哪一個。 – Yuliy 2010-10-04 18:32:18

8

沒有可靠的方法來做到這一點。你怎麼會知道,例如,「你好」不是一個base64字符串?好的,這是一個不好的例子,因爲base64應該被填充以便長度是4的倍數,但是「overflow」是什麼?它的長度爲8個字符,它是一個有效的base64字符串(它可以解碼爲「¢〜〜Z0」),儘管這對於讀者來說顯然是一個正常的詞。您無法確定單詞是普通單詞還是base64編碼文本。

您已經base64編碼文本嵌入在普通文本的事實顯然是一個設計錯誤,我建議你做一些事情,而那個試圖做一些不可能的...

相關問題