java (Android): попробуйте сжатый ввод-вывод и потерпели неудачу

#java #android #zip #compression

#java #Android #zip #сжатие

Вопрос:

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

 public static void outCompressNIO(String outFile, String src) {
    FileChannel fc = null;
    GZIPOutputStream gz = null;
    try {
        fc = new FileOutputStream(outFile).getChannel();
        gz = new GZIPOutputStream(Channels.newOutputStream(fc));
        gz.write(src.getBytes());
        gz.flush();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            gz.close();
            fc.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public static void inCompressNIO(String inFile) {
    FileChannel fc = null;
    GZIPInputStream gz = null;
    try {
        fc = new FileInputStream(inFile).getChannel();
        gz = new GZIPInputStream(Channels.newInputStream(fc));
        byte fileContent[] = new byte[1024];
        StringBuilder sb = new StringBuilder();
        while ((gz.read(fileContent)) != -1) {
            sb.append(new String(fileContent));
        }
        System.out.println(sb.toString());
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            gz.close();
            fc.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  

Но строка, которую я получил обратно из сжатого файла, отличается от исходной от места к месту. Кто-нибудь знает почему? Кстати, моя главная цель состоит в том, что мне нужно эффективно сжать длинную строку (около 15M) в файл и распаковать ее в основную память на Android. Я пытался просто использовать Object IO в Java для достижения этого, это достигается без проблем на моем ПК. Но на Android, если размер объекта string превышает 3 м, требуется вечность, чтобы преобразовать объект, который я получил из ObjectInputStream, в строку. Поэтому я пробую другие способы избежать приведения. Вышеописанное — одна из моих попыток, но поскольку я мало знаю о NIO, я, вероятно, делаю все неправильно, поэтому, если кто-нибудь знает более эффективный способ добиться этого, пожалуйста, укажите мне правильное направление, большое спасибо.

Ответ №1:

  1. Выбросьте FileChannel и просто используйте FileInputStream. Вы используете java.io здесь действительно нет NIO, за исключением случаев, когда вы получаете канал, так что вы просто делаете это сложным способом.
  2. Укажите имя кодировки в String.getBytes().
  3. Сохраните результат чтения (байт[]) в переменной. Используйте эту переменную при добавлении к sb, т.е. sb.append(новая строка (буфер, 0, количество, кодировка));
  4. Еще лучше, оберните InputStreamReader вокруг GZIPInputStream, созданного с тем же именем кодировки, считайте в массив char[], а не в массив byte[], и используйте sb.append(CharBuffer, 0, count). Это позволяет избежать предположения, которое вы в настоящее время делаете, что прочитанные байты составляют целую строку.