Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Вызов arj архиватора из Java


Автор: fclmfan 9.10.2011, 13:47
Здравствуйте! Архивирую файл с помощью ARJ из Java...
Код

public class Main {

    public static void main(String[] args) {
        Runtime r = Runtime.getRuntime();
        Process p = null;
        try {
            p = r.exec("arj.exe a -e a.arj a.txt");
            System.out.println(p.waitFor());
        } catch (Exception e) {
            System.out.println("Error!!!");
        }
        System.out.println("ARJ returned " + p.exitValue());
    }
}

Вот сам http://narod.ru/disk/27780366001/ARJ.EXE.html

Если архивирую совсем маленькие файлы, то работает нормально, а если допустим 1Мб, то программа "зависает" на p.waitFor(), хотя сам файл благополучно архивируется. Если не использую waitFor(), то работает без проблем. Но мне надо именно дождаться, когда будет готов архив... Подскажите, как исправить или обойти проблему?
P.S. сам ARJ работает исправно, если запускать вручную.

Автор: Skynin 9.10.2011, 15:06
Цитата

а если допустим 1Мб, то программа "зависает" на p.waitFor(), ... Но мне надо именно дождаться,

Она то и делает - дожидается когда будет закончена работа. "Дожидается" и "зависла" в отношении потока выполнения программы - считайте одно и тоже. 
Process . waitFor() 
           causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.

Определитесь: вам чтобы ждала или не ждала?

Автор: fclmfan 9.10.2011, 17:28
Цитата(Skynin @  9.10.2011,  15:06 Найти цитируемый пост)
Определитесь: вам чтобы ждала или не ждала?

Цитата(fclmfan @  9.10.2011,  13:47 Найти цитируемый пост)
Но мне надо именно дождаться, когда будет готов архив...

Цитата(Skynin @  9.10.2011,  15:06 Найти цитируемый пост)
"Дожидается" и "зависла" в отношении потока выполнения программы - считайте одно и тоже.

В моём случае она уже не "дожидается", а просто "зависает" на файлах бОльшего размера. Я пробовал ждать и по несколько минут, она не отлипается сама собой. Хотя если архивировать не через джаву, а просто через консоль, на 1Мбайтный файл уходит пару секунд максимум. Так что повторюсь, программа не "дожидается", а "зависает". При чём, как я уже сказал, сам архив "a.arj" появляется не диске физичеки, но программа не завершает работу.

Автор: Skynin 9.10.2011, 18:10
Цитата

Так что повторюсь, программа не "дожидается", а "зависает".

То есть проблема на уровне взаимодействия JVM и ОСи, или ОСи и arj.exe - о завершении внешнего процесса, в каких-то ситуациях (файлы больше ...) не сообщается в точку waitFor()
Программа все ждет и ждет.

Можно посоветовать либо почитать и сделать как в 
http://stackoverflow.com/questions/1247390/java-native-process-timeout
http://stackoverflow.com/questions/2150723/process-waitfor-threads-and-inputstreams
в надежде что есть какой-то тонкий нюанс, - "нельзя запускать без перехвата ввода-вывода и/или из потока main"

или заменить:
версию JVM, версию ОСи, версию arj.exe

Цитата

В моём случае она уже не "дожидается", а просто "зависает"

Когда я обнаруживаю место затыка в программе - у меня слово "зависает" исчезает.
Зависание - это когда не знаешь по какой причине программа застопорилась - ждет и ждет ввода (получения управления) или в бесконечный цикл вошла.

Автор: dobrolub 10.10.2011, 05:44
arj пытается писать в out и err, поэтому тебе надо их читать.

Читать их надо в отдельном Thread, после того как процесс стартовал.

Код

Process p = r.exec("your arj command");

final InputStream in = p.getInputStream();
final InputStream err = p.getErrorStream();

new Thread() {
  public void run() {
    try {
      while (in.read() > 0);
    } catch (Exception e) {
       e.printStackTrace();
    }
  }
}.start();

new Thread() {
  public void run() {
    try {
      while (err.read() > 0);
    } catch (Exception e) {
       e.printStackTrace();
    }
  }
}.start();

p.waitFor();


Если читать не будешь, то arj будет пытаться писать в стрим из которого не читают. По заполнению стрима, arj будет ждать когда операция вывода в консоль завершиться.

Думаю, что архивация мелких файлов не вызывает переполнения буффера, а архивация больших - вызывает.


Автор: fclmfan 10.10.2011, 08:14
dobrolub, спасибо! Ваш способ помог! И Skynin, тоже спасибо за помощь.

Автор: math64 10.10.2011, 08:41
Можно запускать через .bat файл
Код

arj.exe a -e a.arj a.txt >/a.log

и вывод попадёт в файл и его можно не читать или прочитать позже.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)