【问题标题】:How do i get a filename of a file inside a gzip in java?java - 如何在java中的gzip中获取文件的文件名?
【发布时间】:2010-10-21 06:42:56
【问题描述】:
int BUFFER_SIZE = 4096;
    byte[] buffer = new byte[BUFFER_SIZE];
    InputStream input = new GZIPInputStream(new FileInputStream("a_gunzipped_file.gz"));
    OutputStream output = new FileOutputStream("current_output_name");
    int n = input.read(buffer, 0, BUFFER_SIZE);
    while (n >= 0) {
        output.write(buffer, 0, n);
        n = input.read(buffer, 0, BUFFER_SIZE);
    }

    }catch(IOException e){
            System.out.println("error: \n\t" + e.getMessage());
    }

使用上面的代码,我可以成功地提取 gzip 的内容,尽管提取的文件的文件名正如预期的那样总是current_output_name(我知道它是因为我在代码中声明它是这样的)。我的问题是当文件仍在存档中时,我不知道如何获取文件的文件名。

虽然 java.util.zip 提供了一个 ZipEntry,但我无法在 gzip 文件上使用它。 有什么选择吗?

【问题讨论】:

    标签: java gzip


    【解决方案1】:

    我有点同意“Michael Borgwardt”的回复,但这并不完全正确,gzip 文件规范包含存储在 gz 文件头中的可选文件名,遗憾的是没有办法(就我而言知道)在当前的 java (1.6) 中获取该名称。如openjdk中getHeader方法中GZIPInputStream的实现所见

    他们跳过读取文件名

    // Skip optional file name
    if ((flg & FNAME) == FNAME) {
          while (readUByte(in) != 0) ;
    }
    

    我已经修改了 GZIPInputStream 类以从 gzip 存档中获取可选文件名(我不确定我是否可以这样做)(download the original version from here),您只需要添加一个成员字符串文件名;到类,并将上面的代码修改为:

     // Skip optional file name
     if ((flg & FNAME) == FNAME) {
          filename= "";
          int _byte = 0;
          while ((_byte= readUByte(in)) != 0){
               filename += (char)_byte;
          }
     }
    

    它对我有用。

    【讨论】:

      【解决方案2】:

      实际上,使用多个成员的 GZIP 文件格式允许指定原始文件名。包括带有 FLAG.FNAME 的 FLAG 的成员,可以指定名称。不过,我在 java 库中看不到这样做的方法。

      http://www.gzip.org/zlib/rfc-gzip.html#specification

      【讨论】:

        【解决方案3】:

        Apache Commons Compress 提供了两种获取文件名的选项:

        带有元数据(Java 7+ 示例代码)

        try ( //
             GzipCompressorInputStream gcis = //
                 new GzipCompressorInputStream( //
                     new FileInputStream("a_gunzipped_file.gz") //
                 ) //
            ) {
              String filename = gcis.getMetaData().getFilename();
            }
        

        与“约定”

         String filename = GzipUtils.getUnCompressedFilename("a_gunzipped_file.gz");
        

        参考文献

        【讨论】:

          【解决方案4】:

          按照上面的答案,这里是一个创建包含文件“myTest.csv”的文件“myTest.csv.gz”的示例,请注意您不能更改内部文件名,也不能将更多文件添加到 gz 文件中。

          @Test
          public void gzipFileName() throws Exception {
              File workingFile = new File( "target", "myTest.csv.gz" );
              GZIPOutputStream gzipOutputStream = new GZIPOutputStream( new FileOutputStream( workingFile ) );
          
              PrintWriter writer = new PrintWriter( gzipOutputStream );
              writer.println("hello,line,1");
              writer.println("hello,line,2");
              writer.close();
          
          }
          

          【讨论】:

            【解决方案5】:

            Gzip 是纯粹的压缩。 没有存档,它只是文件的数据,压缩。

            约定是 gzip 将 .gz 附加到文件名,而 gunzip 删除该扩展名。因此,logfile.txt 在压缩时变为 logfile.txt.gz,在解压缩时再次变为 logfile.txt。如果重命名文件,名称信息会丢失。

            【讨论】:

            • 对我的愚蠢感到抱歉,我的错误是我没有先阅读 gz。感谢您指出这一点
            • 这并不完全正确。如果查看 RFC 的 GZIP (ietf.org/rfc/rfc1952.txt),在 2.3.1 中,第 4 字节的第 4 位用于指定原始文件名。
            • -1 不完全正确,GZIP 格式可以保存原始文件名和时间戳。只需查看 GNU gzip/gunzip 的手册页,查看压缩和解压缩的 --name--no-name 选项。
            • 是的,这个答案是完全错误的。 Gzip 将名称和时间戳保存在压缩流中。您必须使用 -n 选项明确是否不保存此信息。
            猜你喜欢
            • 1970-01-01
            • 2011-04-04
            • 2020-08-27
            • 1970-01-01
            • 2010-11-03
            • 1970-01-01
            • 2010-10-29
            • 1970-01-01
            相关资源
            最近更新 更多