1

理想情况下,我只想阅读 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);方法。

解决方案,想法?

4

3 回答 3

2

我会按照您的要求对您的回答发表评论,但评论的长度有限。可以实现您想要的:编译源代码而不将其实际提取到文件系统上的物理文件中。

引用接口StandardJavaFileManager的 API

此文件管理器创建表示常规文件、zip 文件条目或类似基于文件系统的容器中的条目的文件对象

在谷歌搜索我发现以下文章:使用 javax.tools 创建动态应用程序

在“Java 编译:概念和实现”部分中,它在“源文件”中声明了以下内容:

一个或多个要编译的 .java 源文件。JavaFileManager 提供了一个抽象文件系统,它将源文件名和输出文件名映射到 JavaFileObject 实例。(这里,文件是指唯一名称和字节序列之间的关联。客户端不需要使用实际的文件系统。)

下面的文章也做了同样的事情:动态内存编译

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

于 2013-04-03T00:53:07.490 回答
0

您可以扫描 ZIP 文件并保留对其条目的引用。然后从列表中选择条目,提取文件并执行您需要执行的任何操作。最初不必完全读取所有文件。ZipFile.close()一个缺点:在处理完 ZIP 存档之前,您不得调用。

例如:

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方法表示您想要对文件执行的所有其他操作。
  2. ZipFile.close()必须在完成 ZIP 文件后调用。close()如果已调用,则无法从其条目中读取数据。
  3. 代码中的count变量是为了输出简洁 - 您需要删除这些变量和相关if的 s。
  4. 为简单起见,我使用了Readerand UTF-8。如果您将文件内容呈现给用户,您可能必须处理文件的字符集。您可能还必须处理它以进行编译。
于 2013-04-02T20:18:21.343 回答
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();
                    }
                }
            }
        });
于 2013-04-02T21:01:29.280 回答