1

我试图解决这个问题,但没有取得多大成功。希望得到一些帮助。
从我的 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);
   }
}

我想就是这样......我很抱歉 - 代码很复杂,这就是我最初只提供简化版本的原因。希望我列出了所有相关部分

4

0 回答 0