Как решить Gzip Magic Number Отсутствует
-
06-07-2019 - |
Вопрос
У меня есть строка, которую я распаковываю на сервере и загружаю на клиент с помощью класса WebClient. Когда я пытаюсь распаковать его, я получаю сообщение об ошибке, что магический номер отсутствует. Я пробовал оба класса GZipStream и методы ICSharpLib для решения этой проблемы, поэтому я в растерянности.
Сжатие / декомпрессия работает, если я пропускаю этап загрузки через WebClient (используя DownloadData, который возвращает данные в виде байта []), поэтому я могу только предположить, что существует некоторая проблема с усечением или повреждением данных, каким-то образом , но так как это сжатые данные, я не уверен, как это отладить.
Вот фрагмент кода, который, кажется, является оскорбительной частью:
byte[] response
try {
response = client.DownloadData(Constants.GetSetting("SyncServer"));
} catch {
MessageBox.Show("There was a problem synchronizing the data. Please try verify the supplied credentials or try again later.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
int rows = SQLiteAPI.ImportStatHistoryXML(CurrentUser.User, myCampus, Convert.ToBase64String(response));
public static int ImportStatHistoryXML(Person tempPerson, Campus tempCampus, string xmlFile) {
byte[] encryptedFile = Convert.FromBase64String(xmlFile);
MemoryStream memStream = new MemoryStream(encryptedFile);
memStream.ReadByte();
GZipInputStream stream = new GZipInputStream(memStream);
MemoryStream memory = new MemoryStream();
byte[] writeData = new byte[4096];
int size;
while (true) {
size = stream.Read(writeData, 0, writeData.Length);
if (size > 0) {
memory.Write(writeData, 0, size);
} else {
break;
}
}
stream.Close();
memory.Position = 0;
StreamReader sr = new StreamReader(memory);
string decompressed = sr.ReadToEnd();
DataSet tempSet = new DataSet();
StringReader xmlReader = new StringReader(decompressed);
tempSet.ReadXml(xmlReader);
DataTable statTable = tempSet.Tables["Stats"];
...more unrelated processing of the table
}
Любая помощь будет оценена. Постскриптум Я использую строку Base64, чтобы иметь возможность передавать туда и обратно через Интернет. На самом деле это может быть та область, в которой я ошибаюсь, поскольку раньше я не выполнял веб-запросов и ответов между настольным приложением и веб-службой.
Решение
Во-первых, я не думаю, что фрагмент допустим, поскольку DownloadString возвращает (как и ожидалось) строку.
Теперь правильно ли я понимаю, что он работает правильно, когда вы используете DownloadData, и неправильно, когда вы используете DownloadString? Это имеет смысл, поскольку недопустимо декодировать данные Gzip как Unicode.
РЕДАКТИРОВАТЬ:
Хорошо, ToBase64String и FromBase64String должны быть в порядке. Но если вы можете избежать этого и напрямую передать байт [], это будет хорошо.
public static int ImportStatHistoryXML(Person tempPerson, Campus tempCampus, byte[] compressedFile) {
Тогда вы избавитесь от первой строки функции (декодирование из base64). Обратите внимание, что мы переименовываем encryptedFile в сжатый файл.
Строка:
memStream.ReadByte();
не должно быть там. Вы читаете байт и отбрасываете его. Если все так, как мы ожидаем, этот байт равен 0x1F, часть магического числа gzip.
Тогда я думаю, что вы используете неправильный класс gzip. Вам нужен GZipStream . Он построен как:
GZipStream stream = new GZipStream(memStream, CompressionMode.Decompress);
Затем вы используете StreamReader непосредственно для этого:
StreamReader sr = new StreamReader(stream);
Было бы полезно, если бы вы знали кодировку, но, надеюсь, значение по умолчанию будет правильным. Тогда это кажется правильным оттуда. Итак, в целом мы получаем ниже. Р>
public static int ImportStatHistoryXML(Person tempPerson, Campus tempCampus, byte[] compressedFile) {
MemoryStream memStream = new MemoryStream(compressedFile);
GZipStream gzStream = new GZipStream(memStream, CompressionMode.Decompress);
StreamReader sr = new StreamReader(gzStream);
string decompressed = sr.ReadToEnd();
DataSet tempSet = new DataSet();
StringReader xmlReader = new StringReader(decompressed);
tempSet.ReadXml(xmlReader);
DataTable statTable = tempSet.Tables["Stats"];
//...
}