You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows10下Java调用Haskell程序,如何无需关闭输入流获取输出

Ah, I see the root of your problem! Let's break this down and fix it step by step.

Why Your Current Setup Isn't Working

Your Haskell script uses the interact function, which is designed to read the entire input stream until it hits EOF (end-of-file), process it all at once, and then write the entire output. That's why you have to close the Java output stream (sending an EOF signal) to get any output—Haskell is waiting for the entire input before it does anything.

When you run simple.exe in CMD, you probably thought you were doing "repeat operations" but were actually restarting the program each time, or sending EOF with Ctrl+Z to trigger the output. It's not truly interactive as you expected.

Step 1: Fix the Haskell Script for Interactive Line-by-Line Handling

To make the program respond to each input line immediately (without waiting for EOF), rewrite it to process lines one at a time. Here are two clean options:

Option 1: Recursive Loop

import Data.Char (toUpper)

main = do
    line <- getLine
    putStrLn $ map toUpper line
    main -- Recurse to handle the next line

Option 2: Use forever from Control.Monad

import Data.Char (toUpper)
import Control.Monad (forever)

main = forever $ do
    line <- getLine
    putStrLn $ map toUpper line

Compile this new script to simple.exe—now when you run it in CMD, typing a line and pressing Enter will immediately spit out the uppercase version, and you can keep doing this until you hit Ctrl+C to exit.

Step 2: Adjust Java Code for Asynchronous IO

When Java interacts with external processes, you need to handle input and output on separate threads to avoid deadlocks. If your main thread tries to read output while the Haskell process is waiting for input (or vice versa), both will freeze up.

Here's a revised Java implementation that works interactively without closing the input stream:

import java.io.*;

public class Main {
    public static void main(String[] args) {
        try {
            Process process = new ProcessBuilder("simple.exe").start();

            // Thread to handle output from the Haskell process (prevents blocking)
            Thread outputHandler = new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                    String response;
                    while ((response = reader.readLine()) != null) {
                        System.out.println("Haskell output: " + response);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            outputHandler.start();

            // Main thread handles sending input to Haskell
            try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()))) {
                // Send first input
                writer.write("Hello");
                writer.newLine();
                writer.flush(); // Critical: pushes data out of Java's buffer to the process

                // Simulate a delay and send another input
                Thread.sleep(1000);
                writer.write("World");
                writer.newLine();
                writer.flush();

                // Keep running or add more inputs as needed
                // To terminate later: writer.close() or process.destroy()
            }

            // Wait for the output thread to finish before exiting
            outputHandler.join();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Key Notes for Java:

  • Separate Threads: Always handle the external process's output in a dedicated thread—this prevents your main thread from blocking while waiting for output.
  • Flush After Write: Calling writer.flush() ensures that Java sends the input to the Haskell process immediately, instead of holding it in an internal buffer.
  • No Early Stream Closure: You no longer need to close the output stream to get output, since the Haskell program now processes each line as it arrives.

With these changes, your Java program can send multiple inputs to the Haskell process and receive outputs in real time, without restarting the process or closing the input stream.

内容的提问来源于stack exchange,提问作者MarwinStockholm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:12:11