Чтобы проверить, полностью ли записан файл - PullRequest
1 голос
/ 12 октября 2011

Как узнать, что программное обеспечение завершило запись файла, если я выполняю это программное обеспечение из Java? Например, я выполняю geniatagger.exe с входным файлом RawText, который создаст выходной файл TAGGEDTEXT.txt. Когда geniatagger.exe закончит запись файла TAGGEDTEXT.txt, я могу сделать некоторые другие действия с этим файлом. Проблема в том, как я могу узнать, что geniatagger закончил писать текстовый файл?

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

Ответы [ 2 ]

1 голос
/ 12 октября 2011

Вы не можете или, по крайней мере, ненадежно.

В этом конкретном случае вам лучше всего наблюдать за завершением процесса.

Вы получаете код возврата процесса в качестве бонуса, который может сообщить вам, если произошла ошибка.

Если вы на самом деле говорите о этом теге GENIA , ниже приведен практический пример, демонстрирующий различные темы (см. Пояснения к пронумерованным комментариям под кодом). Код был протестирован с версией 1.0 для 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() ({5}) может никогда не завершиться.

  3. Обратите внимание, что я передал FileInputStream процессу. Согласно вышеупомянутой странице GENIA, эта команда ожидает фактический ввод вместо параметра -i. OutputStream, который подключается к процессу, должен быть закрыт, иначе программа продолжит работать!

  4. Скопируйте результат процесса в FileOutputStream, файл результатов, который вы ожидаете.

  5. Дайте основному потоку дождаться завершения процесса.

  6. Очистить все потоки.

0 голосов
/ 12 октября 2011

Если программа завершает работу после генерации выходного файла, вы можете вызвать 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);
}
...