如何使用 Java 将每个文件存储在 zip 存档中的数组中?
Posted
技术标签:
【中文标题】如何使用 Java 将每个文件存储在 zip 存档中的数组中?【英文标题】:How to store each file in a zip archive, in an array using Java? 【发布时间】:2013-04-02 16:37:22 【问题描述】:理想情况下,我只想读取 zip 存档并将每个文件存储在准备编译的 Iterable 中。 (假设 zip 仅包含 .java 文件)
这样会很好,但这不起作用,因为我无法获取 zip 中每个文件的路径。
private ArrayList<String> javaFilePaths = new ArrayList<String>();
Iterable<? extends JavaFileObject> = fileManager.getJavaFileObjectsFromStrings(javaFilePaths);
是否可以让ArrayList
的每个元素成为存档中文件的路径?到目前为止,我只能通过 zip 存档并获取所有无用的文件名,因为当我调用 getJavaFileObjectsFromStrings(javaFilePaths);
时,它不会是文件的完整路径。也许我需要先将每个文件的内容存储在一个新的JavaFileObject
中?真的不确定解决这个问题的最佳方法......
有人可以帮忙解决这个问题吗,事实证明这很棘手!
UPDATE:
考虑将 zip 存档中的每个文件作为 File
对象存储在 File
类型的数组中
然后调用getJavaFileObjectsFromFiles(arrayOfFiles);
方法。
解决方案、想法?
【问题讨论】:
不确定您要做什么,但请查看java.util.zip.ZipInputStream
@orid 我“认为”我需要遍历 zip 文件并将每个 .java 文件作为 File
对象存储在 File
类型的数组/列表中
你不应该“思考”。你应该知道你需要什么以及你想问什么
您不能将 ZipEntry
存储为 .java 文件,因为这些文件可能包含字节码,除非您确定它是包含一些工件源的 JarInputStream
@A.J 抱歉,我不是 Java 专家,我也不是什么都懂。这就是为什么我来到这里有很多经验的地方。我知道一般概念,但我不知道如何以编程方式进行。主要概念是用户浏览包含 Java 文件的 zip 存档,然后将 Java 文件临时存储在内存中,然后编译生成类文件。除了如何将 zip 文件夹中的文件存储到数组中之外,我一切正常。
【参考方案1】:
我会按照您的要求对您的回答发表评论,但 cmets 的长度有限。 可以实现您想要的:编译源代码而无需将其实际提取到文件系统上的物理文件中。
引用接口StandardJavaFileManager的API
此文件管理器创建代表常规文件、压缩文件条目或类似文件系统的基于容器中的条目的文件对象
在谷歌搜索我发现了以下文章:Create dynamic applications with javax.tools
在“Java 编译:概念和实现”部分中,它在“源文件”中声明了以下内容:
要编译的一个或多个 .java 源文件。 JavaFileManager 提供了一个抽象文件系统,它将源文件名和输出文件名映射到 JavaFileObject 实例。 (这里的文件是指一个唯一名称和一个字节序列之间的关联。客户端不需要使用实际的文件系统。)
以下文章也是如此:Dynamic in-memory compilation
两者都使用 CharSequence 作为编译源。 您可以尝试根据上面文章中的解释构建自己的实现,并更改为基于 ZipEntry。否则,您可以将 zip 条目的内容(正如您所提到的,您知道它是一个 java 源文件)到 StringBuffer 中,然后使用其中一篇文章中的实现来编译它。
【讨论】:
【参考方案2】:您可以扫描 ZIP 文件并保留对其条目的引用。然后从列表中选择条目,提取文件并执行您需要执行的任何操作。最初不必完全读取所有文件。一个缺点:在处理完 ZIP 存档之前,您不得致电 ZipFile.close()
。
例如:
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
public class SO
static class ZipFileRecord
final ZipFile zf;
final ZipEntry ze;
public ZipFileRecord(ZipFile zf, ZipEntry ze)
super();
this.zf = zf;
this.ze = ze;
public String content() throws IOException
InputStream is = zf.getInputStream(ze);
BufferedReader br = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
StringBuilder sb = new StringBuilder();
String line = null;
int count = 5; // limit loop for reduced output
while ((line = br.readLine())!=null)
sb.append(line);
sb.append("\n");
if (count--<=0)
sb.append("...\n");
break;
br.close();
return sb.toString();
public static class ZipWalker
final ArrayList<ZipFileRecord> list = new ArrayList<>();
ZipFile zf;
public void scan(String fn) throws ZipException, IOException
File f = new File(fn);
if (!f.exists()) throw new RuntimeException("File not found: " + f);
zf = new ZipFile(f);
Enumeration<? extends ZipEntry> entries = zf.entries();
for (ZipEntry ze : Collections.list(entries))
if (ze.getName().endsWith(".java"))
list.add(new ZipFileRecord(zf, ze));
public void dump() throws IOException
int count = 3; // limit loop for reduced output
for (ZipFileRecord fr : list)
System.out.println("=============> " + fr.ze);
System.out.println(fr.content());
if (count--<=0)
break;
zf.close();
public static void main(String[] args) throws ZipException, IOException
ZipWalker zw = new ZipWalker();
zw.scan("path/to/your/file.zip");
zw.dump();
值得注意的事情:
scan
方法执行扫描,dump
方法代表您想要对文件执行的所有其他操作。
完成 ZIP 文件后,必须调用 ZipFile.close()
。如果已调用 close()
,则无法从其条目中读取数据。
代码中的 count
变量是为了简化输出 - 您需要删除这些变量以及相关的 if
s。
为简单起见,我使用了Reader
和UTF-8
。如果您将文件内容呈现给用户,您可能必须处理文件的字符集。您可能还必须处理它以进行编译。
【讨论】:
请看我的回答,如果您有任何想法,请告知? :)【参考方案3】:我快到了,它可以工作,但是 FileOutputStream 创建文件,我可以在之后简单地删除它,但是有没有办法在不创建文件的情况下做到这一点,而是让它成为虚拟的?请评论我的回答。
btnBrowse.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
int returnVal = fileChooser.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION)
try
isZip = true;
ZipFile zipFile = new ZipFile(fileChooser.getSelectedFile());
Enumeration<?> enu = zipFile.entries();
while (enu.hasMoreElements())
ZipEntry zipEntry = (ZipEntry) enu.nextElement();
File file = new File(zipEntry.getName());
InputStream is = zipFile.getInputStream(zipEntry);
FileOutputStream fos = new FileOutputStream(file);
byte[] bytes = new byte[1024];
int length;
while ((length = is.read(bytes)) >= 0)
fos.write(bytes, 0, length);
is.close();
fos.close();
fileArrayList.add(file);
zipFile.close();
catch (IOException ioe)
ioe.printStackTrace();
);
【讨论】:
我想我开始明白你需要什么了。现在我正在处理我的主要项目(支付账单的项目),但明天我将在这个主题上花费一些“*** 时间”。我想,这主要是关于“将 ZIP 虚拟化为一个数组”。可能您需要更多关于将它与 JavaCompiler 和朋友连接起来的详细信息? @RainerSchwarze 实际上我已经成功地从 JTextArea 编译了它,现在我正在添加下一个功能,即浏览包含要编译的多个 Java 源文件的 zip :) 我很享受这个项目很多,因为它挑战了我的知识(计算机科学一年级学生)。以上是关于如何使用 Java 将每个文件存储在 zip 存档中的数组中?的主要内容,如果未能解决你的问题,请参考以下文章
在 Python 中从克隆的 GitHub 存储库创建 Zip 存档