Java 7zip сжатие строки

Я хотел бы сжать строку, определенную вручную, до 7z в Java. Тогда я мог бы преобразовать его в base64. Я нашел много примеров сжатия файлов до 7z и последующего сохранения в новый файл.

Я просто пробую следующий код, и он правильно принимает файл и сжимает его:

private static void addToArchiveCompression(SevenZOutputFile out, File file, String dir) throws IOException {
        String name = dir + File.separator + file.getName();
        if (file.isFile()){
            SevenZArchiveEntry entry = out.createArchiveEntry(file, name);
            out.putArchiveEntry(entry);

            FileInputStream in = new FileInputStream(file);
            byte[] b = new byte[1024];
            int count = 0;
            while ((count = in.read(b)) > 0) {
                out.write(b, 0, count);
            }
            out.closeArchiveEntry();

        } else if (file.isDirectory()) {
            File[] children = file.listFiles();
            if (children != null){
                for (File child : children){
                    addToArchiveCompression(out, child, name);
                }
            }
        } else {
            System.out.println(file.getName() + " is not supported");
        }
    }  

Но как я могу сжать строку, определенную вручную, до 7z и преобразовать ее в byte[]? Итак, я могу преобразовать byte[] в base64 и распечатать его, не создавая и не читая новые файлы?

можете ли вы поделиться кодом для сжатия определенной строки до 7z и преобразовать ее в массив байтов.

Nizam 05.09.2019 13:50
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
1
754
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Поскольку вы уже используете Commons-сжатие для сжатия 7zip, вы можете создать экземпляр SevenZOutputFile(SeekableByteChannel) с SeekableInMemoryByteChannel, который упаковывает массив байтов. Согласно javadoc:

A SeekableByteChannel implementation that wraps a byte[].

When this channel is used for writing an internal buffer grows to accommodate incoming data. A natural size limit is the value of Integer.MAX_VALUE. Internal buffer can be accessed via array().

Что-то типа:

SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(new byte[1024]);
SevenZOutputFile out = new SevenZOutputFile(channel);
// modified addToArchiveCompression(out, ...); for String
// encode channel.array() to Base64

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

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

Преобразование строки в данные для 7z:

Один из вариантов — использовать ByteArrayInputStream вместо FileInputStream. ByteArrayInputStream должен быть инициализирован байтами, соответствующими строке.

См. следующую статью для примера того, как сделать это преобразование:

https://www.baeldung.com/convert-string-to-input-stream

Преобразование выходных байтов в Base64:

Существует несколько подходов, подробно описанных в этой ветке StackOverflow:

Как преобразовать массив байтов в Base64 в Java?

Вывод 7z в память вместо File:

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

https://commons.apache.org/proper/commons-compress/apidocs/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.html

Получение SevenZArchiveEntry из чего-то, кроме файла:

Хотя класс SevenZOutputFile, похоже, не предоставляет для этого возможности, если вы посмотрите на его исходный код, вы заметите, что вы можете вручную создать SevenZArchiveEntry без какого-либо посредника, поскольку он имеет пустой конструктор. Вам придется «притвориться», что это все еще настоящий файл, но это не должно быть проблемой.

Исходный код SevenZArchiveEntry:

https://commons.apache.org/proper/commons-compress/apidocs/src-html/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.html

Это немного оффтоп, но если предположить, что LZMA является частью 7zip, это может вам помочь:

public static byte[]compress(byte[]arr,int level){
    try {
        ByteArrayOutputStream compr = new ByteArrayOutputStream();
        LZMA2Options options = new LZMA2Options();
        options.setPreset(level); // play with this number: 6 is default but 7 works better for mid sized archives ( > 8mb)
        XZOutputStream out = new XZOutputStream(compr, options);
        out.write(arr);
        out.finish();
        return compr.toByteArray();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

public static byte[]decompress(byte[]bts){
    try {
        ByteArrayInputStream bis = new ByteArrayInputStream(bts);
        XZInputStream is = new XZInputStream(bis);
        ByteArrayInputStream decomp = new ByteArrayInputStream(is.readAllBytes());
        ObjectInputStream ois = new ObjectInputStream(decomp);
        byte data[]= (byte[]) ois.readObject();
        return data;
    } catch (IOException | ClassNotFoundException e) {
        throw new RuntimeException(e);
    }
}

Мавен зависимость:

    <dependency>
        <groupId>org.tukaani</groupId>
        <artifactId>xz</artifactId>
        <version>1.8</version>
    </dependency>

преобразовать вашу строку в byte[] с помощью s.getBytes(StandardCharsets.UTF_8);

Другие вопросы по теме