在内存中压缩并使用base64编码

时间:2013-09-26 19:57:56

标签: c# c#-4.0 svg zip base64

我想在内存中压缩SVG文件并使用base64对其进行编码(我想将zipped / base64 SVG保存在XML文件中)。

这就是我所拥有的(但我对所有事情都持开放态度):

byte[] svg = File.ReadAllBytes("test.SVG");
using (MemoryStream ms = new MemoryStream())
{  
    using (Package pkg = Package.Open(ms, FileMode.Create)) 
    {
        PackagePart part = pkg.CreatePart(new Uri("/test.SVG", UriKind.Relative), "image/svg+xml", CompressionOption.Normal);  
        using (Stream strm = part.GetStream()) 
        {  
            using (StreamWriter sw = new StreamWriter(strm)) 
            {  
                sw.Write(svg);
            }

            byte[] b = ReadToEnd(part.GetStream());
            return Convert.ToBase64String(b);
        }
    }
}

它将某些内容转换为base64,但这不是我的文件,因为它只有几个字符长。

2 个答案:

答案 0 :(得分:3)

您的代码存在多个问题。

最重要的是,您打开StreamWriter来编写二进制数据。你有:

byte[] svg;

...

using (StreamWriter sw = new StreamWriter(...))
{
    sw.Write(svg);
}

StreamWriter用于编写文本。您的通话最终会解决为TextWriter.Write(object)。结果就像你打电话:

sw.Write(svg.ToString());

将输出类的名称("System.Byte[]")。这就是为什么你得到的是13个字节长。它还指出了另一个问题(见下文)。

所以你需要做的第一件事就是放弃StreamWriter并拥有:

    using (Stream strm = part.GetStream()) 
    {  
        strm.Write(svg, 0, svg.Length)
    }

至少,它会将您想要的数据写入流中。

现在,至于阅读,你有一个问题。你可能会写:

        strm.Flush();
        strm.Position = 0;
        byte[] b = ReadToEnd(part.GetStream());
        return Convert.ToBase64String(b);

我不知道你的ReadToEnd方法做了什么。也许它定位流并读取所有内容。但这不会给你你想要的东西,这是我提到的另一个问题。

part.GetStream返回的流会覆盖Read方法,而会解压缩数据。因此,您获取的字节数组将与您编写的原始svg数组相同。

查看Package API,我没有看到一个方法可以为您提供特定部分的压缩数据流。

简而言之,我认为您需要编写整个包,将 转换为base-64,然后将其返回,如Alexei's answer所示。

答案 1 :(得分:2)

你不是在开始寻找流。最简单的解决方法是在处置ToArray之前使用MemoryStream

using (MemoryStream ms = new MemoryStream())
{
  // Whatever manipulations with stream you need goes here.
  ...
  ms.Close(); // guarantees to commit all changes, 
              // safe to do as `ToArray` work on disposed stream
  return Convert.ToBase64String(ms.ToArrray());
}