How to execute "less" with paging from a Java console application?
Asked Answered
J

2

6

I need to execute the less command, with paging, from my Java console application. However, the only method I found to execute external commands is Runtime.getRuntime().exec(), which requires me to write/read input/output via streams. So commands like cat work (and less does in fact act like cat), but I need the paging functionality.

In C, I'd use system(). In Ruby, Kernel.exec does the job.

Is there any way to get this done in Java?

Jotham answered 30/1, 2012 at 14:17 Comment(0)
L
2

When you execute an external process with Runtime.exec() its standard input and output streams are not connected to the terminal from which you are running the Java program. You can use shell redirection to connect it, but first you need to know what terminal to use. There is no way to find the terminal using the standard API but probably you can find an open source library that does it.

To see that it can be done, this program opens itself in less:

public class Test {
    public static void main(String[] args) throws Exception {
        Process p = Runtime.getRuntime().exec(
                new String[] {"sh", "-c",
                "less Test.java < "+args[0] + " > "+args[0]});
        System.out.println("=> "+p.waitFor());
    }
}

To run it you should use java Test $(tty). The tty program prints the name of the terminal connected to its stdin.

I'm not too sure about the portability of this solution; at least it works on Linux.

Ladyinwaiting answered 30/1, 2012 at 15:17 Comment(5)
That's interesting - but is there any way to get the tty without passing it as an argument? I could wrap my tool in a script, but I'd rather avoid that.Jotham
You need basically a JNI wrapper for the POSIX function ttyname. You can make one yourself or use an existing POSIX Java library like JPosix (kanga.org/jposix).. It has a method called ttyname that returns the name as a byte array, haven't tried it thoughLadyinwaiting
I've put a library on github that is essentially a wrapper for ttyname and isatty. Still a little rough but should be usable: github.com/joni/TTYUtilLadyinwaiting
I figured out that this does work perfectly fine with "/dev/tty" instead of the result of $(tty).Jotham
You're right! "/dev/tty stands for the controlling terminal (if any) for the current process." tldp.org/HOWTO/Text-Terminal-HOWTO-7.html#ss7.3 Didn't know that.Ladyinwaiting
M
0

List item

The following program will work, initially it prints 10 lines , then press enter it will print next line till end of the file. run program like java Less $fileName

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;

public class Less
{


    public static void main(String args[]) throws IOException
    {
        FileReader reader = new FileReader(args[0]);
        BufferedReader buff = new BufferedReader(reader);
        String readLine;
        int lineCount = 0;
        while ((readLine = buff.readLine()) != null)
        {
           System.out.println(readLine);
            lineCount++;
            if (lineCount > 10)
            { 
                Scanner scanner = new Scanner(System.in);
                scanner.nextLine();
            }
        }
     }
}
Moribund answered 30/1, 2012 at 15:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.