[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1917
  • Last Modified:

Lynx, Java, & Runtime.getRuntime().exec()

LYnx is a text based browser.  It can convert .html files to its rough equivalent in text.

I am trying to use a simple java program to call lynx.bat or lynx.exe .

Lynx.bat is located in C:\Lynx\lynx.bat

I want to use the "-dump" parameter.

Then I must put the name of the file "mydoc.htm"

Then the name of the new file "mydoctxt.txt"

So in completion it would look like this "lynx.bat -dump mydoc.htm > mydoctxt.txt"

This works completely fine from the command line, but when I try to wrap it in a simple java program, it fails.

Here is what I have so far...

package javaapplication2;
import      java.io.*;
class Main{
   
    public static void main(String argv[]) {
       
        try {
            String ls_str;
           
            //Process ls_proc = Runtime.getRuntime().exec("cmd.exe /E :1900 C:\\lynx\\lynx.exe -dump C:\\test.htm > C:\\test6.txt");
            Process ls_proc = Runtime.getRuntime().exec("C:\\lynx\\lynx.bat -dump C:\\test.htm > C:\\test5.txt");

           
            DataInputStream ls_in = new DataInputStream(
            ls_proc.getInputStream());
           
           
            try {
                while ((ls_str = ls_in.readLine()) != null) {
                    System.out.println(ls_str);

                }
            } catch (IOException e) {
                System.out.println("1st catch block");
                System.exit(0);


            }
        } catch (IOException e1) {
            System.err.println(e1);
            System.out.println("2nd catch block");
            System.exit(1);
        }
       
        System.exit(0);
       
       
    }
   
   
}

When I run that a blank text file called test5.txt is created.  It is 0kb in length.  If I run it straight from the command line in windows XP though, test5.txt is created successfully.  If I uncomment out Process ls_proc = Runtime.getRuntime().exec("cmd.exe /E :1900 C:\\lynx\\lynx.exe -dump C:\\test.htm > C:\\test6.txt"); and comment out the other line, the program lags and nothing happens.

I know I have to be missing something simple here, because I whipped up the equivalent prog in VB, in like 3 minutes.
0
bullyellis
Asked:
bullyellis
1 Solution
 
gdrnecCommented:
I had this problem once and I think that I solved by using Runtime.exec(String[] cmdarray) method instead of all one string.

so String[] cmdarray = {"C:\\lynx\\lynx.bat","-dump","C:\\test.htm",">","C:\\test5.txt"};
Runtime.getRuntime().exec(cmdarray);

I think I remeber this solving it. Hope I'm right.

Geoff
0
 
zzynxSoftware engineerCommented:
Sure it isn't a matter of (back) slashes.

Did you try these already?

            Process ls_proc = Runtime.getRuntime().exec("cmd.exe /E :1900 C:/lynx/lynx.exe -dump C:/test.htm > C:/test6.txt");
or
            Process ls_proc = Runtime.getRuntime().exec("C:/lynx/lynx.bat -dump C:/test.htm > C:/test5.txt");
0
 
WebstormCommented:
Hi bullyellis,

You cannot redirect the output with ">" unless you use cmd.exe.
You have to redirect the outputstream from the Process class to a FileOutputStream like that :

String[] cmdarray = {"cmd.exe","/E:1900","/C","C:\\lynx\\lynx.bat","-dump","C:\\test.htm"};
//String[] cmdarray = {"C:\\lynx\\lynx.exe,"-dump","C:\\test.htm"};

// cmd.exe to invoke the batch file is necessary, but not for the .exe file

RunProcess ls_proc = new RunProcess(
         Runtime.getRuntime().exec("C:\\lynx\\lynx.bat -dump C:\\test.htm > C:\\test5.txt"),
          System.in,false,
          new FileOutputStream("C:\\test5.txt"),true, // stdout redirection
          System.err,false);


// And the RunProcess class is :


public class RunProcess
{
    private Process p=null;
    private static final int BUFFER_SIZE=8192;
    private Thread th_in=null,th_out=null,th_err=null;
    private int ret_code=-1;

    public RunProcess(
        final Process p,
        final InputStream p_in,   final boolean in_close,
        final OutputStream p_out, final boolean out_close,
        final OutputStream p_err, final boolean err_close)
    {
        this.p=p;

        // Process. OUT
        (th_out=new Thread(){
            byte b[]=new byte[BUFFER_SIZE];
            InputStream inp=p.getInputStream();
            public void run()
            {
                try{
                    for(;;)
                    {
                        int sz=inp.read(b);
                        if (p_out!=null) p_out.write(b,0,sz);
                    }
                }catch(Exception e){}
            }
        }).start();

        // Process. ERR
        (th_err=new Thread(){
            byte b[]=new byte[BUFFER_SIZE];
            InputStream inp=p.getErrorStream();
            public void run()
            {
                try{
                    for(;;)
                    {
                        int sz=inp.read(b);
                        if (p_err!=null) p_err.write(b,0,sz);
                    }
                }catch(Exception e){}
            }
        }).start();

        if (p_in!=null)
        // Process. IN
        (th_in=new Thread(){
            byte b[]=new byte[BUFFER_SIZE];
            OutputStream outp=p.getOutputStream();
            public void run()
            {
                try{
                    for(;;)
                    {
                        int sz=p_in.read(b);
                        outp.write(b,0,sz);
                    }
                }catch(Exception e){}
            }
        }).start();

        (new Thread(){
            public void run()
            {
                try{
                    ret_code=p.waitFor();
                }catch(Exception ex){}
                if (th_in!=null) th_in.interrupt();
                try{if (in_close&&(p_in!=null)) p_in.close();}catch(Exception ex){}
                try{if (out_close&&(p_out!=null)) p_out.close();}catch(Exception ex){}
                try{if (err_close&&(p_err!=null)) p_err.close();}catch(Exception ex){}
                if (th_out!=null) th_out.interrupt();
                if (th_err!=null) th_err.interrupt();
            }
        }).start();
    }

    public int getReturnCode()
    {
        return ret_code;
    }

    public int waitFor() throws Exception
    {
        return p.waitFor();
    }

    public void destroy()
    {
        p.destroy();
    }
}
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
objectsCommented:
Here an examples of handing the output from a Process that you should be able to easily adapt to your requirements.

http://www.objects.com.au/java/examples/util/ConsoleExec.do
0
 
bullyellisAuthor Commented:
WebStorm,

Your code works kind of.

The problem I ran into was

RunProcess ls_proc = new RunProcess(
         Runtime.getRuntime().exec("C:\\lynx\\lynx.bat -dump C:\\test.htm > C:\\test5.txt"),
          System.in,false,
          new FileOutputStream("C:\\test5.txt"),true, // stdout redirection
          System.err,false);

The 2 instances of "test5.txt" can not be named the same thing.

I get an error that "The process cannot access the file because it is being used by another process."  And again I get the empty text file.

However if I change the code to

RunProcess ls_proc = new RunProcess(
         Runtime.getRuntime().exec("C:\\lynx\\lynx.bat -dump C:\\test.htm > C:\\testa.txt"),
          System.in,false,
          new FileOutputStream("C:\\testb.txt"),true, // stdout redirection
          System.err,false);

Then I get both testa and testb.  testa.txt works correctly and is what I want.  testb.txt however is another empty text file.

Could you explain this ?

0
 
WebstormCommented:
bullyellis, thanks for the points

When you specify a redirection with '>', cmd.exe will redirect output to this file. So, nothing will be written to the process's stdout stream, and you get an empty file.
If you specify a FileOutputStream you don't have to specify another redirection in the command line and it's only usable with cmd.exe :

RunProcess ls_proc = new RunProcess(
         Runtime.getRuntime().exec("C:\\lynx\\lynx.bat -dump C:\\test.htm"),
          System.in,false,
          new FileOutputStream("C:\\testa.txt"),true, // stdout redirection
          System.err,false);

Or

RunProcess ls_proc = new RunProcess(
         Runtime.getRuntime().exec("C:\\lynx\\lynx.bat -dump C:\\test.htm > C:\\testa.txt"),
          System.in,false,
          System.out,false,
          System.err,false);

0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now