我试图解决这个问题,但没有取得多大成功。希望得到一些帮助。
从我的 Java 程序内部,我正在调用一个外部可执行文件,它在完成后会创建一个文本 (ASCII) 文件。我在用
Process p = Runtime.getRuntime().exec("....exe");`
接下来,我要求它在切换之前完成
int exitValue = p.waitFor();
并确保退出值为 0。
在那之后,我正在创建一个 Scanner 对象来读取新创建的文件:
File outputFile = new File(outputFileName);
Scanner scan = new Scanner(outputFile);
该文件与可执行文件位于同一文件夹中,但无论如何我都将完整路径传递给它。
当我检查我是否可以读取文件 ( outputFile.canRead()
) 时,答案是正确的。
当我检查文件的长度时,它返回给我一些 > 0 的数字,即 440827。
但是,当我尝试调用scan.hasNextLine()
or时scan.hasNext()
,答案是否定的。
一个有趣的事实是,当我在 NetBeans 调试模式下运行它时,一切正常。所以,我的猜测是我处于某种竞争状态,即使我正在采取预防措施不中断进程的线程。我试图Thread.sleep()
在调用之前插入语句nextLine()
,但没有结果。
请问有什么建议吗?
这是代码的简化版本......根据要求,这里有更详细的处理(分布在 4 个类之间) - 我为几个级别的重定向道歉:
public class A
{
private void runEngine()
{
try
{
// Skip irrelevant stuff - model is an object of class B:
model.runEngineIfNeeded(keepInputFiles);
outputFileTextArea.setText(
model.processOutput(keepInputFiles, keepOutputFiles));
//...
}
catch (Throwable ex)
{
LOGGER.log(Level.SEVERE, null, ex);
}
}
public class B
{
public void runEngineIfNeeded(boolean keepInputFiles)
throws IOException, InterruptedException
{
// exit under some condition, otherwise:
boolean enginOK = false;
while(!enginOK)
enginOK = createEnginFile(keepInputFiles);
}
public boolean createEnginFile(boolean keepFile)
{
String engineDir = "C:/data";
final String[] cmdArray = {"cmd", "/C", B.EXE_FILENAME};
// output is a 2-dimensional array of strings
output = Exec.getSTDERRandSTDOUT(cmdArray, engineDir);
if (output[1].isEmpty())
return true; //no exception occur
// do some data manipulation and...
return false;
}
public String processOutput(boolean keepLoopinInput, boolean keepLoopinOutputs)
throws IOException, InterruptedException
{
String enginOutput = null;
while (enginOutput == null)
{
enginOutput = c.processEnginOutput(); // c is an obj of class C
if (enginOutput == null)
createLoopinFile(keepEngineInput);
}
return enginOutput;
}
}
public class Exec
{
public static String[] getSTDERRandSTDOUT(String[] cmd, String directory)
throws IOException, InterruptedException {
String[] output = new String[2]; // 2 string array for output
ProcessBuilder processBuilder = new ProcessBuilder(cmd);
if (directory != null) {
processBuilder.directory(new File(directory));
}
Process process = processBuilder.start();
ExecStreamRedirect stdout = new ExecStreamRedirect(process.getInputStream(),
OutputType.STDOUT);
stdout.start();
ExecStreamRedirect stderr = new ExecStreamRedirect(process.getErrorStream(),
OutputType.STDERR);
stderr.start();
int waitFor = process.waitFor();
output[0] = stdout.getSTDOUT().toString();
output[1] = stderr.getSTDERR().toString();
return output;
}
}
class C
{
public String processEnginOutput(float actKtDLS, boolean keepOutputs)
throws FileNotFoundException, InterruptedException,
IOException
{ // Read file into Output text area:
File analysisOutputFile = new File(outputFileNamePath);
Scanner scan = null;
String scanLine = "";
StringBuilder enginOutput = new StringBuilder(
(int) analysisOutputFile.length());
boolean outputFileOK = false;
// Must be careful here, possibility for endless loop:
stop: for (int i = 2000; i < 4000 && !outputFileOK; i+= 100)
{
int j = 0; // start counting lines
try
{
if (GenericUtils.waitIfFileIsNotReady(analysisOutputFile, j))
// does not exist & readable
continue; // go to next iteration
scan = new Scanner(analysisOutputFile);
for (; !outputFileOK; j++)
{
scanLine = scan.nextLine();
enginOutput.append(scanLine).append("\n\n");
// .. more logic here;
}
// .. more logic here;
scan.close();
return enginOutput.toString();
} // end of try
catch (NoSuchElementException ex)
{ //EOF reached
processEngineDelay(
"output file is not completly written. Last line read: "
+ j + ". " + scanLine +
". Wait " + i + " msecs.",
scan,
i);
} // continue [stop] with the next loop iteration...
} // repeat up to 20 times if needed
}
private static void processEngineDelay(String msg, Scanner scan, int i)
throws InterruptedException
{
// to perform error processing
LOGGER.warning(msg);
scan.close(); // close scan
scan = null;
Thread.sleep(i);
}
}
我想就是这样......我很抱歉 - 代码很复杂,这就是我最初只提供简化版本的原因。希望我列出了所有相关部分