Detect Ctrl+C in Java Console

3.2k Views Asked by At

I have a Console-Java game. The score from the game will be saved in a JSON file if Ctrl+C is pressed. The process to save the score in a JSON file works. But I don't know, how to detect Ctrl+C from the console and if this happens, I will save the score (just a method call). With KeyListener it doesn't work on the console (only with JFrame as far as I know).

I couldn't find a solution to my problem on the internet.

Do I have to do it with Runtime? I have tried it, but it didn't work...

Runtime.getRuntime().addShutdownHook(new Thread()
{
    public void run()
    {
        Test.mainThread.interrupt();
    }
});

There are similar questions on Stackoverflow, but not for use on the console Catching Ctrl+C in Java

2

There are 2 best solutions below

6
On

Adding a shutdown hook is the right way to do it, but Test.mainThread.interrupt(); probably will not work. The JVM is already shutting down. Your mainThread is unlikely to have time to respond to an interrupt; once all shutdown hooks finish, Java terminates.

Just have your shutdown hook explicitly perform whatever actions you need taken:

Runtime.getRuntime().addShutdownHook(new Thread()
{
    @Override
    public void run()
    {
        try
        {
            Test.saveScore();
        }
        catch (IOException e)
        {
            System.err.println("Couldn't save score before terminating.");
            e.printStackTrace();
        }
    }
});
0
On

We know that CTRL-C closes the application and shuts down the JVM. And since it is a normal shutdown, it runs the shutdown hooks. So creating a shutdown hook is a correct approach:

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    // Do something to save the score 
}));

Note that we're passing a Runnable here as the shutdown task. So we can pass an object that has the required functionality:

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    gameScores.save(); // assuming we have a gameScores object in this scope
}));

Your initial attempt by interrupting the thread can be viewed as a variant of this approach. Instead of passing the business object - gameScores - we can pass the thread to interrupt it later. But it's better to operate on the business level.