Java:具有非静态文件名的 Zip 文件
Java: Zip file with non-static filename
我在 post 上找到了这个 ZipUtils class:
how to zip a folder itself using java
我修改了它以便我可以传递一个 zip 文件名。但是,它的唯一工作方式是使用硬编码的静态字符串。 zippedFile 字符串是从数据库中获取的。我已经比较了 dbZippedFile 和 hardcodedZippedFile,它们都是相同的……也许将非静态字符串与 FileOutputStream 一起使用存在问题?只有在尝试压缩目录时才会出现此问题(一个文件可以正常工作)。有谁知道我做错了什么或有更好的选择吗?
它从不抛出错误。它只是无法创建文件。
在代码片段中,如果您将 zippedFile.getPath() 替换为硬编码字符串表示形式(即 "D:\dir\file.zip"),它会起作用。
代码:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
Date date = new Date();
String zipName = name+ "_" + dateFormat.format(date) + ".zip";
zippedFile = new File(archive, zipName);
if (zippedFile .exists()) {
zippedFile .delete();
}
ZipUtils.main(dirToZip.getPath(), zippedFile.getPath());
Class:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipUtils
{
private List<String> fileList;
private static String SOURCE_FOLDER; // SourceFolder path
public ZipUtils()
{
fileList = new ArrayList<String>();
}
public static void main(String source, String output)
{
SOURCE_FOLDER = source;
//output = "D:\dir\file.zip";
ZipUtils appZip = new ZipUtils();
appZip.generateFileList(new File(SOURCE_FOLDER));
appZip.zipIt(output);
}
public void zipIt(String zipFile)
{
byte[] buffer = new byte[1024];
String source = "";
FileOutputStream fos = null;
ZipOutputStream zos = null;
try
{
try
{
source = SOURCE_FOLDER.substring(SOURCE_FOLDER.lastIndexOf("\") + 1, SOURCE_FOLDER.length());
}
catch (Exception e)
{
source = SOURCE_FOLDER;
}
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(fos);
System.out.println("Output to Zip : " + zipFile);
FileInputStream in = null;
for (String file : this.fileList)
{
System.out.println("File Added : " + file);
ZipEntry ze = new ZipEntry(source + File.separator + file);
zos.putNextEntry(ze);
try
{
in = new FileInputStream(SOURCE_FOLDER + File.separator + file);
int len;
while ((len = in.read(buffer)) > 0)
{
zos.write(buffer, 0, len);
}
}
finally
{
in.close();
}
}
zos.closeEntry();
System.out.println("Folder successfully compressed");
}
catch (IOException ex)
{
ex.printStackTrace();
}
finally
{
try
{
zos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public void generateFileList(File node)
{
// add file only
if (node.isFile())
{
fileList.add(generateZipEntry(node.toString()));
}
if (node.isDirectory())
{
String[] subNote = node.list();
for (String filename : subNote)
{
generateFileList(new File(node, filename));
}
}
}
private String generateZipEntry(String file)
{
return file.substring(SOURCE_FOLDER.length() + 1, file.length());
}
}
可能有数百种方法可以根据您的需要解决此问题,但从我的角度来看,您希望能够做的是用尽可能少的代码行说 "Zip this folder to this zip file".. .
为此,我可以更改代码以允许您执行类似...
ZipUtils appZip = new ZipUtils();
appZip.zipIt(new File(source), new File(output));
File
的使用不会使参数的含义产生歧义。这种机制还意味着您可以根据需要一次又一次地调用 zipIt
,而不必创建 ZipUtils
的新实例
这将需要对基本代码进行一些修改,因为它假定文件路径的值为 String
,坦率地说,这简直令人抓狂,因为您真正想要的所有信息都可以更容易地从 File
对象 - 恕我直言。这也意味着您根本不需要维护对源路径的引用,超出 zipIt
方法
的范围
public static class ZipUtils {
private final List<File> fileList;
private List<String> paths;
public ZipUtils() {
fileList = new ArrayList<>();
paths = new ArrayList<>(25);
}
public void zipIt(File sourceFile, File zipFile) {
if (sourceFile.isDirectory()) {
byte[] buffer = new byte[1024];
FileOutputStream fos = null;
ZipOutputStream zos = null;
try {
String sourcePath = sourceFile.getPath();
generateFileList(sourceFile);
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(fos);
System.out.println("Output to Zip : " + zipFile);
FileInputStream in = null;
for (File file : this.fileList) {
String path = file.getParent().trim();
path = path.substring(sourcePath.length());
if (path.startsWith(File.separator)) {
path = path.substring(1);
}
if (path.length() > 0) {
if (!paths.contains(path)) {
paths.add(path);
ZipEntry ze = new ZipEntry(path + "/");
zos.putNextEntry(ze);
zos.closeEntry();
}
path += "/";
}
String entryName = path + file.getName();
System.out.println("File Added : " + entryName);
ZipEntry ze = new ZipEntry(entryName);
zos.putNextEntry(ze);
try {
in = new FileInputStream(file);
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
} finally {
in.close();
}
}
zos.closeEntry();
System.out.println("Folder successfully compressed");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
protected void generateFileList(File node) {
// add file only
if (node.isFile()) {
fileList.add(node);
}
if (node.isDirectory()) {
File[] subNote = node.listFiles();
for (File filename : subNote) {
generateFileList(filename);
}
}
}
}
ps- 你 public static void main
,不是有效的 "main entry point",应该是 public static void main(String[] args)
;)
因此,根据您的代码片段,您可以简单地执行类似...
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
Date date = new Date();
String zipName = name+ "_" + dateFormat.format(date) + ".zip";
zippedFile = new File(archive, zipName);
if (zippedFile exists()) {
zippedFile.delete();
}
ZipUtils zu = new ZipUtils();
zu.zipIt(dirToZip, zippedFile);
我在 post 上找到了这个 ZipUtils class: how to zip a folder itself using java
我修改了它以便我可以传递一个 zip 文件名。但是,它的唯一工作方式是使用硬编码的静态字符串。 zippedFile 字符串是从数据库中获取的。我已经比较了 dbZippedFile 和 hardcodedZippedFile,它们都是相同的……也许将非静态字符串与 FileOutputStream 一起使用存在问题?只有在尝试压缩目录时才会出现此问题(一个文件可以正常工作)。有谁知道我做错了什么或有更好的选择吗?
它从不抛出错误。它只是无法创建文件。 在代码片段中,如果您将 zippedFile.getPath() 替换为硬编码字符串表示形式(即 "D:\dir\file.zip"),它会起作用。
代码:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
Date date = new Date();
String zipName = name+ "_" + dateFormat.format(date) + ".zip";
zippedFile = new File(archive, zipName);
if (zippedFile .exists()) {
zippedFile .delete();
}
ZipUtils.main(dirToZip.getPath(), zippedFile.getPath());
Class:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipUtils
{
private List<String> fileList;
private static String SOURCE_FOLDER; // SourceFolder path
public ZipUtils()
{
fileList = new ArrayList<String>();
}
public static void main(String source, String output)
{
SOURCE_FOLDER = source;
//output = "D:\dir\file.zip";
ZipUtils appZip = new ZipUtils();
appZip.generateFileList(new File(SOURCE_FOLDER));
appZip.zipIt(output);
}
public void zipIt(String zipFile)
{
byte[] buffer = new byte[1024];
String source = "";
FileOutputStream fos = null;
ZipOutputStream zos = null;
try
{
try
{
source = SOURCE_FOLDER.substring(SOURCE_FOLDER.lastIndexOf("\") + 1, SOURCE_FOLDER.length());
}
catch (Exception e)
{
source = SOURCE_FOLDER;
}
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(fos);
System.out.println("Output to Zip : " + zipFile);
FileInputStream in = null;
for (String file : this.fileList)
{
System.out.println("File Added : " + file);
ZipEntry ze = new ZipEntry(source + File.separator + file);
zos.putNextEntry(ze);
try
{
in = new FileInputStream(SOURCE_FOLDER + File.separator + file);
int len;
while ((len = in.read(buffer)) > 0)
{
zos.write(buffer, 0, len);
}
}
finally
{
in.close();
}
}
zos.closeEntry();
System.out.println("Folder successfully compressed");
}
catch (IOException ex)
{
ex.printStackTrace();
}
finally
{
try
{
zos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public void generateFileList(File node)
{
// add file only
if (node.isFile())
{
fileList.add(generateZipEntry(node.toString()));
}
if (node.isDirectory())
{
String[] subNote = node.list();
for (String filename : subNote)
{
generateFileList(new File(node, filename));
}
}
}
private String generateZipEntry(String file)
{
return file.substring(SOURCE_FOLDER.length() + 1, file.length());
}
}
可能有数百种方法可以根据您的需要解决此问题,但从我的角度来看,您希望能够做的是用尽可能少的代码行说 "Zip this folder to this zip file".. .
为此,我可以更改代码以允许您执行类似...
ZipUtils appZip = new ZipUtils();
appZip.zipIt(new File(source), new File(output));
File
的使用不会使参数的含义产生歧义。这种机制还意味着您可以根据需要一次又一次地调用 zipIt
,而不必创建 ZipUtils
这将需要对基本代码进行一些修改,因为它假定文件路径的值为 String
,坦率地说,这简直令人抓狂,因为您真正想要的所有信息都可以更容易地从 File
对象 - 恕我直言。这也意味着您根本不需要维护对源路径的引用,超出 zipIt
方法
public static class ZipUtils {
private final List<File> fileList;
private List<String> paths;
public ZipUtils() {
fileList = new ArrayList<>();
paths = new ArrayList<>(25);
}
public void zipIt(File sourceFile, File zipFile) {
if (sourceFile.isDirectory()) {
byte[] buffer = new byte[1024];
FileOutputStream fos = null;
ZipOutputStream zos = null;
try {
String sourcePath = sourceFile.getPath();
generateFileList(sourceFile);
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(fos);
System.out.println("Output to Zip : " + zipFile);
FileInputStream in = null;
for (File file : this.fileList) {
String path = file.getParent().trim();
path = path.substring(sourcePath.length());
if (path.startsWith(File.separator)) {
path = path.substring(1);
}
if (path.length() > 0) {
if (!paths.contains(path)) {
paths.add(path);
ZipEntry ze = new ZipEntry(path + "/");
zos.putNextEntry(ze);
zos.closeEntry();
}
path += "/";
}
String entryName = path + file.getName();
System.out.println("File Added : " + entryName);
ZipEntry ze = new ZipEntry(entryName);
zos.putNextEntry(ze);
try {
in = new FileInputStream(file);
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
} finally {
in.close();
}
}
zos.closeEntry();
System.out.println("Folder successfully compressed");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
protected void generateFileList(File node) {
// add file only
if (node.isFile()) {
fileList.add(node);
}
if (node.isDirectory()) {
File[] subNote = node.listFiles();
for (File filename : subNote) {
generateFileList(filename);
}
}
}
}
ps- 你 public static void main
,不是有效的 "main entry point",应该是 public static void main(String[] args)
;)
因此,根据您的代码片段,您可以简单地执行类似...
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
Date date = new Date();
String zipName = name+ "_" + dateFormat.format(date) + ".zip";
zippedFile = new File(archive, zipName);
if (zippedFile exists()) {
zippedFile.delete();
}
ZipUtils zu = new ZipUtils();
zu.zipIt(dirToZip, zippedFile);