Есть ли лучшая библиотека сжатия для строк, чем DotNetZip или LZMA? - PullRequest
5 голосов
/ 20 августа 2011

У меня есть строка данных размером чуть более 800 символов, которую я пытаюсь сжать, чтобы использовать в QR-коде (я хотел бы, по крайней мере, 50%, но, вероятно, был бы рад, если бы я получил ее меньше, чемсемьсот).Вот пример строки, которую я пытаюсь сжать, которая содержит 841 символ:

+hgoSuJm2ecydQj9mXXzmG6b951L2KIl0k9VGzIEtLztuWO2On9rt7DUlH0lXzG4iJ1yK0fA
97mDyclKSttIZXOxSPBf85LEN4PUUqj65aio5qwZttZSZ64wpnMFg/7Alt1R39IJvTmeYfBm
Tuc1noMMcknlydFocwI8/sk2Sje5MR/nYNX0LPkQhzyi5vFJdrndqAgXYULsYrB3TJDAwvgs
Kw9C5EJnrlqcb21zg17O2gU/C8KY0pz9RPzUl1Sb0rCP8iZCeis4YbQ5tuUppOfnO/X0Mosv
SOQJ/bF9juKW8ocnQvNjsNxGV1gPkWWtiU2Old7Qm7FLDqL6kQKrq356yifs0NiMVGdvAg32
eugewuttCugoZASYOpQdwPu1jMxVO1fzF3zEy5w6tDlcfA2DZwa+un9/k8XZWAO/KVExy68q
UtVRQxsIOKgpl/2tNw5DBAKbykKIkmizbsA2xtzqnYqld4kOdNMJh3YjlqWF9Bt8MZo7a+Q6
jgayr2rjpyIptc599DGtvp68ZNQ64TKNmiMnnyGMo3E+xW34G3RrsYnHGm+xJoLKoOJhacDu
oZke1ycJgQv+Y61WPrvtFOVBxV5rvSzO0+8px5AWN3uCrrw1RmT5N14IVhh6BOtRjsifqIB2
dAKxzBNsvbXm1SzkuyqYiMnp5ivy3m2mPwc9GLsykx0FRIkhCYO8ins9E5ot9QvVnE155MFA
8FVwsP5uNdOF4EzQS2/h2QK3zb5Yq4Nftlo605Dd5vuVN/A7CUN38DaAKBxDKgqDzydfQnZw
R0hTfMHNLgBJKNDSpz2P6almGlUJtXT6IYmzuU2Iaion8ePG

Я уже пробовал следующие три библиотеки:

  1. Встроенный .NET GzipStream
  2. DotNetZip, в том числе
    • GzipStream
    • DeflateStream
  3. LZMA SDK из 7-zip

Я столкнулся с проблемой, когда сжатие фактически делает строку длиннее .Насколько я понимаю, у DeflateStream было меньше всего накладных расходов, но он все еще добавляет символы.Используя DotNetZip, я сказал ему использовать максимальное сжатие:

Imports Ionic.Zlib

Shared Function CompressData(data As Byte()) As Array

    Dim msCompressed As MemoryStream = New MemoryStream

    ' I'm not sure if the last parameter on this next function should be
    ' true (for LeaveOpen), but it doesn't seem to affect it either way.
    Dim deflated As DeflateStream = New DeflateStream(msCompressed, _
        CompressionMode.Compress, CompressionLevel.BestCompression, True)

    ' Write data to compression stream (which is linked to the memorystream)
    deflated.Write(data, 0, data.Length)
    deflated.Flush()
    deflated.Close()

    Return msCompressed.ToArray
End Function

Я только думаю, что это будет ухудшаться, поскольку у меня будет даже больше данных.Есть ли лучший алгоритм сжатия для строк такой длины?Сжатие обычно работает только на более длинных строках?К сожалению, данные таковы, что я не могу использовать автономные символы для фрагментов данных.

Кроме того, могу ли я использовать буквенно-цифровую кодировку для QR-кода или мне нужно использовать двоичный код?Не думаю, что смогу, по http://www.qrme.co.uk/qr-code-forum.html?func=view&catid=3&id=324,, но я бы хотел убедиться.

Спасибо за вашу помощь!

Ответы [ 4 ]

3 голосов
/ 23 августа 2011

На первый взгляд кажется, что вы пытаетесь взять некоторые данные и преобразовать их в QR-код следующим образом:

-> шифрование -> кодирование base64 -> сжатие -> создание QR-кода.

Я предлагаю использовать этот процесс вместо:

-> сжимать -> шифровать -> создавать QR-код.

