无法通过带有Process.getOutputStream()的stdin从Java向C写入大量字节.write()

时间:2013-10-17 14:05:44

标签: java c pipe stdin outputstream

我想将String对象的内容从Java程序传输到C程序作为输入。为了避免使用temporarly文件,我想使用带有process.getOutputStream()的stdin,因为我正在通过我的Java程序使用ProcessBuilder执行C程序。

从shell开始,我的C程序可以通过键盘输入或重定向器给出的文件来工作:

#myprog < myFile.txt

当我从我的Java程序process.getOutputStream()。write()发送数据时,它正在工作,而发送的数据少于16363字节。如果更多,则发生IOException并显示消息“Stream closed”。

这是我的java代码:

ProcessBuilder processBuilder;

    if (Double.isNaN(delta2))
    {
        processBuilder = new ProcessBuilder(CMD.getPath(), Integer.toString(algoType.ordinal() + 1));
    }
    else
    {
        processBuilder = new ProcessBuilder(CMD.getPath(), Integer.toString(algoType.ordinal() + 1), Double.toString(delta2));
    }

    try
    {
        Process process = processBuilder.start();

        OutputStream writer = process.getOutputStream();

        InputStream matrixToSend = new ByteArrayInputStream(shortestPathMatrix.getBytes());

        int buf;
        int i = 0;

        if (matrixToSend != null)
        {
            while ((buf = matrixToSend.read()) != -1)
            {
                System.out.println(i++);
                if (i == 8172)
                {
                    writer.flush();
                }

                writer.write(buf);
            }

            System.out.println("plouf");
            writer.close();
        }

        ReadThread stdoutThread = new ReadThread(process.getInputStream());
        ReadThread stderrthread = new ReadThread(process.getErrorStream());

        process.waitFor();

        for (ReadThread t : new ReadThread[]
        { stdoutThread, stderrthread })
        {
            synchronized (t)
            {
                if (!t.hasCompleted)
                {
                    t.wait();
                }
            }
        }

        ProcessOutput output = new ProcessOutput(process.exitValue(), stdoutThread.targetBuffer.toByteArray(), stderrthread.targetBuffer.toByteArray());

        if (output.getReturnCode() == 0)
        {
            writer.close();
            return parseOutoutToResult(new String(output.getStdout()));
        }
        else
        {
            writer.close();
            byte[] out = output.getStdout();
            byte[] err = output.getStderr();
            String error = new String(err.length == 0 ? out : err);
            throw new IllegalStateException("Command " + CMD.getPath() + " [" + Integer.toString(algoType.ordinal() + 1) + " " + Double.toString(delta2) + "] has failed (exit code=" + output.getReturnCode()
                    + ")\n" + error);
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

在我的C代码中,我只是这样做:

FILE *f = stdin;

然后:

while (fgets(line, MAX_LINE_LENGTH, f))
{
    //process
}

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

fgets()无法执行或 假设MAX_LINE_LENGTH大于16363:由于C源使用fgets()仅在收到(EOF或)换行符(典型值为\n)后返回,Java代码将发送{在传输管道已满之前{1}}。

管道的大小是系统依赖的,并且在您的系统上似乎是16k。

此外,Java代码似乎正在发送二进制数据,其中C代码需要ascii数据(如使用\n)。因此,Java应该将它发送的整数转换为ascii格式,并将fgets()转换为后者。

答案 1 :(得分:0)

感谢大家的帮助。事实上,这是我格式化要发送的数据的方式中的一个愚蠢的错误。由于没有重新计算数据,C程序正在关闭管道......