GZip vs Deflate vs Zlib — Форматы и заголовки
Вы пытаетесь распаковать данные и получаете ошибки "invalid header" или "incorrect header check". Или, возможно, сжатые данные работают с одним инструментом, но не работают с другим. Проблема? GZip, Deflate и Zlib используют один и тот же базовый алгоритм сжатия (DEFLATE), но оборачивают его в разные заголовки и контрольные суммы. Понимание этих различий форматов критически важно для отладки проблем со сжатием, работы с API и выбора правильного формата сжатия.
Ядро: Алгоритм DEFLATE
В основе всех трёх форматов лежит алгоритм сжатия DEFLATE, определённый в RFC 1951. DEFLATE объединяет LZ77 (сжатие со скользящим окном) с кодированием Хаффмана для достижения эффективного сжатия данных. Это тот же алгоритм, который используется в ZIP файлах, PNG изображениях и HTTP-сжатии.
DEFLATE создаёт необработанный поток сжатых данных без заголовков, контрольных сумм и метаданных об исходных данных. Этот необработанный формат эффективен, но требует дополнительной обёртки для практического использования.
Формат #1: GZip (RFC 1952)
GZip — самый распространённый формат, с которым вы столкнётесь. Он оборачивает сжатые DEFLATE данные с:
- 10-байтовым заголовком: Начинается с магических байтов
1F 8B - Метаданными: Метод сжатия, флаги, временная метка, тип ОС
- Опциональными дополнениями: Исходное имя файла, комментарий, дополнительные поля
- Сжатые DEFLATE данные
- 8-байтовым футером: Контрольная сумма CRC-32 + несжатый размер (mod 2^32)
Структура заголовка GZip
Байт 0-1: 1F 8B # Магическое число (идентифицирует формат GZip)
Байт 2: 08 # Метод сжатия (08 = DEFLATE)
Байт 3: Флаги # Опциональные функции (имя файла, комментарий и т.д.)
Байт 4-7: Временная метка # Время модификации (Unix timestamp)
Байт 8: Доп. флаги # Индикатор уровня сжатия
Байт 9: ОС # Операционная система (0=FAT, 3=Unix, 11=NTFS)
... [опционально] # Имя файла, комментарий, дополнительные данные
... DEFLATE данные # Сжатая полезная нагрузка
... CRC-32 # 4 байта: контрольная сумма несжатых данных
... Размер # 4 байта: несжатый размер mod 2^32Когда используется GZip
- HTTP-сжатие:
Content-Encoding: gzip - Сжатие файлов: Файлы
.gz(например,archive.tar.gz) - Утилита командной строки Gzip:
gzip/gunzip - Git объекты: Сжимаются в формате GZip
Пример GZip
# Исходный текст
"Hello, World!"
# Сжатый GZip (hex):
1F 8B 08 00 00 00 00 00 00 03 F3 48 CD C9 C9 D7
51 08 CF 2F CA 49 51 04 00 D0 C3 4A EC 0D 00 00 00
# Разбор:
1F 8B - Магическое число GZip
08 - Сжатие DEFLATE
00 - Нет флагов
00 00 00 00 - Нет временной метки
00 - Сжатие по умолчанию
03 - ОС Unix
... - Сжатые DEFLATE данные
D0 C3 4A EC - Контрольная сумма CRC-32
0D 00 00 00 - Несжатый размер (13 байт)Формат #2: Zlib (RFC 1950)
Zlib похож на GZip, но с более простой структурой заголовка. Он оборачивает сжатые DEFLATE данные с:
- 2-байтовым заголовком: Метод сжатия и флаги
- Сжатыми DEFLATE данными
- 4-байтовым футером: Контрольная сумма Adler-32 (быстрее чем CRC-32)
Структура заголовка Zlib
Байт 0: CMF # Метод сжатия и флаги
Биты 0-3: CM = 8 # Метод сжатия (8 = DEFLATE)
Биты 4-7: CINFO # Размер окна (log2(window) - 8)
Байт 1: FLG # Флаги
Биты 0-4: FCHECK # Контрольная сумма заголовка
Бит 5: FDICT # Флаг предустановленного словаря
Биты 6-7: FLEVEL # Уровень сжатия
... DEFLATE данные # Сжатая полезная нагрузка
... Adler-32 # 4 байта: контрольная сумма несжатых данныхКогда используется Zlib
- PNG изображения: Каждый PNG-чанк сжат Zlib
- PDF файлы: Встроенные потоки используют Zlib-сжатие
- Модуль Python zlib: Формат по умолчанию
- Java Deflater/Inflater: Формат по умолчанию
- OpenSSL: Формат сжатия по умолчанию
Пример Zlib
# Исходный текст
"Hello, World!"
# Сжатый Zlib (hex):
78 9C F3 48 CD C9 C9 D7 51 08 CF 2F CA 49 51 04
00 1F 9E 04 6A
# Разбор:
78 - CMF: DEFLATE, окно 32K
9C - FLG: Сжатие по умолчанию, контрольная сумма
... - Сжатые DEFLATE данные
1F 9E 04 6A - Контрольная сумма Adler-32Формат #3: Необработанный DEFLATE
Необработанный DEFLATE — это просто поток сжатых данных без заголовков или контрольных сумм вообще. Это самый компактный формат, но требует внешнего знания о данных для правильной распаковки и проверки.
Когда используется необработанный DEFLATE
- HTTP-сжатие:
Content-Encoding: deflate(технически должен быть Zlib, но некоторые серверы отправляют необработанный DEFLATE) - ZIP файлы: Отдельные записи используют необработанный DEFLATE (заголовки/контрольные суммы находятся в структуре ZIP)
- 7-Zip: Метод DEFLATE использует необработанный формат
Пример необработанного DEFLATE
# Исходный текст
"Hello, World!"
# Сжатый необработанный DEFLATE (hex):
F3 48 CD C9 C9 D7 51 08 CF 2F CA 49 51 04 00
# Нет заголовка, нет футера, только сжатые данныеТаблица сравнения форматов
| Функция | GZip | Zlib | Raw DEFLATE |
|------------------|-----------|-----------|-------------|
| Размер заголовка | 10+ байт | 2 байта | 0 байт |
| Контр. сумма | CRC-32 | Adler-32 | Нет |
| Метаданные | Да | Минимум | Нет |
| Накладные расх. | ~18 байт | ~6 байт | 0 байт |
| Магич. байты | 1F 8B | 78 XX | Нет |
| Инфо о размере | Да | Нет | Нет |
| Врем. метка | Да | Нет | Нет |
| RFC | 1952 | 1950 | 1951 |Почему инструменты дают сбой: Несоответствие формата
Самая распространённая ошибка сжатия — попытка распаковать данные с неправильным ожиданием формата:
Ошибка #1: "incorrect header check"
Вы пытаетесь распаковать данные GZip как Zlib (или наоборот). Декомпрессор читает первые два байта как заголовок Zlib, и контрольная сумма не проходит проверку.
# Пример Python: Неправильный формат
import zlib
gzip_data = b'\x1f\x8b\x08...' # Формат GZip
zlib.decompress(gzip_data)
# Ошибка: zlib.error: Error -3 while decompressing: incorrect header checkРешение: Используйте zlib.decompress(data, wbits=16+zlib.MAX_WBITS) для GZip или gzip.decompress()
Ошибка #2: "invalid stored block lengths"
Вы пытаетесь распаковать данные Zlib как необработанный DEFLATE (или наоборот).
# Пример Python: Отсутствующий заголовок
import zlib
zlib_data = b'\x78\x9c...' # Формат Zlib
zlib.decompress(zlib_data, wbits=-zlib.MAX_WBITS) # Режим raw DEFLATE
# Ошибка: zlib.error: Error -5 while decompressing: incomplete or truncated streamРешение: Используйте положительный wbits для Zlib, отрицательный для необработанного DEFLATE
Ошибка #3: "invalid distance too far back"
Вы распаковываете с неправильным размером окна или данные повреждены.
API сжатия в разных языках программирования
Python
import zlib
import gzip
# Формат GZip
gzip_data = gzip.compress(b"Hello") # Создать GZip
original = gzip.decompress(gzip_data) # Распаковать GZip
# Формат Zlib (по умолчанию)
zlib_data = zlib.compress(b"Hello") # Создать Zlib
original = zlib.decompress(zlib_data) # Распаковать Zlib
# Необработанный DEFLATE
deflate_data = zlib.compress(b"Hello", wbits=-zlib.MAX_WBITS)
original = zlib.decompress(deflate_data, wbits=-zlib.MAX_WBITS)
# Автоопределение формата
def decompress_any(data):
# Попробовать GZip
if data[:2] == b'\x1f\x8b':
return gzip.decompress(data)
# Попробовать Zlib
elif data[:1] == b'\x78':
return zlib.decompress(data)
# Попробовать raw DEFLATE
else:
return zlib.decompress(data, wbits=-zlib.MAX_WBITS)JavaScript (Node.js)
const zlib = require('zlib');
// Формат GZip
const gzipData = zlib.gzipSync(Buffer.from('Hello'));
const original = zlib.gunzipSync(gzipData);
// Формат Zlib
const zlibData = zlib.deflateSync(Buffer.from('Hello'));
const original = zlib.inflateSync(zlibData);
// Необработанный DEFLATE
const deflateData = zlib.deflateRawSync(Buffer.from('Hello'));
const original = zlib.inflateRawSync(deflateData);Java
import java.util.zip.*;
// Формат Zlib (по умолчанию)
Deflater deflater = new Deflater();
deflater.setInput(data);
deflater.finish();
byte[] zlibData = new byte[1024];
int size = deflater.deflate(zlibData);
// Необработанный DEFLATE
Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true); // nowrap=true
// ... то же, что и выше
// Формат GZip
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzos = new GZIPOutputStream(baos);
gzos.write(data);
gzos.close();
byte[] gzipData = baos.toByteArray();Путаница с HTTP Content-Encoding
HTTP-заголовок Content-Encoding: deflate неоднозначен. Согласно RFC 2616, он должен использовать формат Zlib, но многие реализации используют вместо этого необработанный DEFLATE.
Что ожидают браузеры
Content-Encoding: gzip— Формат GZip (наиболее распространён, лучше всего поддерживается)Content-Encoding: deflate— Формат Zlib (спецификация RFC) ИЛИ необработанный DEFLATE (распространённая ошибка)Content-Encoding: br— Brotli (новее, лучше сжатие)
Лучшая практика для HTTP
Всегда используйте GZip для HTTP-сжатия. Он универсально поддерживается, чётко определён и избегает неоднозначности deflate.
# Конфигурация Nginx
gzip on;
gzip_types text/plain text/css application/json application/javascript;
# Конфигурация Apache
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml
</IfModule>Определение формата сжатия
Вы можете определить формат, проверив первые несколько байтов:
function detectFormat(data) {
if (data.length < 2) return 'unknown';
// Проверить магическое число GZip
if (data[0] === 0x1f && data[1] === 0x8b) {
return 'gzip';
}
// Проверить заголовок Zlib
// Байт CMF: 0x78 обычен (DEFLATE с окном 32K)
// Байт FLG варьируется, но контрольная сумма заголовка должна быть корректной
if (data[0] === 0x78 && (data[0] * 256 + data[1]) % 31 === 0) {
return 'zlib';
}
// Может быть raw DEFLATE (надёжное определение невозможно)
return 'raw-deflate (или неизвестно)';
}
// Примеры
detectFormat([0x1f, 0x8b, 0x08, ...]); // 'gzip'
detectFormat([0x78, 0x9c, ...]); // 'zlib'
detectFormat([0x78, 0xda, ...]); // 'zlib' (более высокое сжатие)
detectFormat([0xf3, 0x48, ...]); // 'raw-deflate (или неизвестно)'Уровни сжатия и компромиссы
Все три формата поддерживают уровни сжатия (обычно 0-9 или 1-9, где выше = лучше сжатие, но медленнее):
- Уровень 0: Без сжатия (только хранение) — быстро, но без экономии места
- Уровень 1-3: Быстрое сжатие — хорошо для данных в реальном времени
- Уровень 6: По умолчанию — сбалансированная скорость и сжатие
- Уровень 9: Максимальное сжатие — медленно, но лучшее соотношение
Сравнение степени сжатия
Для типичных текстовых данных (таких как JSON или HTML):
- GZip уровень 6: ~70-80% сжатие (в 3-5 раз меньше)
- GZip уровень 9: ~75-85% сжатие (немного лучше, гораздо медленнее)
- Brotli уровень 11: ~80-90% сжатие (лучше для статических файлов)
Реальный сценарий отладки
Вы загружаете сжатые API-ответы и получаете ошибки декомпрессии. Вот как отладить:
Шаг 1: Захватить необработанные данные
# Пример Python
import requests
response = requests.get('https://api.example.com/data',
headers={'Accept-Encoding': 'gzip'})
# Необработанные сжатые данные
compressed = response.content
# Проверить заголовок Content-Encoding
print(response.headers.get('Content-Encoding')) # 'gzip' или 'deflate'
# Проверить первые байты
print(compressed[:10].hex()) # '1f8b08...' = GZipШаг 2: Определить формат
# Проверить магические байты
if compressed[:2] == b'\x1f\x8b':
print("Формат: GZip")
data = gzip.decompress(compressed)
elif compressed[:1] == b'\x78':
print("Формат: Zlib")
data = zlib.decompress(compressed)
else:
print("Формат: Raw DEFLATE (или неизвестно)")
try:
data = zlib.decompress(compressed, wbits=-zlib.MAX_WBITS)
except:
print("Тоже не raw DEFLATE!")Шаг 3: Проверить декомпрессию
# Проверить, выглядят ли распакованные данные корректно
print(f"Распакованный размер: {len(data)} байт")
print(f"Первые 100 символов: {data[:100]}")
# Попробовать распарсить как JSON, если ожидается
import json
try:
parsed = json.loads(data)
print("Корректный JSON!")
except:
print("Не корректный JSON - возможно всё ещё сжато или повреждено")Использование инструментов сжатия
При работе со сжатыми данными используйте инструменты, поддерживающие все три формата:
- GZip Компрессор/Декомпрессор — Сжатие и распаковка текста в формате GZip
- Серверный процессор GZip — Высокопроизводительное сжатие для больших файлов
Инструмент GZip в DevToys Pro поддерживает:
- Форматы GZip, Zlib и необработанный DEFLATE
- Автоматическое определение формата
- Настраиваемые уровни сжатия
- Кодирование Base64 для передачи
- Сообщения об ошибках при неудаче декомпрессии
Лучшие практики
- Используйте GZip для HTTP и сжатия файлов — наиболее широко поддерживается
- Используйте Zlib для встроенного сжатия — PNG, PDF, внутренние структуры данных
- Избегайте необработанного DEFLATE — отсутствие контрольной суммы делает обнаружение повреждения невозможным
- Всегда проверяйте контрольные суммы — обнаруживайте повреждённые данные на ранней стадии
- Документируйте выбор формата — предотвратите проблемы интеграции
- Тестируйте с несжимаемыми данными — убедитесь, что ваш код корректно обрабатывает расширение
- Рассмотрите Brotli для статических файлов — лучше сжатие, чем GZip
Типичные ошибки
- Предположение, что "deflate" означает raw DEFLATE — должен быть Zlib, но не всегда
- Не проверять магические байты — приводит к загадочным ошибкам декомпрессии
- Игнорирование ошибок контрольной суммы — повреждённые данные могут вызвать проблемы безопасности
- Использование неправильного размера окна — вызывает ошибки "invalid distance"
- Сжатие уже сжатых данных — тратит CPU и фактически увеличивает размер
Ключевые выводы
- GZip, Zlib и необработанный DEFLATE используют один алгоритм DEFLATE
- GZip: 10-байтовый заголовок + CRC-32, наиболее распространён для файлов и HTTP
- Zlib: 2-байтовый заголовок + Adler-32, используется в PNG, PDF и многих библиотеках
- Необработанный DEFLATE: без заголовков или контрольных сумм, используется в ZIP файлах
- Определяйте формат по магическим байтам: 0x1f8b = GZip, 0x78XX = Zlib
- HTTP-кодирование "deflate" неоднозначно — придерживайтесь GZip
- Всегда используйте контрольные суммы для обнаружения повреждённых данных
Связанные инструменты:
- GZip Компрессор/Декомпрессор — Сжатие и распаковка текста с GZip
- Серверный процессор GZip — Высокопроизводительное сжатие для больших файлов
- Кодировщик Base64 — Кодирование сжатых данных для передачи