Java: как получить строковое представление сжатого байтового массива? - PullRequest
1 голос
/ 19 мая 2010

Я хочу поместить сжатые данные в удаленный репозиторий.
Чтобы поместить данные в этот репозиторий, я могу использовать только метод, который принимает имя ресурса и его содержимое в виде строки. (например, data.txt + "Привет, мир").
Репозиторий копирует файловую систему, но это не так, поэтому я не могу использовать Файл напрямую.

Я хочу иметь возможность сделать следующее:

  1. клиент отправляет на сервер файл 'data.txt'
  2. сервер сжимает «data.txt» в сжатый файл «data.zip»
  3. сервер отправляет строковое представление data.zip в хранилище
  4. хранилище данных репозитория.zip
  5. клиент загружает из репозитория data.zip и может открыть его с помощью своего любимого zip инструмента

Проблема возникает на шаге 3 , когда я пытаюсь получить строковое представление моего сжатого файла.

Вот пример класса с использованием потока zip *, который эмулирует репозиторий, демонстрирующий мою проблему.
Созданный zip-файл работает, но после его «сериализации» он поврежден.
(пример класса использовать Джакарта commons.io)

Большое спасибо за вашу помощь.

package zip;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.FileUtils;

/**
 * Date: May 19, 2010 - 6:13:07 PM
 *
 * @author Guillaume AME.
 */
public class ZipMe {
    public static void addOrUpdate(File zipFile, File ... files) throws IOException {

        File tempFile = File.createTempFile(zipFile.getName(), null);
        // delete it, otherwise you cannot rename your existing zip to it.
        tempFile.delete();

        boolean renameOk = zipFile.renameTo(tempFile);
        if (!renameOk) {
            throw new RuntimeException("could not rename the file " + zipFile.getAbsolutePath() + " to " + tempFile.getAbsolutePath());
        }
        byte[] buf = new byte[1024];

        ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));

        ZipEntry entry = zin.getNextEntry();
        while (entry != null) {
            String name = entry.getName();
            boolean notInFiles = true;
            for (File f : files) {
                if (f.getName().equals(name)) {
                    notInFiles = false;
                    break;
                }
            }
            if (notInFiles) {
                // Add ZIP entry to output stream.
                out.putNextEntry(new ZipEntry(name));
                // Transfer bytes from the ZIP file to the output file
                int len;
                while ((len = zin.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }
            }
            entry = zin.getNextEntry();
        }
        // Close the streams
        zin.close();
        // Compress the files
        if (files != null) {
            for (File file : files) {
                InputStream in = new FileInputStream(file);
                // Add ZIP entry to output stream.
                out.putNextEntry(new ZipEntry(file.getName()));
                // Transfer bytes from the file to the ZIP file
                int len;
                while ((len = in.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }
                // Complete the entry
                out.closeEntry();
                in.close();
            }
            // Complete the ZIP file
        }
        tempFile.delete();
        out.close();

    }

    public static void main(String[] args) throws IOException {

        final String zipArchivePath = "c:/temp/archive.zip";
        final String tempFilePath = "c:/temp/data.txt";
        final String resultZipFile = "c:/temp/resultingArchive.zip";

        File zipArchive = new File(zipArchivePath);
        FileUtils.touch(zipArchive);

        File tempFile = new File(tempFilePath);
        FileUtils.writeStringToFile(tempFile, "hello world");
        addOrUpdate(zipArchive, tempFile);

        //archive.zip exists and contains a compressed data.txt that can be read using winrar

        //now simulate writing of the zip into a in memory cache
        String archiveText = FileUtils.readFileToString(zipArchive);
        FileUtils.writeStringToFile(new File(resultZipFile), archiveText);

        //resultingArchive.zip exists, contains a compressed data.txt, but it can not
        //be read using winrar: CRC failed in data.txt. The file is corrupt

    }

}

Ответы [ 2 ]

2 голосов
/ 19 мая 2010

Zip-файлы являются двоичными. Обработка строк в Java является текстовой и может искажать то, что она видит как CRLF, нулевые байты и маркеры EOF. Когда дело доходит до чтения и перезаписи zip-файла, я предлагаю вам попробовать в качестве эксперимента readFileToByteArray и writeByteArrayToFile. Если это сработает, то я подозреваю, что виновата обработка String.

1 голос
/ 23 мая 2010

сервер отправляет строковое представление data.zip в хранилище

Таким образом, вы хотите получить строковое (то есть текстовое) представление zip (то есть двоичного) потока.

Base64 - самый популярный способ сделать это.

Одной из популярных реализаций Java является Общие Apache ( кодек компонент)

...