Я хотел бы сжать строку, определенную вручную, до 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 и распечатать его, не создавая и не читая новые файлы?
Поскольку вы уже используете 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
должна быть подкреплена массивом байтов или своего рода потоком. Вы можете использовать следующую реализацию:
Получение SevenZArchiveEntry
из чего-то, кроме файла:
Хотя класс SevenZOutputFile
, похоже, не предоставляет для этого возможности, если вы посмотрите на его исходный код, вы заметите, что вы можете вручную создать SevenZArchiveEntry
без какого-либо посредника, поскольку он имеет пустой конструктор. Вам придется «притвориться», что это все еще настоящий файл, но это не должно быть проблемой.
Исходный код SevenZArchiveEntry
:
Это немного оффтоп, но если предположить, что 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);
можете ли вы поделиться кодом для сжатия определенной строки до 7z и преобразовать ее в массив байтов.