当前位置: 首页 > 知识库问答 >
问题:

Java程序忽略zip文件中的所有文件

公良子轩
2023-03-14

当我通过控制台给出zip文件夹路径时,我有一个程序。它将遍历文件夹中的每个项目(每个子项目、子项目的子项目等)。但是如果它遇到一个zip文件夹,它会忽略zip文件夹中的所有内容,我需要读取zip文件夹中的所有内容,包括文件。

以下是贯穿每个项目的方法:

    public static String[] getLogBuffers(String path) throws IOException//path is given via console
  {
    String zipFileName = path;
    String destDirectory = path;
    BufferedInputStream errorLogBuffer = null;
    BufferedInputStream windowLogBuffer = null;
    String strErrorLogFileContents="";
    String strWindowLogFileContents="";
    String[] errorString=new String[2];



    byte[] buffer = new byte[1024];
    ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName));
    ZipEntry zipEntry = zis.getNextEntry();
    while (zipEntry != null)
    {
      String filePath = destDirectory + "/" + zipEntry.getName();
      System.out.println("unzipping" + filePath);
      if (!zipEntry.isDirectory())
      {
                if (zipEntry.getName().endsWith("errorlog.txt"))
                {
                  ZipFile zipFile = new ZipFile(path);
                  InputStream errorStream = zipFile.getInputStream(zipEntry);
                  BufferedInputStream bufferedInputStream=new BufferedInputStream(errorStream);
                  byte[] contents = new byte[1024];
                  System.out.println("ERRORLOG NAME"+zipEntry.getName());
                  int bytesRead = 0;
                  while((bytesRead = bufferedInputStream.read(contents)) != -1) {
                    strErrorLogFileContents += new String(contents, 0, bytesRead);
                  }

                }
                if (zipEntry.getName().endsWith("windowlog.txt"))
                { ZipFile zipFile = new ZipFile(path);
                  InputStream windowStream = zipFile.getInputStream(zipEntry);
                  BufferedInputStream bufferedInputStream=new BufferedInputStream(windowStream);
                  byte[] contents = new byte[1024];
                  System.out.println("WINDOWLOG NAME"+zipEntry.getName());

                  int bytesRead = 0;
                  while((bytesRead = bufferedInputStream.read(contents)) != -1) {
                    strWindowLogFileContents += new String(contents, 0, bytesRead);
                  }

                }

      }
    
      zis.closeEntry();
      zipEntry = zis.getNextEntry();

    }
    errorString[0]=strErrorLogFileContents;
    errorString[1]=strWindowLogFileContents;
    zis.closeEntry();
    zis.close();
    System.out.println("Buffers ready");
    return errorString;
  }

在父zip文件夹内访问的项目(我的控制台输出):

unzippingC:logFolders/logX3.zip/logX3/
unzippingC:logFolders/logX3.zip/logX3/Anan/
unzippingC:logFolders/logX3.zip/logX3/Anan/errorreports/
unzippingC:logFolders/logX3.zip/logX3/Anan/errorreports/2021-11-23_103518.zip
unzippingC:logFolders/logX3.zip/logX3/Anan/errorreports/errorlog.txt
unzippingC:logX3.zip/logX3/Anan/errorreports/version.txt
unzippingC:logFolders/logX3.zip/logX3/Anan/errorreports/windowlog.txt

正如你所看到的程序只去直到2021-11-23_103518.zip,并在另一条路径之后,但2021-11-23_103518.zip有孩子的项目(文件),我需要访问感谢任何帮助,谢谢

共有1个答案

曹德明
2023-03-14

zip文件不是文件夹。虽然Windows将zip文件视为文件夹,但它不是文件夹。. zip文件是一个带有内部条目表的单个文件,每个条目包含压缩数据。

您读取的每个内部. zip文件都需要一个新的ZipFile或ZipInputStream。这是没有办法的。

您不应该创建新的ZipFile实例来读取相同的内容。压缩文件的条目。您只需要一个ZipFile对象。您可以使用its entries()方法查看它的条目,也可以使用ZipFile的getInputStream方法读取每个条目。

如果使用多个对象读取相同的zip文件会在Windows上遇到文件锁定问题,我不会感到惊讶。)

try (ZipFile zipFile = new ZipFile(path))
{
    Enumeration<? extends ZipEntry> entries = zipFile.entries();
    while (entries.hasMoreElements())
    {
        ZipEntry zipEntry = entries.nextElement();

        if (zipEntry.getName().endsWith("errorlog.txt"))
        {
            try (InputStream errorStream = zipFile.getInputStream(zipEntry))
            {
                // ...
            }
        }
    }
}

请注意,没有创建其他ZipFile或ZipInputStream对象。只有zipFile读取并遍历文件。还要注意使用try with resources语句隐式关闭ZipFile和InputStream。

您不应该使用=来构建字符串。这样做会创建大量中间字符串对象,这些对象必须进行垃圾收集,这可能会影响程序的性能。您应该将每个zip条目的InputStream包装在InputStreamReader中,然后使用该读取器的transferTo方法附加到保存组合日志的单个StringWriter。

String strErrorLogFileContents = new StringWriter();
String strWindowLogFileContents = new StringWriter();

