Откуда берется дополнительный символ в моем методе сжатия? - PullRequest
1 голос
/ 21 октября 2011

У меня был метод сжатия и распаковки, который использовался для добавления дополнительного пустого символа.Мне удалось это исправить, но я не уверен, почему исправление сработало, и надеюсь, что кто-нибудь сможет мне это объяснить.

Исправление (-1 из buffer.length в следующей строке):

System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length - 1), 0, gzBuffer, 0, 4)

Исходная строка:

System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length), 0, gzBuffer, 0, 4)

Функции:

Private Function Compress(ByVal bytes As Byte()) As Byte()
    Using ms As New MemoryStream()

        Using zip As New Ionic.Zlib.GZipStream(ms, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.BestCompression, True)
            zip.Write(bytes, 0, bytes.Length)
        End Using

        //ms.Position = 0
        Dim compressed As Byte() = ms.ToArray()

        Dim gzBuffer(compressed.Length + 4) As Byte
        System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length)
        System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length -1), 0, gzBuffer, 0, 4)

        Return gzBuffer
    End Using
End Function

Private Function DeCompress(ByVal bytes As Byte()) As Byte()

    Using ms As New MemoryStream()
        Dim msgLength As Integer = BitConverter.ToInt32(bytes, 0)
        ms.Write(bytes, 4, bytes.Length - 4)

        Dim buffer(msgLength) As Byte

        ms.Position = 0
        Dim offset As Integer = 0
        Using zip As New Ionic.Zlib.GZipStream(ms, Ionic.Zlib.CompressionMode.Decompress)
            While offset < buffer.Length - 1
                offset += zip.Read(buffer, offset, buffer.Length - offset)
            End While
        End Using

        Return buffer
    End Using
End Function

1 Ответ

2 голосов
/ 21 октября 2011

Это лучше, теперь длина не перезаписывает часть сжатых данных.

Теперь ваша проблема в том, что вы неправильно используете метод Stream.Read. Метод возвращает количество прочитанных байтов, которое может быть меньше количества запрошенных байтов, поэтому вы должны получить это возвращаемое значение и повторять чтение, пока у вас не будут все данные:

Dim offset as Integer = 0
Using zip As New Ionic.Zlib.GZipStream(ms, Ionic.Zlib.CompressionMode.Decompress)
  Do While offset < buffer.Length
    offset += zip.Read(buffer, offset, buffer.Length - offset)
  Loop
End Using

Кроме того, вместо записи байтового массива в поток памяти, просто создайте поток памяти из массива:

Using ms As New MemoryStream(bytes)

Вместо чтения потока памяти в массив, просто используйте метод ToArray:

Dim compressed As Byte() = ms.ToArray()

Edit:

Единственная проблема в коде была связана с тем, как массивы создаются в VB с использованием наивысшего индекса вместо размера, поэтому буфер следует создавать с помощью:

Dim buffer(msgLength - 1) As Byte

Используя свойство Position при чтении и записи потока памяти, вы можете избежать создания дополнительных буферов:

Private Function Compress(ByVal bytes As Byte()) As Byte()
  Using ms As New MemoryStream()
    ms.Position = 4
    Using zip As New GZipStream(ms, CompressionMode.Compress, True)
      zip.Write(bytes, 0, bytes.Length)
    End Using
    ms.Position = 0
    ms.Write(BitConverter.GetBytes(bytes.Length), 0, 4)
    Return ms.ToArray()
  End Using
End Function

Private Function DeCompress(ByVal bytes As Byte()) As Byte()
  Dim msgLength As Integer = BitConverter.ToInt32(bytes, 0)
  Using ms As New MemoryStream(bytes)
    Dim buffer(msgLength - 1) As Byte
    ms.Position = 4
    Dim offset As Integer = 0
    Using zip As New GZipStream(ms, CompressionMode.Decompress)
      While offset < buffer.Length
        offset += zip.Read(buffer, offset, buffer.Length - offset)
      End While
    End Using
    Return buffer
  End Using
End Function

(Примечание. В этом коде используется стандарт .NET GZipStream.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...