2015-09-12 3 views
1

Я создал приложение для Android, и на самом деле все работает нормально.Связана ли эта неправильная кодировка функций?

Я получаю данные с сервера через WebSockets, но перед его отправкой клиенту он сжимается с GZIPOutputStream на сервере, как это:

public class GZip { 

    public static ByteBuffer compress(String msg) { 
     if(msg == null || msg.length() == 0) 
      return null;    
     ByteBuffer bytes = null; 
     try { 
      ByteArrayOutputStream obj=new ByteArrayOutputStream(); 
      GZIPOutputStream gzip = new GZIPOutputStream(obj); 
      gzip.write(msg.getBytes("UTF-8")); 
      gzip.close(); 
      bytes = ByteBuffer.wrap(obj.toByteArray()); 
     } catch(Exception e) { 
      return null; 
     } 
     return bytes; 
    } 

} 

На стороне клиента (Android приложение) String msg распаковывается по:

private static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); 
public static String decompress(byte[] compressed) { 
     String msg = null; 
     try { 
      final int BUFFER_SIZE = 32; 
      ByteArrayInputStream is = new ByteArrayInputStream(compressed); 
      GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE); 
      StringBuilder string = new StringBuilder(); 
      byte[] data = new byte[BUFFER_SIZE]; 
      int bytesRead; 
      while ((bytesRead = gis.read(data)) != -1) { 
       string.append(new String(data, 0, bytesRead, UTF8_CHARSET)); 
      } 
      gis.close(); 
      is.close(); 

      msg = string.toString(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return msg; 
    } 

Таким образом, от моего понимания это не должно производить никаких проблем при dealiing с не US-ASCII символов, так как все ен- или правильно декодировать в UTF-8.

Например, рассмотрите слово Eckstoß, которое содержит специальный символ ß. Так вот пример из трех TextViews в Android приложение, которое одновременно отображать слово Eckstoß

enter image description here

Что я нахожу очень странным здесь, является тот факт, что все три версии слова Exkstoß имеют собственные ванные/декодируется как описано выше. Однако в одной строке оно отображается неправильно.

Однако, это даже будет (IMHO) weireder. Это фактически список, и когда (из-за прокрутки) TextView исчезает и снова появляется (например, вниз по экрану), тогда (иногда) символы затем отображаются правильно.

Что может вызвать эту странную проблему?

+0

У меня возникло ощущение, что у вас нет проблем с передачей контента, возможно, с сообщением, которое вы генерируете, или, возможно, с созданием пользовательского интерфейса. Когда вы отлаживаете сообщение после декомпрессии, все выглядит нормально? –

ответ

0

Это всего лишь предположение.

Читает распакованные байты в блоках по 32 байт, а затем преобразовать из байт в utf8 символы с этим фрагментом:

new String(data, 0, bytesRead, UTF8_CHARSET) 

Может быть проблемой, что 32 байта data не совпадает с границами символов ? То есть специальные символы кодируются двумя или более байтами, но не все байты последнего символа находятся в буфере data.

Эта теория не объясняет, почему прокрутка даст вам разные результаты.

0

Когда символ Юникода кодируется в UTF-8, число результирующих байтов равно 1, 2, 3 или 4. Например, когда японский символ U+3042 кодируется в UTF-8, число результирующих байтов равно 3 (0xE3, 0x81, 0x82). Другим примером является U+20BB7. Этот символ Юникода преобразуется в 4 байта (0xF0, 0xA0, 0xAE, 0xB7), когда он кодируется в UTF-8.

Предположим, что gis.read(data) пытается прочитать [0xF0, 0xA0, 0xAE, 0xB7] (= его юникодное скалярное значение U + 20BB7). Есть ли какой-либо гарант, что gis.read(data) всегда возвращает 4? Нет. Если он возвращает 2, например, new String(data, 0, 2, UTF_8_CHARSET) не может проанализировать данный массив байтов как действительную последовательность UTF-8.

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