3

I want to pass a string with multiple contiguous spaces as a parameter to a jar file using Windows command prompt called in another java program. The java file is something like this which prints all of its arguments:

package src;
public class myClass
{
    public static void main(String[] args)
    {
        for(int i = 0; i < args.length; i++)
        {
            System.out.println("args" + i+ ":" + args[i]);
        }
    }
}

Now, this is how I call the above main method from another java program and print the output:

package src;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class NewClass
{
    public static void main(String[] args) throws IOException
    {
        Runtime rt = Runtime.getRuntime();
        Process pr;
        String grmmClassPath ="C:\\Users\\XX\\Documents\\NetBeansProjects\\JavaApplication1\\dist\\JavaApplication1.jar";
        String className = "src.myClass";
        pr = rt.exec("cmd.exe /c java"
                 + " -cp " + grmmClassPath
                 + " " + className
                 + " \"hello   world\""
        );
        WriteProcessStream(pr);
    }

    public static void WriteProcessStream(Process pr) throws IOException
    {
        InputStreamReader isr = new InputStreamReader(pr.getInputStream());
        String startLabel = "<OUTPUT>";
        String endLabel = "</OUTPUT>";
        BufferedReader br = new BufferedReader(isr);
        String line = null;
        System.out.println(startLabel);
        while ((line = br.readLine()) != null)
        {
            System.out.println(line);
        }
        System.out.println(endLabel);
    }
}

So when I run the above program, It prints:

<OUTPUT>
arg 0 is: hello world
</OUTPUT>

That's exactly where the problem is! I want the args[0] to be with three spaces, but anything I do, I can't get args[0] with at least two contiguous spaces.

It's interesting that If I'd called the myClass' main method directly from cmd.exe, like this:

java -cp JavaApplication1.jar  src.myClass "hello   world"

I would have had the following output:

arg 0 is:hello   world

, and surprisingly, its spaces had been reserved!

I'd appreciate it if anyone could help me with this.

Diamond
  • 598
  • 5
  • 15
  • I have never tried it, but have you tried to put the spaces into quotes? – rpax Jul 02 '15 at 23:32
  • @rpax: I don't get your question. if you see more precisely, you can see that hello world is wrapped in quotes and I want it as my first argument with all of its spaces. – Diamond Jul 03 '15 at 00:43
  • Have you tried setting these command line arguments in your development environment and debugging it to see if you get the same results? I used "hello world" (3 spaces) and it still contained 3 spaces when I printed it. – Shar1er80 Jul 03 '15 at 04:27
  • @user3257464 Sorry. Now I understand what you meant. – rpax Jul 03 '15 at 08:23
  • Have you tried ""hello "world" ? That is, embed the spaces with quotes for the first parameter, and wrap the whole string in quotes. I'm afraid the cmd line parser is going to be tough to trick into taking spaces and not discarding them as whitespace – David W Jul 03 '15 at 12:15
  • @Shar1er80: You're right! I supposed that that there is no difference between calling it directly from cmd.exe and calling it from cmd.exe called from another program. I changed my question. Take a look again, please. – Diamond Jul 03 '15 at 14:58
  • @DavidW: I've changed my question, take a look again, please. – Diamond Jul 03 '15 at 14:59
  • What about if you use the output stream instead of the input stream? – Shar1er80 Jul 03 '15 at 22:55

1 Answers1

1

Necro but: don't use the Runtime.exec(String) overload. Per the javadoc (indirectly) it tokenizes the command at any whitespace ignoring the quoting rules that would apply if you entered this command line directly via CMD (or a Unix shell). The Windows executor then rebuilds the command line from the tokens, with your extra spaces lost.

Instead use the String[] overload with the correct parsing:

 p = runtime.exec(new String[]{"cmd","/c","java","-cp",classpath,classname,"hello   world"});

or you don't actually use any feature of CMD here so you don't need it:

 p = runtime.exec(new String[]{"java","-cp",classpath,classname,"hello   world"});

If you use ProcessBuilder instead, its ctor and .command(setter) are declared as String... (vararg) so you can just pass the tokens without writing new String[]{...}.

Alternatively, run CMD and give it the commandline as input:

 p = runtime.exec("cmd"); // or new ProcessBuilder + start 
 String line = "java -cp " + classpath + " " + classname + " \"hello   world\"\n";
 p.getOutputStream.write(line.getBytes());

(For this approach the output from CMD will include banner, prompt, and echo of the input.)

dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70