c# - C#:解码 Base64 字符串不返回完整结果/乱码
问题描述
我们有一个保存在数据库中的 base64 编码字符串。(结果仍然需要使用 bzip2 解码,但这是另一个问题。)但是,当尝试使用 C# 对其进行转换时,我们遇到了一些问题。
// get base 64 string from file
string base64String = File.ReadAllText(@"D:\bzip2\base64text.txt", Encoding.UTF8);
// decode from base64
var largeCompressedTextAsBytes = Convert.FromBase64String(base64String);
// convert to string
var decodedString = Encoding.UTF8.GetString(largeCompressedTextAsBytes);
- 首先,我们认为我们必须删除第一部分才能使其转换:
=base64begin line=73 size=142698 crc=
- 接下来我们得到一个结果,但它太小了(而且都是胡言乱语,但这也可能是因为使用 bzip2 进一步编码)
��oW�k�_i�ۍ��ֶӽ^k���MZ�V�bzip2,7,16813,16573,16672,16636,15710,14413,7264,BZh61AY&SY�de...</p>
- 我们尝试从文本中删除换行符(无济于事)
text.Replace(Environment.NewLine, "");
有人在这里有什么想法吗?
谢谢
肖夫
解决方案
数据的第一行实际上是标题:
=base64begin line=73 size=142698 crc=1e0db1eda49fad0c242c2da2071ea521501a91ad
其余的是base64。将该 base64 转换为二进制后,您会得到一些文本:
bzip2,7,16813,16573,16672,16636,15710,14413,7264,
...后跟一个 bzip2 文件。我不知道这个“标题”数据是什么,但是在删除它之后,其余的可以使用bunzip2
. 结果是一个包含一些图像的 RTF 文件。
您接下来的步骤应该是获取有关在数据库中存储数据的内容以及具体步骤的更多信息。它们似乎是:
- 压缩文件
- 添加以“bzip2”开头的“header”前缀
- 将结果转换为base64
- 添加另一个带有 CRC 和长度的“标题”前缀
- 存储结果文本
您应该尝试找出所有这些步骤的精确细节,以便您可以撤消它们,并在此过程中执行任何检查(例如 CRC 检查)。
这是一个完整的程序,可以从您提供的示例中提取文件。我已经猜到了“内部”标题表单,但是您应该真正尝试找出创建标题的原因,以便验证我的假设。
using SharpCompress.Compressors.BZip2;
using System;
using System.IO;
using System.Text;
class Program
{
static void Main(string[] args)
{
string base64;
using (var reader = File.OpenText(args[0]))
{
// Skip the first line, which has some header information
// TODO: Use it instead, to validate the rest of the data.
reader.ReadLine();
base64 = reader.ReadToEnd();
}
byte[] bytes = Convert.FromBase64String(base64);
int startOfBody = FindStartOfBody(bytes);
using (var input = new MemoryStream(bytes, startOfBody, bytes.Length - startOfBody))
{
using (var bzip2 = new BZip2Stream(input, SharpCompress.Compressors.CompressionMode.Decompress, true))
{
using (var output = File.OpenWrite(args[1]))
{
bzip2.CopyTo(output);
}
}
}
}
private static int FindStartOfBody(byte[] bytes)
{
// The file starts with a "header" of an unknown format, which we need to
// skip. It looks like the format *might* be a sequence of comma-separated values
// - Name of some kind (BZIP2)
// - Number of further values
// - The remaining values
// That's what this code does.
int offset = 0;
// Skip the name
GetNextHeaderValue(bytes, ref offset);
// Find out how many more values there are
string valueCountText = GetNextHeaderValue(bytes, ref offset);
int valueCount = int.Parse(valueCountText);
// Skip them
for (int i = 0; i < valueCount; i++)
{
GetNextHeaderValue(bytes, ref offset);
}
// We'll now be positioned at the end
return offset;
}
private static string GetNextHeaderValue(byte[] bytes, ref int offset)
{
StringBuilder builder = new StringBuilder();
// TODO: Validation that we're not going past the end of the data...
// We assume all header data is ASCII.
for (; bytes[offset] != ','; offset++)
{
builder.Append((char) bytes[offset]);
}
// Move the offset past the comma
offset++;
return builder.ToString();
}
}