如何使用 Java 将每个文件存储在 zip 存档中的数组中?

问题描述 投票:0回答:3

理想情况下,我只想读取 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 arrays zip archive
3个回答
2
投票
我会按照您的要求对您的答案发表评论,但评论的长度有限。 可以实现您想要的:编译源代码而不实际将其提取到文件系统上的物理文件。

引用接口API

StandardJavaFileManager

此文件管理器创建代表常规文件、

zip 文件条目或基于类似文件系统的容器中的条目的文件对象

在谷歌搜索我发现了以下文章:

使用javax.tools创建动态应用程序

在“Java 编译:概念和实现”部分中,它对“源文件”进行了以下说明:

要编译的一个或多个.java源文件。 JavaFileManager 提供了一个抽象文件系统,它将源文件名和输出文件名映射到 JavaFileObject 实例。 (

这里,文件是指唯一名称和字节序列之间的关联。客户端不需要使用实际的文件系统。)

下面的文章也做了同样的事情:

动态内存编译

两者都使用 CharSequence 作为编译源。 您可以尝试根据上面文章中的说明构建自己的实现,并更改为基于 ZipEntry。否则,您可以将 zip 条目的内容(正如您提到的,您知道它是一个 java 源文件)读取到 StringBuffer 中,然后使用其中一篇文章中的实现来编译它。


0
投票
您可以扫描 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(); } }

值得注意的事情:

  1. scan
    方法执行扫描,
    dump
    方法代表您想要对文件执行的所有其他操作。
    完成 ZIP 文件后必须调用
  2. ZipFile.close()
    。如果已调用 
    close()
    ,则无法从其条目中读取数据。
  3. 代码中的
  4. count
     变量是为了输出简洁 - 您需要删除这些变量以及关联的 
    if
  5. 为了简单起见,我使用了
  6. Reader
    UTF-8
    。如果您向用户呈现文件内容,您可能必须处理文件的字符集。您可能还需要处理它以进行编译。

0
投票
我快到了,它可以工作,但是 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(); } } } });
    
© www.soinside.com 2019 - 2024. All rights reserved.