检查文件是否完整写入

时间:2011-10-11 21:03:25

标签: java file process runtime

如果我从java执行该软件,如何知道软件是否写完文件?例如,我正在使用输入文件RawText执行geniatagger.exe,该文件将生成输出文件TAGGEDTEXT.txt。当geniatagger.exe写完TAGGEDTEXT.txt文件后,我可以用这个文件做一些其他人员。问题是 - 我怎么知道geniatagger写完文本文件了?

try{
  Runtime rt = Runtime.getRuntime();
    Process p = rt.exec("geniatagger.exe -i "+ RawText+ " -o TAGGEDTEXT.txt");
  }

2 个答案:

答案 0 :(得分:1)

你不能,或者至少不可靠。

在这种特殊情况下,最好的办法是观察过程完成。

您可以将流程'返回代码作为奖励,这可以告诉您是否发生了错误。

如果您实际上在谈论this GENIA tagger,下面是一个演示各种主题的实际示例(请参阅代码下方有关编号注释的说明)。该代码使用v1.0 for Linux进行了测试,并演示了如何安全地运行一个过程,该过程希望输入和输出流管道都能正常工作。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.concurrent.Callable;

import org.apache.commons.io.IOUtils;

public class GeniaTagger {

    /**
     * @param args
     */
    public static void main(String[] args) {
        tagFile(new File("inputText.txt"), new File("outputText.txt"));
    }

    public static void tagFile(File input, File output) {
        FileInputStream ifs = null;
        FileOutputStream ofs = null;
        try {
            ifs = new FileInputStream(input);
            ofs = new FileOutputStream(output);
            final FileInputStream ifsRef = ifs;
            final FileOutputStream ofsRef = ofs;

            // {1}    
            ProcessBuilder pb = new ProcessBuilder("geniatagger.exe");
            final Process pr = pb.start();

            // {2}
            runInThread(new Callable<Void>() {
                public Void call() throws Exception {
                    IOUtils.copy(ifsRef, pr.getOutputStream());
                    IOUtils.closeQuietly(pr.getOutputStream());   // {3}
                    return null;
                }
            });
            runInThread(new Callable<Void>() {
                public Void call() throws Exception {
                    IOUtils.copy(pr.getInputStream(), ofsRef);   // {4}
                    return null;
                }
            });
            runInThread(new Callable<Void>() {
                public Void call() throws Exception {
                    IOUtils.copy(pr.getErrorStream(), System.err);
                    return null;
                }
            });

            // {5}
            pr.waitFor();
            // output file is written at this point.
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // {6}
            IOUtils.closeQuietly(ifs);
            IOUtils.closeQuietly(ofs);
        }
    }

    public static void runInThread(final Callable<?> c) {
        new Thread() {
            public void run() {
                try {
                    c.call();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                }
            }
        }.start();
    }
}
  1. 使用ProcessBuilder开始您的流程,它具有比普通Runtime.getRuntime().exec(...)更好的界面。

  2. 在不同的主题中设置流程管道,其他waitFor()中的FileInputStream调用可能永远不会完成。

  3. 请注意,我向该进程发送了-i。根据上述GENIA页面,该命令需要实际输入而不是OutputStream参数。必须关闭连接到流程的FileOutputStream,否则程序将继续运行!

  4. 将流程结果复制到您正在等待的结果文件{{1}}。

  5. 让主线程等到进程完成。

  6. 清理所有溪流。

答案 1 :(得分:0)

如果程序在生成输出文件后退出,那么您可以调用Process.waitFor()让它运行完成然后您可以处理该文件。请注意,您可能不得不耗尽标准输出和错误流(至少在Windows上)以完成该过程。

<强> [编辑]

这是一个未经测试且可能充满问题的例子:

  // ...
  Process p = rt.exec("geniatagger.exe -i "+ RawText+ " -o TAGGEDTEXT.txt");
  drain(p.getInputStream());
  drain(p.getErrorStream());
  int exitCode = p.waitFor();
  // Now you should be able to process the output file.
}

private static void drain(InputStream in) throws IOException {
  while (in.read() != -1);
}