-1

I have a file lowercase.perl ,this takes one file as an input and prints all its content in lowercase into another output file.

use warnings;
use strict;

binmode(STDIN, ":utf8");
binmode(STDOUT, ":utf8");

while(<STDIN>) {
  print lc($_);
   }

and I want to run it from java

import java.io.*;

public class Sample {
    public static void main(String args[]) {
        Process process;
        try
        {
            process = Runtime.getRuntime().exec("perl lowercase.perl  <lower.eng> lowerlm.eng");

            process.waitFor();
            if(process.exitValue() == 0)
            {
                System.out.println("Command Successful");
            }
            else
            {
                System.out.println("Command Failure");
            }
        }
        catch(Exception e)
        {
            System.out.println("Exception: "+ e.toString());
        }
    }
}

but this is not working. All my files are in same directory and i am running terminal in same directory as well. What seems to be happening is that the perl script is being executed but the input parameter <lower.eng>(this has to be passed with diamond operators) that i have passed is not working properly. I have ran perl script directly and it is working fine if ran without using java.

  • 1
    Okay for future questions (and preferably edited into this one), you really should include how it isn't working (IE: what's happening that you don't want). Also, you should post any research you've done and things you've tried (preferably an [mcve]). All that said, have you tried specifying the absolute path of your script and data files (I would know this if you mentioned what you tried and research you've done)? IE: `"perl C:\\tmp\\lowercase.perl C:\\tmp\\lower.eng C:\\tmp\\lowerlm.eng"`. – Ironcache Feb 09 '18 at 18:01
  • 1
    https://stackoverflow.com/questions/14022114/perl-script-runs-in-terminal-but-doesnt-run-when-invoked-from-java-program – mob Feb 09 '18 at 18:02
  • Thankyou for your suggestion i will take care in future.I have updated my question and hope it is clear now. – user9238004 Feb 09 '18 at 18:58
  • Your Perl script is missing a `}`. – ikegami Feb 09 '18 at 19:05
  • What output are you getting (in the console and in `lowerlm.eng`)? – ikegami Feb 09 '18 at 19:06
  • the missing } is a typo here in the question sorry.no output comes in console but lowerlm.eng gets edited with the lowercase version of all the text from lower.eng this happens only when perl command is ran directly but not when ran using java – user9238004 Feb 09 '18 at 19:07

1 Answers1

0

What is a little confusing in your description is

exec("perl lowercase.perl  <lower.eng> lowerlm.eng");

... the input parameter <lower.eng> (this has to be passed with diamond operators) that i have passed is not working properly.

because that implies you want the literal string "<lower.eng>" as a command-line argument. However, in your comments you say

lowerlm.eng gets edited with the lowercase version of all the text from lower.eng this happens only when perl command is ran directly but not when ran using java

which means that actually, <lower.eng and >lowerlm.eng are shell redirections. Although not explicitly stated in the documentation of Runtime.exec, it appears that Java does not call the shell. And indeed, if in your Perl script you inspect @ARGV (e.g. by writing it to a file), you will see that your Perl script, when called from Java, is being called with the command-line arguments "<lower.eng>" and "lowerlm.eng" instead of having its input and output redirected.

There are a couple of possible solutions:

A. Use Java's ProcessBuilder to set up the redirections for you, either to and from files, or, if your input and/or output originates in the same Java program, avoid the temporary files using OutputStream and InputStream directly. This would not require any modifications to the Perl script.

ProcessBuilder pb = new ProcessBuilder("perl", "lowercase.perl");
pb.redirectInput(new File("lower.eng"));
pb.redirectOutput(new File("lowerlm.eng"));
Process process = pb.start();

B. Modify the Perl script to accept input/output filenames on the command line (e.g. Getopt::Long, although below I'm keeping it simpler), so that you don't have to rely on shell redirections.

use warnings;
use strict;

die "Usage: $0 INFILE OUTFILE\n" unless @ARGV==2;
my $INFILE  = $ARGV[0];
my $OUTFILE = $ARGV[1];

open my $ifh, '<', $INFILE  or die "$INFILE: $!";
open my $ofh, '>', $OUTFILE or die "$OUTFILE: $!";
while (<$ifh>) {
    print $ofh lc;
}
close $ifh;
close $ofh;

C. Although I don't recommend this, just for the sake of completeness: you could call the shell from Java, e.g. sh -c 'perl ...'. This is not a good idea because you would have to be very careful with quoting and all shell metacharacters.

haukex
  • 2,973
  • 9
  • 21