Баг №4244499
Этот баг был зарегистрирован еще в 1999г.
Проблема была не только с русскими файлами, а например с французскими (как в примере).
Корни довольно глубокие и существовали серьезные (надеюсь) причины, по которым эту ошибку долгое время не исправляли. В итоге, много-много лет в Java нельзя было сделать простыми штатными средствами zip-архив, который бы содержал файлы с именами не на латинице.
К сожалению, жизнь такова, что все это время некоторых java-программистов заставляли делать такие zip-архивы. Приходилось использовать например apache-вский commons-compress.
Использовать очень просто. Алгоритм буквально в два шага:
Шаг 1. Загружаем jar-ик (ссылка) или просто добавляем в pom.xml зависимость (если maven) :
....
org.apache.commons
commons-compress
1.3
Шаг 2. Используем:
import java.io.File;
import java.io.FileInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import static org.apache.commons.compress.utils.IOUtils.copy;
/*
* ТОЛЬКО В ОЗНАКОМИТЕЛЬНЫХ ЦЕЛЯХ!
* Пример очень небрежный, в реальных задачах код нужно причесать!
* Author: Vit
*/
public class Sample {
public static void main(String[] args) throws Exception {
File srcDir = new File("c:/temp/dir");
// список файлов
File[] files = srcDir.listFiles();
File zipFile = new File(srcDir, srcDir.getName() + ".zip");
// архив
ZipArchiveOutputStream zaos = new ZipArchiveOutputStream(zipFile);
for (File itemFile : files) {
ZipArchiveEntry entry = new ZipArchiveEntry(itemFile.getName());
zaos.putArchiveEntry(entry);
FileInputStream fis = new FileInputStream(itemFile);
try {
// копируем потоки
copy(fis, zaos);
} finally {
fis.close();
}
zaos.closeArchiveEntry();
}
zaos.close();
}
}
Счастливый конец.
В текущей версии JDK 7 этого бага уже нет.
Во-первых в семерке в ZIP API добавили новый конструктор, в котором можно явно указывать кодировку:
ZipOutputStream(OutputStream out,Charset charset)
Во-вторых, по-умолчанию используется стандартная UTF-8 кодировка.
Таким образом, дополнительных библиотек использовать не нужно, можно сразу делать zip-архив:
/*
* ТОЛЬКО В ОЗНАКОМИТЕЛЬНЫХ ЦЕЛЯХ!
* Пример очень небрежный, в реальных задачах код нужно причесать!
* Author: Vit
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Sample {
public static void main(String[] args) throws Exception {
File srcDir = new File("c:/temp/dir");
File[] files = srcDir.listFiles();
File zipFile = new File(srcDir, srcDir.getName() + "_j7.zip");
FileOutputStream fos = new FileOutputStream(zipFile);
try (ZipOutputStream zos = new ZipOutputStream(fos)) {
for (File itemFile : files) {
ZipEntry entry = new ZipEntry(itemFile.getName());
zos.putNextEntry(entry);
try (FileInputStream fis = new FileInputStream(itemFile)) {
byte[] buff = new byte[8192];
int length = -1;
while (-1 != (length = fis.read(buff))) {
zos.write(buff, 0, length);
}
}
zos.closeEntry();
}
}
}
}