Когда вы хотите и зашифровать, и сжать, почти все рекомендуют сжимать, а затем шифровать. (Поскольку шифрование работает так же хорошо, как со сжатыми данными, так и с несжатыми данными. Но сжатие обычно делает открытый текст короче, а зашифрованные файлы длиннее. Для более подробной информации смотрите: « Можно ли сжать зашифрованный файл? » « Сжать и затем зашифровать или наоборот? » « Составление сжатия и шифрования » " Сжать, затем зашифровать ленты " « Лучше ли зашифровать сообщение, а затем сжать его или наоборот? Что обеспечивает большую безопасность? » « Сжатие и шифрование файлов в Windows » « Шифрование и сжатие » « Зашифрованные или сжатые контейнеры, такие как zip и 7z, сначала сжимают или шифруют? » « При сжатии и шифровании, нужно ли сначала сжимать или сначала шифровать? », и др.)

«Могу ли я использовать буквенно-цифровую кодировку для QR-кода или мне нужно использовать двоичный код?»

Большинство алгоритмов шифрования выдают двоичный вывод, поэтому будет проще всего напрямую преобразовать его в двоичный код QR. Я полагаю, вы могли бы каким-то образом преобразовать зашифрованные данные во что-то, что могло бы обрабатывать буквенно-цифровое кодирование QR, но почему?

"Есть ли какой-нибудь лучший алгоритм сжатия"

Для зашифрованных данных, нет. (Почти наверняка) невозможно сжать хорошо зашифрованные данные, независимо от того, какой алгоритм вы используете.

Если вы сжимаете, а затем шифруете, как рекомендуется, то эффективность различных алгоритмов сжатия зависит от конкретных видов входных данных, а не от того, что вы делаете с ними после сжатия.

Какими данными являются ваши входные данные?

Если, гипотетически, ваши входные данные не содержат текст ASCII, возможно, вы могли бы использовать один из алгоритмов сжатия, упомянутых в « Действительно простое сжатие коротких строк » « Лучший алгоритм сжатия для коротких текстовых строк » « Сжатие строк ASCII в C » " Сжатие текста в Твиттере ".

Если, с другой стороны, ваши входные данные представляют собой какую-то фотографию, возможно, вы могли бы использовать один из многих алгоритмов сжатия, упомянутых в « проблема кодирования изображений в Twitter ».

3 голосов
/ 20 августа 2011

Этот ответ связан с ответом Гуффы.Он сказал, что QR-код может принимать двоичные данные, и это должно быть ограничением используемой вами библиотеки.

Я посмотрел исходный код библиотеки.Вы вызываете функцию кодирования правильно?Это содержимое функции кодирования

public virtual Bitmap Encode(String content, Encoding encoding)
{
    bool[][] matrix = calQrcode(encoding.GetBytes(content));
    SolidBrush brush = new SolidBrush(qrCodeBackgroundColor);
    Bitmap image = new Bitmap( (matrix.Length * qrCodeScale) + 1, (matrix.Length * qrCodeScale) + 1);
    Graphics g = Graphics.FromImage(image);
    g.FillRectangle(brush, new Rectangle(0, 0, image.Width, image.Height));
    brush.Color = qrCodeForegroundColor ;
    for (int i = 0; i < matrix.Length; i++)
    {
        for (int j = 0; j < matrix.Length; j++)
        {
            if (matrix[j][i])
            {
                g.FillRectangle(brush, j * qrCodeScale, i * qrCodeScale, qrCodeScale, qrCodeScale);
            }
        }
    }
    return image;
}

Первая строка (encoding.GetBytes (content)) преобразует строку в байты.

Получите исходный код, затем измените его, чтобы иметь эту функцию: "общедоступное виртуальное растровое кодирование (содержимое в байтах [])"

2 голосов
/ 20 августа 2011

Вы сравниваете разные компрессоры.Семейство Zip обычно использует статистическое сжатие, а семейство LZ - сокращение от Lempel-Ziv - словарное сжатие для удаления избыточности во входном тексте.Таким образом, сжатие работает путем удаления лишней информации.Он хорошо работает с текстовыми файлами и изображениями, не очень хорошо работает с аудио, видео и программными файлами.Для последнего есть сжатие с потерями, но не для программных файлов.Учитывая ваш пример строки, она содержит слишком много энтропии, чтобы хорошо сжиматься.Вы можете рассчитать информационную энтропию с помощью -log (p) + log (2), где p - это вероятность появления символа в вашем тексте.См. Также теорию информации и теорему Шеннона.

2 голосов
/ 20 августа 2011

Сжатие работает путем удаления избыточности в данных, но, похоже, что строка содержит случайные / зашифрованные данные, поэтому нет избыточности для удаления.

Однако это данные, закодированные с использованием base-64, поэтому каждый символ несет только шесть бит информации. Если вы сохраняете двоичные данные вместо кодировки base-64, это всего 631 байт.

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