2013-08-14 1 views
2

У меня возникли проблемы с определенным сегментом моего кода. Предполагается, что программа Java принимает некоторые предопределенные переменные и использует функцию «sed» UNIX для замены строк «AAA» и «BBB» в предварительно написанном сценарии оболочки. У меня есть три метода для этого: один, который заменяет строки в файле с помощью команды «sed» и записывает вывод в другой файл; тот, который удаляет исходный файл с помощью команды «rm»; и тот, который переименовывает выходной файл в имя исходного файла с помощью «mv». Есть три копии сценария оболочки в трех разных каталогах, и каждый из них должен быть заменен его собственными конкретными переменными.Пустой выходной файл генерируется при запуске Java-процесса

Замена должна произойти для всех трех файлов сценариев оболочки, но это происходит только для двоих. В третьем скрипте оболочки кажется, что процесс не завершился, так как размер байта этого файла равен 0. Файл, который не заменен, является полностью случайным, поэтому не один и тот же файл не работает во время каждого прогона.

Я не уверен, почему эта ошибка происходит. Есть ли у кого-нибудь возможные решения? Вот код:

public void modifyShellScript(String firstParam, String secondParam, int thirdParam, int fourthParam, String outfileDirectoryPath) throws IOException{ 
    String thirdDammifParamString = ""; 
    String fourthDammifParamString = ""; 
    thirdDammifParamString = Integer.toString(thirdDammifParam); 
    fourthDammifParamString = Integer.toString(fourthDammifParam); 
    String[] cmdArray3 = {"/bin/tcsh","-c", "sed -e 's/AAA/"+firstDammifParam+"/' -e 's/BBB/"+secondDammifParam+"/' -e 's/C/"+thirdDammifParamString+"/' -e 's/D/"+fourthDammifParam+"/' "+outfileDirectoryPath+"runDammifScript.sh > "+outfileDirectoryPath+"runDammifScript.sh2"}; 
    Process p; 
    p = Runtime.getRuntime().exec(cmdArray3); 
} 

public void removeOriginalShellScript(String outfileDirectoryPath) throws IOException{ 
    String[] removeCmdArray = {"/bin/tcsh", "-c", "rm "+outfileDirectoryPath+"runDammifScript.sh"}; 
    Process p1; 
    p1 = Runtime.getRuntime().exec(removeCmdArray); 
} 

public void reconvertOutputScript(String outfileDirectoryPath) throws IOException{ 
    String[] reconvertCmdArray = {"/bin/tcsh","-c","mv "+outfileDirectoryPath+"runDammifScript.sh2 "+outfileDirectoryPath+"runDammifScript.sh"}; 
    Process reconvert; 
    reconvert = Runtime.getRuntime().exec(reconvertCmdArray); 
} 
+0

Почему бы просто не использовать Java для замены строки вместо sed? – rob

+0

Функциональность UNIX, похоже, намного лучше работает с разбором файлов. Кроме того, я не хотел иметь дело с чтением из файла, находя конкретную последовательность CHAR «AAA» и заменяя ее. Это хорошая идея, без сомнения, но у меня осталось еще три часа, чтобы закончить этот скрипт, и эта проблема только что произошла. –

ответ

2

Если вы еще не сделали, посмотрите на When Runtime.exec() won't. Один или несколько Process могут быть висящими, потому что вы не потребляете потоки вывода и ошибок. В частности, посмотрите на примеры StreamGobbler.

Также может случиться так, что вы забыли включить в нижнюю черту outfileDirectoryPath. Прочитайте поток ошибок процесса, чтобы увидеть, что происходит не так:

InputStream err = p.getErrorStream(); 
// read the stream and print its contents to the console, or whatever 

Имейте в виду, что вы хотите прочитать потоки в отдельных потоках.

При этом я бы лично сделал все это изначально на Java вместо того, чтобы полагаться на внешние зависимости от платформы.

Для замены подстроки, read the file to a String, затем используйте String.replace и/или String.replaceAll.

Вы можете заменить 'тело с с вызовом File.delete:

public void removeOriginalShellScript(String outfileDirectoryPath) throws IOException{ 
    File f = new File(outfileDirectoryPath, "runDammifScript.sh"); 
    f.delete(); 
} 

Вы можете заменить reconvertOutputScript' removeOriginalShellScript s тело с призывом Files.move:

public void reconvertOutputScript(String outfileDirectoryPath) throws IOException{ 
    File src = new File(outfileDirectoryPath, "runDammifScript.sh2"); 
    File dst = new File(outfileDirectoryPath, "runDammifScript.sh"); 
    Files.move(src, dst); 
} 

Или просто заменить как removeOriginalShellScript и reconvertOoutputScript с вызовом Files.move, указав опцию REPLACE_EXISTING:

File src = new File(outfileDirectoryPath, "runDammifScript.sh2"); 
File dst = new File(outfileDirectoryPath, "runDammifScript.sh"); 
Files.move(src, dst, REPLACE_EXISTING); 
+0

Спасибо за отличный ответ. Я не использовал эту функцию Java. Тем не менее, я хотел бы сохранить это как последнее средство, потому что эта функция является БОЛЬШОЙ частью моего кода, и для включения этих функций в мои методы потребуется много времени и заменить все необходимые строки. Тем не менее, мне любопытно, почему мои методы работают для двух моих файлов, а не для третьего.Кажется, что это не проблема с тем, как я написал свой код, но с чем-то другим. –

+0

Если вы хотите сохранить один и тот же API, вы можете просто заменить содержимое существующих методов этими более простыми, чистыми реализациями Java. Причиной ваших висячих процессов может быть то, что просто, как потоки процесса, которые не потребляются. – rob

+0

Я обновил свой ответ, чтобы продемонстрировать, как вы можете заменить свои реализации при сохранении существующего API. Я также добавил некоторые советы по отладке; Надеюсь, поможет. – rob

Смежные вопросы