【问题标题】:Encode Base64 String in Chunks in C#在 C# 中的块中编码 Base64 字符串
【发布时间】:2014-08-13 05:49:31
【问题描述】:

我有一些文件,我将其保存在隔离存储中,如何使用块将隔离流转换为 Base64,如果我将流直接转换为 base64,那么 base64 变得太长,并且 Visual Studio 停止工作。那么如何使用块呢?请参阅下面的代码:

BinaryReader rdr = new BinaryReader(isofile);
long lng = rdr.BaseStream.Length;
int rr = Convert.ToInt32(lng);
byte[] b = rdr.ReadBytes(rr);
string str = Convert.ToBase64String(b);

【问题讨论】:

  • 你能解释一下为什么你需要它作为 Base64 开头吗?
  • @Noctis 是的,我必须将它返回给 Web 服务,并作为 Base64。谢谢,请给我意见

标签: c# base64


【解决方案1】:

尝试使用预定义的块大小并按数据块读取文件。然后您可以使用每个块中的数据并使用它。如果您需要将整个文件作为 Base64 发布,那么按块读取它不会改变它太长的事实,如果这是问题的话。

int chunkSize = 1024;
string source = @"file.accdb";

BinaryReader rdr = new BinaryReader(new FileStream(source, FileMode.Open));
int streamLength = (int)rdr.BaseStream.Length;


while (rdr.BaseStream.Position < rdr.BaseStream.Length) 
{
    byte[] b = new byte[chunkSize];

    long remaining = rdr.BaseStream.Length - rdr.BaseStream.Position;
    if(remaining >= chunkSize)
    {
        rdr.Read(b, 0, chunkSize);
    }
    else
    {
        rdr.Read(b, 0, (int)remaining);
    }

    string chunkString = Convert.ToBase64String(b);
    // .. do something with the chunk of data, write to a stream, etc
}

编辑:我已经在您的场景中对此进行了测试,阅读了您通过默认 Windows 安装获得的野生动物视频,并将它们写入带有字节的文件中,并且还使用 Base64 编码的字符串,例如你正在做,两个测试都OK,我可以在这两种情况下毫无问题地播放视频,所以阅读的方法应该不是这里的问题。我已经提供了我用于测试的方法。如果问题仍然存在,请尝试上传一个小文件并验证发送的内容是否与您的 Web 服务正在获取和保存的内容相匹配。我认为问题可能是我在下面的评论中描述的,暗示 C# 和 Java 对待 Base64 有点不同。

StringBuilder acc = new StringBuilder();
int chunkSize = 2187;
string source = @"Wildlife.wmv";

BinaryReader rdr = new BinaryReader(new FileStream(source, FileMode.Open));

while (rdr.BaseStream.Position < rdr.BaseStream.Length)
{
    byte[] b = new byte[chunkSize];

    long remaining = rdr.BaseStream.Length - rdr.BaseStream.Position;
    if (remaining >= chunkSize)
    {
        rdr.Read(b, 0, chunkSize);
    }
    else
    {
        rdr.Read(b, 0, (int)remaining);
    }

    acc.Append(Convert.ToBase64String(b));
}

FileStream fs = new FileStream(@"c:\dev\test.wmv", FileMode.OpenOrCreate);
fs.Write(Convert.FromBase64String(acc.ToString()),0,0);

Process.Start(@"c:\dev\test.wmv");

【讨论】:

  • 不应该是:while (rdr.BaseStream.Position &lt; StreamLength) 吗?否则,听起来就足够了:)
  • 安德烈,谢谢伙计,我正在测试你的答案。非常感谢!!
  • Andrej,当我尝试使用 VLC 播放器使用此代码播放视频时,我收到以下消息:“VLC 无法识别输入格式:”..任何更正?
  • 既然你提到你正在尝试从 C# 上传到 Java,我偶然发现了一些可能帮助你解决错误的东西:如果你检查这个接受的答案:stackoverflow.com/a/13929054/1361993 用户要去反过来,但显然 C# 和 Java 在使用 Base64 方面有所不同,答案说“它应该像用 C# 使用的 + 和 / 替换 Java 使用的 - 和 _ 一样简单”,所以也许你可以尝试替换反过来看看它是否适合你。
  • stackoverflow.com/q/5805022/1698987 谈到了类似的事情,但我很惊讶他们有不同的实现......这有点违背了我猜的目的......无论如何,确保你没有运行我在回答中也强调了这个问题。
【解决方案2】:

我仍然不是 100% 知道原因,但我建议您查看 answer 以了解类似情况。

我正在使用 Web 服务,我不记得很长时间需要使用 base64。上次我这样做是为了一个与不同应用程序通信的 php ......你确定你需要这样做吗?


示例(使用 Andrej 代码)。 此案例有效,但是:阅读代码后的警告以了解更多信息

// Input
var my_string = "Hello world!";
// Get as binary
System.Text.ASCIIEncoding  encoding = new System.Text.ASCIIEncoding();
var input_as_binary = encoding.GetBytes(my_string);
    /*
        72 
        101 
        108 
        108 
        111 
        32 
        119 
        111 
        114 
        108 
        100 
        33 
    */
// If the following is not an exact divisor, It won't work.
int chunkSize = 6;
// Create a stream and reader
Stream stream = new MemoryStream(as_binary);
BinaryReader rdr = new BinaryReader(stream);
int streamLength = (int)rdr.BaseStream.Length;
// A stub to hold the bits of Base64. This will happen on your receiving end
var sb = new StringBuilder();

// from Andrej answer, I'm just using the "streamLength" Var he defined 
while (rdr.BaseStream.Position < streamLength) 
{
    byte[] b = new byte[chunkSize];

    long remaining = streamLength - rdr.BaseStream.Position;
    if(remaining >= chunkSize)
    {
        rdr.Read(b, 0, chunkSize);
    }
    else
    {
        rdr.Read(b, 0, (int)remaining);
    }
    string chunkString = Convert.ToBase64String(b).Dump("as base 64");

    // Lets assume we send it and it's received on the other side
    sb.Append(chunkString);
}

// This should happen on your receiving side as well
var other_side = sb.ToString(); // value => SGVsbG8gd29ybGQh
// Back into byte array
var byte_from_64 = Convert.FromBase64String(other_side);
// Back into string. Will hold "Hello World!"
var string_from_byte = encoding.GetString(byte_from_64);

以上工作。但是,如果您将块大小更改为无法为您提供精确 Base64 位的值(例如 5,而不是 6),您将得到一个类似 SGVsbG8=IHdvcmw=ZCEAAAA= 的字符串,然后是一个异常:

FormatException

The input is not a valid Base-64 string as it contains a non-base 64 character 
, more than two padding characters, or an illegal character among the pa... 

这就是为什么我建议玩弄你的意见:)

【讨论】:

  • Noctis,Web 服务是用 Java 创建的,它的类型是“Base64”,我正在添加一些媒体文件,所以我必须将其转换为 Base64。谢谢。有什么建议吗?
  • 是的,看看 Andrej 的回答。我会用一些简短的东西来测试它,以确保它不会表现得很好笑:)
【解决方案3】:
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-05
  • 1970-01-01
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多