try (ZipFile zipFile = new ZipFile(path))
{
    Enumeration<? extends ZipEntry> entries = zipFile.entries();
    while (entries.hasMoreElements())
    {
        ZipEntry zipEntry = entries.nextElement();

        if (zipEntry.getName().endsWith("errorlog.txt"))
        {
            try (Reader entryReader = new InputStreamReader(
                zipFile.getInputStream(zipEntry)),
                StandardCharsets.UTF_8)
            {
                entryReader.transferTo(strErrorLogFileContents);
            }
        }
    }
}

注意StandardCharset的使用。UTF_8。从字节创建字符串而不指定字符集几乎是不正确的。如果您不提供字符集,Java将使用系统的默认字符集,这意味着您的程序在Windows中的行为将不同于在其他操作系统上的行为。

如上所述,一个本身是内部zip文件的zip条目需要一个全新的ZipFile或ZipInputStream对象来读取它。我建议将条目复制到临时文件中,因为从另一个ZipInputStream读取ZipInputStream的速度很慢,然后在完成读取后删除临时文件。

try (ZipFile zipFile = new ZipFile(path))
{
    Enumeration<? extends ZipEntry> entries = zipFile.entries();
    while (entries.hasMoreElements())
    {
        ZipEntry zipEntry = entries.nextElement();

        if (zipEntry.getName().endsWith(".zip"))
        {
            Path tempZipFile = Files.createTempFile(null, ".zip");
            try (InputStream errorStream = zipFile.getInputStream(zipEntry))
            {
                Files.copy(errorStream, tempZipFile,
                    StandardCopyOption.REPLACE_EXISTING);
            }

            String[] logsFromZip = getLogBuffers(tempZipFile.toString());

            strErrorLogFileContents.write(logsFromZip[0]);
            strWindowLogFileContents.write(logsFromZip[1]);

            Files.delete(tempZipFile);
        }
    }
}

最后,考虑为返回值创建一个有意义的类。字符串数组很难理解。调用者不会知道它总是恰好包含两个元素,也不会知道这两个元素是什么。自定义返回类型将非常短:

public class Logs {
    private final String errorLog;

    private final String windowLog;

    public Logs(String errorLog,
                String windowLog)
    {
        this.errorLog = errorLog;
        this.windowLog = windowLog;
    }

    public String getErrorLog()
    {
        return errorLog;
    }

    public String getWindowLog()
    {
        return windowLog;
    }
}

从Java 16开始,您可以使用记录来缩短声明:

public record Logs(String errorLog,
                   String windowLog)
{ }

无论您是使用记录还是写出类,您都可以在方法中使用它作为返回类型:

public static Logs getLogBuffers(String path) throws IOException
{
    // ...

    return new Logs(
        strErrorLogFileContents.toString(),
        strWindowLogFileContents.toString());
}

*Windows资源管理器shell将zip文件视为文件夹的做法是一个非常糟糕的用户界面。我知道我不是唯一一个这么想的人。它通常会让用户的事情变得更加困难,而不是更容易。

 类似资料:
  • 我想用Java编写一个GUI zip/unzip程序。该程序将能够压缩文件和目录/IES的任何组合,并解压缩一个或多个压缩文件。 现在我刚刚完成了GUI和zip Funtion。但是zip funtion似乎不能正常工作,产生的zip文件不知何故被破坏了。我找不到问题到底出在哪里。它似乎与函数或函数有关。 当我测试该程序时,输出如下: 归档:找不到test1.zip中央目录结束签名。要么这个文件不

  • 问题内容: 我需要使用以下命令创建一个zip文件: 这可行,但是创建的zip文件会创建一个目录结构,将目录模仿为原始文件。我不需要很多额外的文件夹。 粗略浏览手册页或Google搜索时,我没有找到答案。 问题答案: 您可以使用。

  • 我试图在ZIP文件内创建一个ZIP文件,以重新构建以前在内存中的zip结构,我在Java。 我失败了,因为我得到了一个错误的内部ZIP内创建的初始ZIP文件。文件已损坏。当试图打开它时,我得到一个“文件的意外结局”。 我得到了这个结构: -input.zip--InnerInput.zip 代码使用java Stack和Map在内存中解压。然后它创建input2.zip,内部nput.zip。 总

  • GitBook会读取 .gitignore,.bookignore,.ignore 文件来获取忽略的文件和目录的列表。 这些文件的格式,遵循和 .gitignore 同样的约定: # 这是一个注释 # 忽略文件test.md test.md # 忽略文件夹 "bin" 中的所有内容 bin/*

  • 我已经阅读了前面的所有主题以及关于如何使用命令提示符的建议。但让我们来看看windows用户。 我正在使用GitHub桌面,只是从站点简单安装 我没有访问命令提示版Git的权限。我有.idea文件夹要排除在跟踪范围之外。知道怎么做吗?

  • 我在settigns.xml文件中添加了代理配置,但Maven没有使用它,我通过使settings.xml文件无效来确认这一点。我运行maven install命令来更新设置和全局设置以指向正确的文件,仍然没有运气。我正在使用maven3.0.4。