Как открыть сгенерированный java-файл zip-файла в кодировке UTF-8
Наш продукт имеет функцию экспорта, которая использует ZipOutputStream
заархивировать каталог; однако при попытке заархивировать каталог, содержащий имена файлов с китайскими или японскими символами, экспорт не работает должным образом. По некоторым причинам новые файлы в заархивированном файле названы по-другому. Вот пример нашего почтового индекса:
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
out.setEncoding("UTF-8");
//program to add directory to zip
//program add/create file to zip
out.close();
Мой алгоритм импорта, также встроенный в Java, может правильно импортировать заархивированный файл, даже если он содержит китайские / японские символы в именах файлов / каталогов.
Zipfile zipfile = new ZipFile(zipPath, "UTF-8");
Enumeration e = zipFile.getEntries();
while (e.hasMoreElements()) {
entry = (ZipEntry) e.nextElement();
String name = entry.getName();
....
Испытывает ли программа zip программу разархивирование файлов в кодировке UTF-8, или есть что-то особенное, что необходимо для создания файла zip, который может быть легко использован существующим программным обеспечением с использованием кодировки utf-8??
Я написал пример программы:
package ZipFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
public class ZipFolder{
public static void main(String[] a) throws Exception
{
String srcFolder = "D:/9.4_work/openscript_repo/中文124.All/中文";
String destZipFile = "D:/Eclipse_Projects/OpenScriptDebuggingProject/src/ZipFile/demo.zip";
zipFolder(srcFolder, destZipFile);
}
static public void zipFolder(String srcFolder, String destZipFile) throws Exception
{
ZipOutputStream zip = null;
FileOutputStream fileWriter = null;
fileWriter = new FileOutputStream(destZipFile);
zip = new ZipOutputStream(fileWriter);
zip.setEncoding("UTF-8");
// using GBK encoding, the chinese name can be correctly displayed when unzip
// zip.setEncoding("GBK");
addFolderToZip("", srcFolder, zip);
zip.flush();
zip.close();
}
static private void addFileToZip(String path, String srcFile, ZipOutputStream zip) throws Exception
{
File folder = new File(srcFile);
if (folder.isDirectory()) {
addFolderToZip(path, srcFile, zip);
}
else {
byte[] buf = new byte[1024];
int len;
FileInputStream in = new FileInputStream(srcFile);
zip.putNextEntry(new ZipEntry(path + "/" + folder.getName()));
while ((len = in.read(buf)) > 0) {
zip.write(buf, 0, len);
}
}
}
static private void addFolderToZip(String path, String srcFolder, ZipOutputStream zip) throws Exception
{
File folder = new File(srcFolder);
for (String fileName : folder.list()) {
if (path.equals("")) {
addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip);
}
else {
addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip);
}
}
}
}
2 ответа
Верхний ответ здесь может ответить на ваш вопрос; к сожалению, кажется, что формат Zip не позволяет создать файл Zip, который будет правильно отображать имена файлов на любом компьютере:
https://superuser.com/questions/60379/linux-zip-tgz-filenames-encoding-problem
Я ожидаю, что это работает, когда вы устанавливаете кодировку на GBK, потому что это кодировка вашей системы по умолчанию, и поэтому 7zip использует ее для всех открываемых zip-файлов.
Это говорит о том, что rar
а также 7z
форматы имеют лучшую поддержку.
Я нашел запись в блоге специально о UTF-8 в zips с Java. Предполагается, что есть более новая версия спецификации ZIP, которую могут не создавать текущие версии Java, но Java 7 подойдет. Я не знаю, используют ли классы Apache это тоже.
http://blogs.oracle.com/xuemingshen/entry/non_utf_8_encoding_in
Следующий служебный класс позволяет сжимать и распаковывать строки, используя алгоритм сжатия GZIP. Это может быть полезно, например, если вы хотите сохранить длинные строки в базе данных.
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.GZIPInputStream;
public class GzipStringUtil {
public static byte[] compressString(String uncompressedString) throws IllegalArgumentException, IllegalStateException {
if (uncompressedString == null) {
throw new IllegalArgumentException("The uncompressed string specified was null.");
}
try {
byte[] utfEncodedBytes = uncompressedString.getBytes("UTF-8");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(baos);
gzipOutputStream.write(utfEncodedBytes);
gzipOutputStream.finish();
gzipOutputStream.close();
return baos.toByteArray();
}
catch (Exception e) {
throw new IllegalStateException("GZIP compression failed: " + e, e);
}
}
public static String uncompressString(byte[] compressedString) throws IllegalArgumentException, IllegalStateException {
if (compressedString == null) {
throw new IllegalArgumentException("The compressed string specified was null.");
}
try {
ByteArrayInputStream bais = new ByteArrayInputStream(compressedString);
GZIPInputStream gzipInputStream = new GZIPInputStream(bais);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int value = 0; value != -1;) {
value = gzipInputStream.read();
if (value != -1) {
baos.write(value);
}
}
gzipInputStream.close();
baos.close();
return new String(baos.toByteArray(), "UTF-8");
}
catch (Exception e) {
throw new IllegalStateException("GZIP uncompression failed: " + e, e);
}
}
}
Вот TestCase, который предоставляет пример использования класса выше:
public class GzipStringUtilTest extends TestCase {
public void testGzipStringUtil() {
String input = "This is a test. This is a test. This is a test. This is a test. This is a test.";
System.out.println("Input: [" + input + "]");
byte[] compressed = GzipStringUtil.compressString(input);
System.out.println("Compressed: " + Arrays.toString(compressed));
System.out.println("-> Compressed input string of length " + input.length() + " to " + compressed.length + " bytes");
String uncompressed = GzipStringUtil.uncompressString(compressed);
System.out.println("Uncompressed: [" + uncompressed + "]");
assertEquals("The uncompressed string [" + uncompressed + "] unexpectedly does not match the input string [" + input + "]", input, uncompressed);
System.out.println("The input was compressed and uncompressed successfully, and the input matches uncompressed output.");
}
}