为什么?重构后C#错误:“流无效或未找到相应的签名。” [英] Why? C# Error after Refactor: 'The stream is invalid or no corresponding signature was found.'

查看:296
本文介绍了为什么?重构后C#错误:“流无效或未找到相应的签名。”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是来自此处的后续问题:使用SevenZipSharp将流解压缩为字符串

This is a follow-on question from here: Decompress Stream to String using SevenZipSharp.

以下代码的工作原理是:它接受一个字符串并成功地对其进行压缩和解压缩。

The following code works in the sense that it takes a string and successfully compresses and decompresses it.

using System;
using System.IO;
using SevenZip;

namespace _7ZipWrapper
{
    public class ProgramOriginal
    {
        public static void Main()
        // This should be broken into separate methods
        {
            // Setup Input String
            var strToCompress = "This String"; // will pass as parameter
            var memStreamToCompress = new MemoryStream();

            var StringToStream = new StreamWriter(memStreamToCompress);
            StringToStream.Write(strToCompress);
            StringToStream.Flush();

            // Confirm the Input Stream is As-Expected
            memStreamToCompress.Position = 0;
            var MemoryAsString = new StreamReader(memStreamToCompress);
            Console.WriteLine("Stream in memory: " + MemoryAsString.ReadToEnd());
            Console.ReadKey();

            // Setup the SevenZip Dll
            SevenZipCompressor.SetLibraryPath(@"C:\Temp\7za64.dll");

            // Set up a compressor...
            SevenZipCompressor SevenZipC = new SevenZipCompressor();
            SevenZipC.CompressionMethod = CompressionMethod.Ppmd;
            SevenZipC.CompressionLevel = global::SevenZip.CompressionLevel.Ultra;
            SevenZipC.ScanOnlyWritable = true;

            // Compress PassedStream -> CompressedStream
            var compressedMemoryStream = new MemoryStream();
            SevenZipC.CompressStream(memStreamToCompress, compressedMemoryStream, "Optional Password Field");
            compressedMemoryStream.Position = 0;
            StreamReader compressedMemoryAsString = new StreamReader(compressedMemoryStream);

            // Show that we have a compressed String
            compressedMemoryStream.Position = 0;
            Console.WriteLine(compressedMemoryAsString.ReadToEnd());
            Console.ReadKey();

            // Set up a decompressor... (only needs to know what to decompress)
            compressedMemoryStream.Position = 0;
            var SevenZipE = new SevenZip.SevenZipExtractor(compressedMemoryStream, "Optional Password Field");

            // Decompress CompressedStream
            var DecompressedMemoryStream = new MemoryStream();
            SevenZipE.ExtractFile(0, DecompressedMemoryStream);

            // Show that DecompressedMemoryStream is valid
            DecompressedMemoryStream.Position = 0;
            StreamReader decompressedStreamAsText = new StreamReader(DecompressedMemoryStream);
            Console.WriteLine("Decompressed String: " + decompressedStreamAsText.ReadToEnd());
            Console.ReadKey();
        }
    }
}

但是,以上代码显然以目前的形式(注定要成为COM DLL)并没有多大用处。

However, the above code obviously does little good in its current form (this is destined to become a COM DLL).

我以为自己是家住户,重构很麻烦,但是,我尝试将代码重新安排为有用的东西,这让我无所适从为什么下面的代码会引发System.ArgumentException(流无效或未找到相应的签名。),但是上面的代码没有问题。

I thought I was home-and-hosed and that refactoring would be a cinch, However, my attempts to rearranging the code into something useful have left me at a loss as to why the following code throws a System.ArgumentException ('The stream is invalid or no corresponding signature was found.') but the code above runs without issue.

一定有一些区别,但是我对导致它的原因以及如何解决感到困惑。

Fundamentally there must be some sort of difference but I'm at a loss as to what causes it, and how to resolve. A solution accompanied with a brief explanation will be much appreciated.

using System;
using System.IO;
using SevenZip;

namespace _7ZipWrapper
{
    public class Program
    {
        public static void Main()
        {
            // Setup Input String
            var strToCompress = "This String"; // will eventually pass as parameter


            // Convert input string to memory stream
            var memStreamToCompress = StringToStream(strToCompress);


            // Confirm the Input Stream is As-Expected
            memStreamToCompress.Position = 0;
            var MemoryAsString = new StreamReader(memStreamToCompress);
            Console.WriteLine("Stream in memory: " + MemoryAsString.ReadToEnd());
            Console.ReadKey();

            // Compress the Stream
            memStreamToCompress.Position = 0;
            var compressedString = StreamCompress(memStreamToCompress, "password");

            // Decompress the String
            var memStreamToRestore = StringToStream(compressedString);
            memStreamToRestore.Position = 0;

            var decompressedString = StreamDecompress(memStreamToRestore, "password");

            Console.WriteLine(decompressedString);
            Console.ReadKey();
        }

