【问题标题】:Converting Base64 to string inserts whitespaces将 Base64 转换为字符串会插入空格
【发布时间】:2018-10-02 13:17:17
【问题描述】:

我正在尝试将 Base64 编码的字符串转换为文本。我正在使用以下代码:

public static string Base64Decode(string base64EncodedData)
{
    var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
    return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}

它确实可以工作,但它会在每个字符后放置空格。此外,它会在转换后的字符串的开头添加一个无效字符。 Base64 字符串中的内容是 XML,因此当它将其转换为文本并放置空格时,XML 变得无效。有没有其他选择?

这是转换后的示例输出:

? < ? x m l  v e r s i o n = " 1 . 0 "  e n c o d i n g = " U T F - 1 6 "  s t a n d a l o n e = " n o " ? >   < I m p o r t >     < o p t i o n s >       < P r o c N a m e > E R P N u m b e r < / P r o c N a m e >       < J o b I D > A N L 0 0 1 8 5 0 < / J o b I D >     < / o p t i o n s >     < R o w >       < D o c I d  / >       < E R P N u m b e r  / >     < / R o w >   < / I m p o r t > 

【问题讨论】:

  • 您确定字符串是 utf8,而不是 utf16?请提供 base64 字符串的minimal reproducible example
  • 我假设传入的base64EncodedData 实际上是UTF-16 编码的。尝试改用System.Text.Encoding.UTF16.GetString
  • 您需要两件事来将字节解释为文本:1) 字节,2) 字符编码。询问发件人,或者可能已经通过规范、标准、约定等传达给您。
  • @TomBlodget - 因为它实际上是 XML(可能在开头带有字节顺序标记),OP 可以返回一个字节数组,将其放入 MemoryStream,他们使用 XmlReader.Create(Stream) 来解析XML。我认为(但尚未检查)XmlReader 将正确解释编码。或者如果确实有BOM,那么OP可以使用new StreamReader(Stream, true)来检测。
  • @dbc 是的,好点。知道字节是 XML 文档就足够了,因为 XML 标准有一个算法来确定字符编码。

标签: c# xml string base64


【解决方案1】:

看起来原始二进制数据是使用 UTF-16 转换为字节的字符串,与文本的 encoding="UTF-16" 部分匹配。将二进制数据转换回字符串时需要使用正确的编码:

return Encoding.Unicode.GetString(base64EncodedBytes);

这是假设您一开始就无法更改产生数据的因素。如果您可以将其更改为使用 UTF-8,那么如果文本都是 ASCII 字符,您最终将获得一半的数据...

【讨论】:

  • 谢谢。这是我的一个愚蠢的错误,我没有注意到源代码中的编码。将其更改为 UTF8 并且现在可以使用。
【解决方案2】:

正如Jon Skeethis answer 中解释的那样,该字符串似乎以UTF-16 而不是UTF-8 编码。

你也写了

此外,它在转换后的字符串的开头添加了一个无效字符。

这个无效字符几乎可以肯定是byte order mark,一个小的序言字节序列,指示流中使用的特定编码。鉴于它的存在,您可以配置一个StreamReader 来检测使用new StreamReader(Stream, true) 构造函数指定的编码:

public static string Base64Decode(string base64EncodedData)
{
    var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
    using (var reader = new StreamReader(new MemoryStream(base64EncodedBytes), true))
    {
        return reader.ReadToEnd();
    }
}

请注意,StreamReader 在处理过程中会消耗字节顺序标记,因此它不会包含在返回的字符串中。

或者,由于您的 base64 数据实际上是 XML,并且 XML 包含自己的 encoding declaration,您可以提取字节数组并直接使用 XmlReader 解析它:

public static XmlReader CreateXmlReaderFromBase64(string base64EncodedData, XmlReaderSettings settings = null)
{
    var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
    return XmlReader.Create(new MemoryStream(base64EncodedBytes), settings);
}

根据docsXmlReader.Create(Stream)会按要求检测编码:

XmlReader 扫描流的第一个字节以查找字节顺序标记或其他编码符号。确定编码后,使用编码继续读取流,处理继续将输入解析为(Unicode)字符流。

【讨论】:

    猜你喜欢
    • 2021-12-12
    • 1970-01-01
    • 2016-08-11
    • 2014-05-10
    • 2017-07-28
    • 2014-03-14
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多