2010-10-04 109 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编码文本嵌入在普通文本的事实显然是一个设计错误,我建议你做一些事情,而那个试图做一些不可能的...

相关问题