2013-11-15 5 views
0

У меня есть приложение, которое отправляет данные, полученные из источника данных на моем ПК (скажем, Excel или Access) в принимающее приложение на планшет Android. Я на этапе тестирования сжимаю данные перед отправкой, а затем распаковываю их после получения. Я использую GZIP для этого, с DotNetZip на стороне C# и встроенным классом GZIPInputStream на стороне Java.Отправка gzipped данных по сети с C# на Java

У меня возникли проблемы с тем, чтобы он работал правильно. Когда я делаю тест только с одной стороны (сжимаю и декомпрессию, чтобы увидеть, остались ли данные нетронутыми), все в порядке. Он работает как на C#, так и на Java. Но когда я добираюсь до точки отправки и получения данных, я сталкиваюсь с этой проблемой: «неизвестный формат (магический номер ef1f)». Я видел другие сообщения SO, где это обсуждалось, но ответы, похоже, не помогают.

Вот код, я использую для сжатия на C# стороне:

public void compressData() { 
    byte[] buffer = Ionic.Zlib.GZipStream.CompressBuffer(this.RawStreamData.ToArray()); 
    this.RawStreamData = new MemoryStream(buffer); 
} 

А вот код, я использую, чтобы распаковать на стороне Java. Поскольку данные считываются с помощью BufferedReader, я должен преобразовать из полукокса [] в байт [] первоначально:

public NetMessage decompressMsg(NetMessage nMsg) throws IOException { 
    ByteArrayOutputStream baOut = new ByteArrayOutputStream(); 
    OutputStreamWriter osWriter = new OutputStreamWriter(baOut); 
    osWriter.write(nMsg.getRawMsg()); //.getRawMsg() returns a char[] of the raw data 
    osWriter.close(); 
    ByteArrayInputStream baIn = new ByteArrayInputStream(baOut.toByteArray()); 
    GZIPInputStream gzIn = new GZIPInputStream(baIn); 
    byte[] buffer = new byte[128]; 
    int nReadBytes = gzIn.read(buffer); 
    String sDecompMsg = new String(buffer); 

    while (nReadBytes > -1) { 
     buffer = new byte[128]; 
     nReadBytes = gzInput.read(buffer); 
     String sTemp = new String(buffer); 
     sDecompMsg += sTemp; 
    } 

    nMsg.setRawMsg(sDecompMsg.toCharArray()); 

    return nMsg; 
} 

Он бросает исключение, когда я пытаюсь построить GZIPInputStream. Я уже знаю, как я реконструирую сообщение из результирующего декомпрессированного буфера неправильно (от тестирования только на стороне Java), но это проблема, которую мне нужно достичь в первую очередь! :) Любая помощь будет оценена по достоинству. Я подозреваю, что это может иметь какое-то отношение к настройкам уровня сжатия; в C# я использую значение по умолчанию, но AFAIK не существует такого параметра на стороне Java. BufferedReader создается с кодировкой ASCII.

ответ

2

Поскольку данные считываются с помощью BufferedReader, я должен преобразовать из полукокса [] в байтах [] первоначально:

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

+0

'NetMessage' - это оболочка для сообщений данных, которые отправляются туда и обратно с ПК на планшет. Метод '.getRawMsg()' возвращает необработанные данные для сообщения как 'char []', что фактически сжато со стороны C#. Поскольку 'GZIPInputStream' требует использования базового потока, я использую' OutputStreamWriter' для преобразования из 'char []' в 'byte []'. Этот процесс превращает необработанные данные в текст? – Fam

+0

@ F.Ali: Если он возвращает данные как 'char []', это * not * необработанные данные - это текст. Исходные данные двоичные. Является ли 'NetMessage' под вашим контролем? Если это так, похоже, что он нуждается в исправлении. –

+0

Да, похоже, мне нужно будет переработать 'NetMessage', чтобы использовать' byte [] 'вместо этого. Спасибо. – Fam

2

«BufferedReader создан с кодировкой ASCII». Тогда очевидно, что ваша программа не может работать. Сжатые данные GZip используют весь бит байтов, поэтому интерпретация его как ASCII приводит к потере данных. Кроме того, вы преобразовываете символы обратно в байтовый массив без указания кодировки, поэтому используется по умолчанию система, которая не контролируется вашей программой. Вы должны использовать одну и ту же кодировку для обоих преобразований, и она должна сохранять всю информацию обо всех битах, например. использование iso-latin-1 будет выполнять эту работу. Но было бы гораздо лучше исправить этот недостаток преобразования байтов в символы и обратно в байты.

Смежные вопросы