Return Java 中来自 ZipOutputStream 的 Zip 文件
Return Zip File from ZipOutputStream in Java
我有一个从文件列表创建 Zip 文件的功能。是否可以 return Zip 文件而不保存在磁盘上?我需要该文件,因为我必须将 zip 文件用作另一个函数的参数。我不确定 ByteStream 是否适合我。
public File compressFileList(List<File> fileList,String fileName) {
FileOutputStream fileOutputStream=null;
ZipOutputStream zipOutputStream=null;
FileInputStream fileInputStream=null;
String compressedFileName=fileName +".zip";
if(fileList.isEmpty())
return null;
try
{
fileOutputStream = new FileOutputStream(compressedFileName);
zipOutputStream = new ZipOutputStream(new BufferedOutputStream(fileOutputStream));
for (File file: fileList) {
fileInputStream = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
byte[] tmp = new byte[4*1024];
int size = 0;
while((size = fileInputStream.read(tmp)) != -1){
zipOutputStream.write(tmp, 0, size);
}
zipOutputStream.flush();
fileInputStream.close();
}
zipOutputStream.close();
return compressedFile; //This is what I am missing
}
catch (FileNotFoundException e)
{
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
编辑:添加用例
想法是创建一个zip文件并使用Watson的VisualRecognition Service的CreateClassifierOptions方法。
classifierOptions = new CreateClassifierOptions.Builder()
.classifierName("Santa")
.addClass("Santa", new File("C:\app\GitRepo\images\beagle.zip"))
.negativeExamples(new File("C:\app\GitRepo\images\nosport.zip"))
.build();
生成器接受 zip 文件作为参数。
了解
根据Alexandre Dupriez 的解释,我认为最好将文件存储在硬盘上的某个位置。
您应该可以使用 ByteArrayOutputStream
而不是 FileOutputStream
:
zipOutputStream = new ZipOutputStream(new ByteArrayOutputStream());
这里的难点在于向使用 zip 文件的方法提供 File
。 java.io.File
不提供允许您操作内存文件的抽象。
java.io.File
抽象和java.io.FileInputStream
实现
为简化起见,如果我们必须归结为 File
抽象是什么,我们会将其视为 URI
。因此,为了能够构建一个内存中的 File
,或者至少模仿它,我们需要提供一个 URI
,然后由 File
的消费者使用阅读其内容。
如果我们查看消费者可能使用的 FileInputStream
,我们可以看到它总是以本地调用结束,这让我们有可能抽象出一个 FileSystem
内存文件:
// class java.io.FileInputStream
/**
* Opens the specified file for reading.
* @param name the name of the file
*/
private native void open0(String name) throws FileNotFoundException;
如果有可能让消费者接受 InputStream
会更容易,但从你的问题陈述来看,我猜这是不可能的。
API 来电
您的要求是向 Watson Visual API 提供 File
。
能否请您提供您需要调用的API方法?
public void compressFileList(List<File> fileList, OutputStream outputStream)
throws IOException {
try (ZipOutputStream zipOutputStream =
new ZipOutputStream(new BufferedOutputStream(outputStream));
for (File file: fileList) {
try (FileInputStream fileInputStream = new FileInputStream(file)) {
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
byte[] tmp = new byte[4*1024];
int size = 0;
while((size = fileInputStream.read(tmp)) != -1){
zipOutputStream.write(tmp, 0, size);
}
zipOutputStream.flush();
} catch (FileNotFoundException e) { // Maybe skip not found files.
Logger.log(Level.INFO, "File not found {}", file.getPath());
}
}
}
}
用法:
if (fileList.isEmpty()) {
...
return;
}
try {
compressFileList(fileList, servletRequest.getOutputStream())) {
} catch (FileNotFoundException e) {
...
} catch (IOException e) {
...
}
我有一个从文件列表创建 Zip 文件的功能。是否可以 return Zip 文件而不保存在磁盘上?我需要该文件,因为我必须将 zip 文件用作另一个函数的参数。我不确定 ByteStream 是否适合我。
public File compressFileList(List<File> fileList,String fileName) {
FileOutputStream fileOutputStream=null;
ZipOutputStream zipOutputStream=null;
FileInputStream fileInputStream=null;
String compressedFileName=fileName +".zip";
if(fileList.isEmpty())
return null;
try
{
fileOutputStream = new FileOutputStream(compressedFileName);
zipOutputStream = new ZipOutputStream(new BufferedOutputStream(fileOutputStream));
for (File file: fileList) {
fileInputStream = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
byte[] tmp = new byte[4*1024];
int size = 0;
while((size = fileInputStream.read(tmp)) != -1){
zipOutputStream.write(tmp, 0, size);
}
zipOutputStream.flush();
fileInputStream.close();
}
zipOutputStream.close();
return compressedFile; //This is what I am missing
}
catch (FileNotFoundException e)
{
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
编辑:添加用例
想法是创建一个zip文件并使用Watson的VisualRecognition Service的CreateClassifierOptions方法。
classifierOptions = new CreateClassifierOptions.Builder()
.classifierName("Santa")
.addClass("Santa", new File("C:\app\GitRepo\images\beagle.zip"))
.negativeExamples(new File("C:\app\GitRepo\images\nosport.zip"))
.build();
生成器接受 zip 文件作为参数。
了解
根据Alexandre Dupriez 的解释,我认为最好将文件存储在硬盘上的某个位置。
您应该可以使用 ByteArrayOutputStream
而不是 FileOutputStream
:
zipOutputStream = new ZipOutputStream(new ByteArrayOutputStream());
这里的难点在于向使用 zip 文件的方法提供 File
。 java.io.File
不提供允许您操作内存文件的抽象。
java.io.File
抽象和java.io.FileInputStream
实现
为简化起见,如果我们必须归结为 File
抽象是什么,我们会将其视为 URI
。因此,为了能够构建一个内存中的 File
,或者至少模仿它,我们需要提供一个 URI
,然后由 File
的消费者使用阅读其内容。
如果我们查看消费者可能使用的 FileInputStream
,我们可以看到它总是以本地调用结束,这让我们有可能抽象出一个 FileSystem
内存文件:
// class java.io.FileInputStream
/**
* Opens the specified file for reading.
* @param name the name of the file
*/
private native void open0(String name) throws FileNotFoundException;
如果有可能让消费者接受 InputStream
会更容易,但从你的问题陈述来看,我猜这是不可能的。
API 来电
您的要求是向 Watson Visual API 提供 File
。
能否请您提供您需要调用的API方法?
public void compressFileList(List<File> fileList, OutputStream outputStream)
throws IOException {
try (ZipOutputStream zipOutputStream =
new ZipOutputStream(new BufferedOutputStream(outputStream));
for (File file: fileList) {
try (FileInputStream fileInputStream = new FileInputStream(file)) {
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
byte[] tmp = new byte[4*1024];
int size = 0;
while((size = fileInputStream.read(tmp)) != -1){
zipOutputStream.write(tmp, 0, size);
}
zipOutputStream.flush();
} catch (FileNotFoundException e) { // Maybe skip not found files.
Logger.log(Level.INFO, "File not found {}", file.getPath());
}
}
}
}
用法:
if (fileList.isEmpty()) {
...
return;
}
try {
compressFileList(fileList, servletRequest.getOutputStream())) {
} catch (FileNotFoundException e) {
...
} catch (IOException e) {
...
}