        private static MemoryStream StringToStream(string strToMemoryStream)
        {
            var memoryStream = new MemoryStream();
            var writer = new StreamWriter(memoryStream);
            writer.Write(strToMemoryStream);
            writer.Flush();
            return memoryStream;
        }

        private static MemoryStream StringToStream1(string strToMemoryStream)
        {
            var memoryStream = new MemoryStream();
            var writer = new StreamWriter(memoryStream);
            writer.Write(strToMemoryStream);
            writer.Flush();
            return memoryStream;
        }


        private static string StreamCompress(MemoryStream memStreamToCompress, string optionalPassword)
        {
            // Setup the SevenZip Dll
            SevenZipCompressor.SetLibraryPath(@"C:\Temp\7za64.dll");

            // Set up a compressor...
            SevenZipCompressor SevenZip = new SevenZipCompressor();
            SevenZip.CompressionMethod = CompressionMethod.Ppmd;
            SevenZip.CompressionLevel = global::SevenZip.CompressionLevel.Ultra;
            SevenZip.ScanOnlyWritable = true;

            // Compress PassedStream -> CompressedStream
            var compressedMemoryStream = new MemoryStream();
            SevenZip.CompressStream(memStreamToCompress, compressedMemoryStream, optionalPassword); // "Optional Password Field"
            compressedMemoryStream.Position = 0;
            StreamReader compressedMemoryAsString = new StreamReader(compressedMemoryStream);
            return compressedMemoryAsString.ReadToEnd();
        }

        private static string StreamDecompress(MemoryStream compressedMemoryStream, string optionalPassword)
        {
            // Setup the SevenZip Dll
            SevenZipExtractor.SetLibraryPath(@"C:\Temp\7za64.dll");

            // Set up a decompressor... (only needs to know what to decompress)
            compressedMemoryStream.Position = 0;
            // CRASHES Next Line: System.ArgumentException: 'The stream is invalid or no corresponding signature was found.'
            var SevenZip = new SevenZip.SevenZipExtractor(compressedMemoryStream, optionalPassword);  

            // Decompress CompressedStream
            var DecompressedMemoryStream = new MemoryStream();
            SevenZip.ExtractFile(0, DecompressedMemoryStream);

            // Show that DecompressedMemoryStream is valid
            DecompressedMemoryStream.Position = 0;
            StreamReader decompressedStreamAsText = new StreamReader(DecompressedMemoryStream);
            return decompressedStreamAsText.ReadToEnd();
        }
    }
}

注意:虽然我很欣赏我正在学习的这段代码可能存在多个问题,打算在CodeReview上进行下一次迭代。就是说,随时提出建议,但是现在这对我来说是一个学习练习。 TIA

Note: While I appreciate there may be multiple issues with this code I'm learning and intend to put the next iteration up on CodeReview. That said, feel free to offer suggestions but right now this is a learning exercise for me. TIA

推荐答案

您的工作代码已解压缩 compressedMemoryStream 。您的破损代码解压缩了从 compressedMemoryStream 创建的字符串

Your working code decompressed compressedMemoryStream. Your broken code decompressed a string created from compressedMemoryStream.

前面的问题,压缩的结果不是文本。如果必须将其表示为文本,则应使用Base64或十六进制。但是只是像从UTF-8编码的文本一样读取它(这就是您现在正在做的)就根本行不通。

As I said in your previous question, the result of compression is not text. If you must represent it as text, you should use Base64 or hex. But just reading from it as if it's UTF-8-encoded text (which is what you're doing now) simply will not work.

StreamCompress 方法应该是 byte [] 。这很容易实现:

The result of your StreamCompress method should probably be a byte[]. That's easy to achieve:

// Note: changed input type to just Stream to make it more general
private static byte[] StreamCompress(Stream input, string optionalPassword)
{
    SevenZipCompressor.SetLibraryPath(@"C:\Temp\7za64.dll");
    SevenZipCompressor SevenZip = new SevenZipCompressor();
    SevenZip.CompressionMethod = CompressionMethod.Ppmd;
    SevenZip.CompressionLevel = global::SevenZip.CompressionLevel.Ultra;
    SevenZip.ScanOnlyWritable = true;

    var output = new MemoryStream();
    SevenZip.CompressStream(input, output, optionalPassword);
    // You don't even need to rewind when you call ToArray
    return output.ToArray();
}

要解压缩,只需创建一个 MemoryStream 将该字节数组包装为许多选项之一。

When you want to decompress, you can just create a MemoryStream to wrap that byte array, as one of many options.

如果确实需要结果作为字符串,则可以调用 Convert.ToBase64String ,然后稍后调用 Convert.FromBase64String 取回原始字节。

If you really need the result as a string, you can then call Convert.ToBase64String, then later call Convert.FromBase64String to get back the original bytes. This will not lose information, unlike your current approach.

我还应该指出,除非您想要7zip特定的压缩,否则很多都是纯托管的压缩库也可用。

I should also point out that unless you want 7zip-specific compression, there are plenty of purely-managed compression libraries available too.

这篇关于为什么?重构后C#错误:“流无效或未找到相应的签名。”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