如何使用 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 变量是为了简化输出 - 您需要删除这些变量以及相关的 ifs。 为简单起见,我使用了ReaderUTF-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 存档中的数组中?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中创建未压缩的 Zip 存档

在 Java 中修改 ZIP 存档中的文本文件

如何在 Java 中创建一个 zip 文件

在 Python 中从克隆的 GitHub 存储库创建 Zip 存档

如何使用 perl Archive::Zip 将文件添加到存档中?

如何使用 Python zipfile 将文件放入 zip 存档中