【问题标题】:Mounting and untar'ing a file in Java在 Java 中挂载和解压缩文件
【发布时间】:2010-11-09 05:15:07
【问题描述】:

我目前正在开发一个 Web 应用程序,该应用程序涉及安装驱动器和提取 tar.gz 文件,全部使用 Java。由于应用程序在 linux 环境中运行,我想我会尝试使用 unix 命令,如“mount”和“tar”。

Runtime runtime = Runtime.getRuntime();
Process proc;

String mountCommand = "mount -t cifs -o username=...";
String extractCommand = "tar xzf ..."

proc = runtime.exec(mountCommand);
proc.waitFor();

proc = runtime.exec(extractCommand);
proc.waitFor();

在终端中运行 mount 命令和 extract 命令可以正常工作,但在 java 中 FIRST 运行时会失败。第二个 proc.waitFor() 返回退出代码 2。但是,在第一次尝试失败后运行此代码可以正常工作。我有一种感觉,问题在于 waitFor() 没有等到 mount 命令完全完成。我是否遗漏了代码中的重要内容?

另外,我宁愿在 Java 中完成这一切,但我很难弄清楚如何解压文件,所以我采用了这种方法。 (哦,如果有人能告诉我该怎么做,我会很高兴)。任何建议都将不胜感激!

【问题讨论】:

    标签: java process runtime tar mount


    【解决方案1】:

    查看 Ant 代码库中的 org.apache.tools.tar 包。该包中有一个类,TarInputStream,可用于读取 tar 档案。

    【讨论】:

    • 是的,这似乎是要走的路,我只是不知道在使用它时如何在提取的文件上保留最后修改的日期。
    【解决方案2】:

    这可能与你调用方法的方式有关。

    看到这个answer

    基本上尝试使用

    .exec( String [] command );
    

    而不是

    .exec( String command );
    

    我不确定它是否相关,因为你提到它第二次运行。试一试,让我们知道。

    【讨论】:

    • 感谢您的输入,但这似乎不起作用。根据我的阅读,这只是一个接一个地调用一个 exec,而无需等待每个进程完成。
    • :( 太伤心了。好吧,它实际上所做的并不是准确地分离参数。所以“命令参数选项选项”被转换为 4 个部分(命令、参数、选项、选项),那就是它。有时传递参数的顺序不正确,它使用两个字符串而不是 4 发送“命令参数”“选项选项”。
    【解决方案3】:

    这一切都可以在 Java 中完成,但在处理本机进程时,您必须注意一些注意事项。

    waitFor() 命令可能没有做你希望的事情:如果你启动的进程有一个子进程来完成你需要的实际工作,那么当父进程完成时返回的 waitFor() 不允许有足够的时间让子进程完成。

    解决此问题的一种方法是循环一些测试,以查看您启动的本机进程是否已完成并令您满意——在这种情况下,可能会检查是否存在某些 java.io.File。

    【讨论】:

    • 啊,有道理。使用那个 File 技巧会奏效,但感觉太老套了……我想在我求助之前我会再研究一下 Java 库。
    【解决方案4】:

    快速解答

    由于存在对外部命令的依赖,因此简化如下:

    #!/bin/bash
    mount -t cifs -o username=...
    tar xzf ...
    

    将其命名为 mount-extract.sh,然后使用单个 Runtime.exec() 调用来调用它。

    半集成答案

    使用 Java API。

    您需要Runtime.exec 来执行挂载命令。

    前瞻性

    由于 Java 是一种跨平台的软件开发工具,请考虑将应用程序中的挂载命令抽象为基于底层操作系统动态派生。

    见:How can I mount a windows drive in Java?

    见:http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#getProperties()

    当然,敏捷开发会坚持在需要之前不要这样做。所以在此之前请记住它(因为您可能永远不会在基于 Unix 的系统上运行该应用程序)。

    【讨论】:

    • 非常有帮助,非常感谢。我刚刚尝试了第一种快速方法,但由于同样的问题而失败了。 bash 脚本没有等到挂载完成才执行 tar 命令,程序就崩溃了。我将再次尝试使用 Java 进行提取。实际上,我之前尝试过使用 tar 库,但无法弄清楚如何在提取的文件中保留最后修改的日期,所以我放弃了。必须有一种简单的方法来做到这一点。还有一个 SMB 库 (jcifs.samba.org),看起来很有前途。
    • 现在你知道了一些你之前不知道的事情:mount 命令在完成之前就退出了。另一种解决方案是使用睡眠和循环,直到可以读取文件(或经过固定次数的迭代)。
    【解决方案5】:

    取得进展。如果有人想知道,这就是我如何在 Java 中提取 tar.gz 文件。结合一些在线教程。

    public static void extract(String tgzFile, String outputDirectory)
        throws Exception {
    
    // Create the Tar input stream.
    FileInputStream fin = new FileInputStream(tgzFile);
    GZIPInputStream gin = new GZIPInputStream(fin);
    TarInputStream tin = new TarInputStream(gin);
    
    // Create the destination directory.
    File outputDir = new File(outputDirectory);
    outputDir.mkdir();
    
    // Extract files.
    TarEntry tarEntry = tin.getNextEntry();
    while (tarEntry != null) {
        File destPath = new File(outputDirectory + File.separator + tarEntry.getName());
    
        if (tarEntry.isDirectory()) {
        destPath.mkdirs();
        } else {
        // If the parent directory of a file doesn't exist, create it.
        if (!destPath.getParentFile().exists())
            destPath.getParentFile().mkdirs();
    
        FileOutputStream fout = new FileOutputStream(destPath);
        tin.copyEntryContents(fout);
        fout.close();
        // Presserve the last modified date of the tar'd files.
        destPath.setLastModified(tarEntry.getModTime().getTime());
        }
        tarEntry = tin.getNextEntry();
    }
    tin.close();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-30
      • 1970-01-01
      • 2010-12-14
      • 1970-01-01
      • 2010-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多