2

私のアプリでは、DataContractSerializerによって書き込まれたデータを解凍して、別のアプリのDeflate Streamを圧縮し、解凍されたデータを編集して、もう一度圧縮する必要があります。

解凍は正常に機能しますが、私が圧縮したデータでは機能しません。

問題は、これを行うと次のようになることです。byte [] result = Compressor.Compress(Compressor.Decompress(sourceData));

結果のバイト配列の長さは、sourceData配列とは異なります。

例えば:

    string source = "test value";
    byte[] oryg = Encoding.Default.GetBytes(source);

    byte[] comp = Compressor.Compress(oryg);
    byte[] result1 = Compressor.Decompress(comp);

    string result2 = Encoding.Default.GetString(res);

ここで、result1.Lengthは0で、result2はもちろん""です。

これが私のCompressorクラスのコードです。

public static class Compressor
{
    public static byte[] Decompress(byte[] data)
    {
        byte[] result;

        using (MemoryStream baseStream = new MemoryStream(data))
        {
            using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Decompress))
            {
                result = ReadFully(stream, -1);
            }
        }

        return result;
    }

    public static byte[] Compress(byte[] data)
    {
        byte[] result;

        using (MemoryStream baseStream = new MemoryStream())
        {
            using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Compress, true))
            {
                stream.Write(data, 0, data.Length);
                result = baseStream.ToArray();
            }
        }

        return result;
    }

    /// <summary>
    /// Reads data from a stream until the end is reached. The
    /// data is returned as a byte array. An IOException is
    /// thrown if any of the underlying IO calls fail.
    /// </summary>
    /// <param name="stream">The stream to read data from</param>
    /// <param name="initialLength">The initial buffer length</param>
    private static byte[] ReadFully(Stream stream, int initialLength)
    {
        // If we've been passed an unhelpful initial length, just
        // use 32K.
        if (initialLength < 1)
        {
            initialLength = 65768 / 2;
        }

        byte[] buffer = new byte[initialLength];
        int read = 0;

        int chunk;
        while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
        {
            read += chunk;

            // If we've reached the end of our buffer, check to see if there's
            // any more information
            if (read == buffer.Length)
            {
                int nextByte = stream.ReadByte();

                // End of stream? If so, we're done
                if (nextByte == -1)
                {
                    return buffer;
                }

                // Nope. Resize the buffer, put in the byte we've just
                // read, and continue
                byte[] newBuffer = new byte[buffer.Length * 2];
                Array.Copy(buffer, newBuffer, buffer.Length);
                newBuffer[read] = (byte)nextByte;
                buffer = newBuffer;
                read++;
            }
        }
        // Buffer is now too big. Shrink it.
        byte[] ret = new byte[read];
        Array.Copy(buffer, ret, read);
        return ret;
    }
}

できればこの事件を手伝ってください。よろしく、アダム

4

1 に答える 1

4

(編集:まだすべてのバイトをフラッシュしない可能性があるフラッシュの使用から、ここでのPhilの回答に従って、最初にdeflateが確実に破棄されるように切り替えました:Deflateを使用して文字列をzipおよびunzipします

バッキングストアからの読み取りを試みる前に、圧縮時にdeflateストリームが完全にフラッシュされ、deflateが圧縮を終了して最終バイトを書き込むことができるようにする必要があります。収縮蒸気を閉じるか、それを処分することで、これを達成できます。

public static byte[] Compress(byte[] data)
{
    byte[] result;

    using (MemoryStream baseStream = new MemoryStream())
    {
        using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Compress, true))
        {
            stream.Write(data, 0, data.Length);
        }
        result = baseStream.ToArray();  // only safe to read after deflate closed
    }

    return result;
}    

また、ReadFullyルーチンは非常に複雑に見え、バグがある可能性があります。1つは:

while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)

2番目のチャンクを読み取るときreadは、バッファーの長さよりも大きくなります。つまり、常に負の値がstream.Readに渡され、読み取るバイト数が示されます。私の推測では、2番目のチャンクを読み取ってゼロを返し、whileループから外れることはありません。

この目的には、JonバージョンのReadFullyをお勧めします。ストリームからバイト配列を作成する

于 2010-10-03T00:19:10.923 に答える