Creating a Runnable jar with optional parameters - java

Curious little issue I am running into here:
I would like a client to be able to do something like:
(1) java -jar myJar.jar inputFile outputFile
or
(2) java -jar myJar.jar text outputFile
outputFile is an optional argument.
Essentially (1) will read input from a file for them, while (2) they provide the input my program will use directly. There is no way to determine whether or not the argument is the input or whether it is the location of the file though that I can think of. For normal command line stuff you would specify a flag like -i inputfile to show you want it to read from a file. What are my options here that maintain ease of use for the client?
Is my only option to create a syntax the client must use for the first argument? i.e.
"-t text" or "-i inputFile"?
I have seen libraries such as commons cli which would enable this, but I would prefer a solution that does not involve using a library.

If I understood the problem correctly, can't you just check the number of arguments instead of explicitly specifying direct input? Like, if one arg is passed the first arg is output, and if 2 args are passed then the first arg is input and the second arg is output?
With that being said - Using a 'option' syntax of the hyphen- kind is probably easiest on most people used to a cli.

I would suggest to read from standard input (System.in) and print to standard out (System.out)
This way, no parameters are required. It's very intuitive for people who work with CLI tools. And you can leave the details of where the input comes from to the OS.
So in a unix OS, you would use your jar something like this:
echo "some test" | java -jar myjar.jar > outfile
or
cat somefile | java -jar myjar.jar > outfile

You can use
input=text or file=inputfile
(with output=outputFile as optional).
In this case, you can treat all your parameters in the same way and split them with the delimiter '=', check the left side of '=' to determine which parameter it is.

Related

How to recursively call a Java program with PowerShell and pass in a file path

I am trying to batch rename files in a folder. For example, right now I want to remove the character at the second index in the names of all of the files in a given folder. I have written a Java program that will do this given the path of the file.
The problem is that I am trying to batch the process with PowerShell, and I have very little knowledge of PowerShell. I basically just started using it today, and mainly to test run my Java program from the command line. I decided to try PowerShell for this because I saw a YouTube video where someone used PowerShell recursively to remove a certain character (like a "-") from every spot it appears in every file name in a folder. I thought maybe I could recurse with PowerShell to batch the process of changing every file name.
I want to recursively call the Java program with PowerShell and have PowerShell pass in each path of each file one by one in a folder to the Java program. I don't know if this is possible, but I'm hoping it is.
I have tried the following, though since I don't really any knowledge of PowerShell, I don't really know what to try. "Copy" is the name of the folder in which the files I want to modify are located.
get-childitem -recurse | java -cp "C:\Users\Media PC\Documents\Renamer\src\main\java" org.example.Main $_.name
I am getting the Java program to run, because I'm getting an error back from the program saying I didn't pass in a proper file path.
Building on Abraham Zinala's helpful comment:
Leaving aside the fact that invoking an external program (i.e., creation of a child process) file by file is inefficient:
Get-ChildItem -File -Recurse | ForEach-Object {
java -cp "C:\Users\Media PC\Documents\Renamer\src\main\java" org.example.Main $_.FullName
}
Note: The -File switch limits results to just files (doesn't include directories).
PowerShell's automatic $_ variable can only be used inside script blocks ({ ... }), so using $_.name as an argument as-is won't work.
See this answer for all contexts in which $_ is meaningfully defined.
In order to pass an argument to a command that isn't designed to take its input directly from the pipeline, use the ForEach-Object cmdlet for custom-processing of each input object one at a time.
Inside the script block passed to it, you can use $_ to refer to the pipeline input object at hand.
Get-ChildItem outputs instances of the following .NET types:
System.IO.DirectoryInfo(for directories) and
System.IO.FileInfo (for files)
Their .FullName property contains their full, file-system-native path, so $_.FullName is a robust way to refer to just that. Given that .Name only reports the mere file name, it wouldn't be sufficient to identify the file at hand in a recursive traversal of the current dir.
In PowerShell (Core) 7+, you could use just $_, because there such instances consistently stringify as the value of their .FullName property (when passing arguments to an external program, objects are implicitly stringified) - unfortunately, this is not the case in Windows PowerShell; see this answer.

How to handle "<" in args from terminal input in java [duplicate]

I am trying to read the filename by the command line,
This is command that our professor wants us to type:
java MultiBinaryClient xxxxxx.edu 6001 < files.txt
I was trying to use args[3] to get the file name, but args only contains "xxxxxx.edu" and "6001". why not "<" and "files.txt" in the args[]? Can anyone help me out?
BTW, I am using MAC terminal to test my code, I believe my professor uses win CMD, will it make differences?
Thank you!
Let's see what each fragment means. This is how we execute a Java class containing a main method:
java MultiBinaryClient
The only command-line arguments that are being passed to your program are these ones:
xxxxxx.edu 6001
And this snippet is not part of the expected arguments to the Java program:
< files.txt
It's just Unix shell syntax to specify that the contents of files.txt must be read into your program via the standard input.
I know it's an old question, but I've had this problem recently. Here's what I've done to handle it:
Well, as the others said, the "<" redirects the file contents to stdin. If you want to use the file contents as program arguments, you can use xargs:
xargs -a FILE java JAVA_ARGS
or, more specifically:
xargs -a FILE java -cp CLASSPATH CLASS_WITH_MAIN_METHOD
< is a redirection. The file will be streaming over stdin.
You should escape the '<'
java MultiBinaryClient xxxxxx.edu 6001 \< files.txt

How to use Java to run a command through Mac OS Terminal

I am a high school student working on a project that will convert the video from a YouTube link into an MP3 and download it. However, the way that the video form YouTube is downloaded and converted is through the Mac OS terminal by using YouTube-dl.
This is what I put into the terminal:
youtube-dl -f bestvideo+bestaudio \"ytsearch:{https://www.youtube.com/watch?v=5X-Mrc2l1d0}\"
This works in terminal, but when I try to use:
Runtime.getRuntime().exec("cd /Users/poppa/Desktop/IA Vids");
and there's an error saying "No such file or directory"
Another Problem that I am having is running the code that is inputted into the Terminal from Java. I'm using IntelliJ IDEA if that helps. Thank You!
You have a space in the directory path. Try putting double quotes around like this:
Runtime.getRuntime().exec("cd \"/Users/zeidakel/Desktop/IA Vids\"");
Also note that executing cd command from JVM may have no effect on current user dir when (for example) creating files with new File("path")
If cd means change directory (and isn't the name of an executable), then it almost certainly won't take effect, even if it is executed correctly. The process spawned by exec() will have a working directory, and it can be changed -- but that change will only affect the spawned process.
In addition, having spaces in arguments to exec() is inherently problematic. exec() is not a shell, and you won't be able to protect the string from being split at the spaces by using shell mechanisms like quotes. Instead, you need to split the command into arguments yourself, knowing where the splits should be, and then use the form of exec() that takes a String[] as input. That is, split the arguments into an array of strings yourself, rather than relying on exec() to do it for you (wrongly).
Runtime.exec() is fraught with difficulties, and needs very careful handling. I've written extensively about this subject here:
http://kevinboone.me/exec.html

run existing java program with cmd

I have a running java program which converts a json file into another file format. Everything works great.
For the implementation I decided to use the MVC pattern.
Now I want to implement the whole conversion routine so that I can use a command prompt but I never worked with that and don't know how to achieve this at all.
My thoughts were:
Open cmd and navigate to the main.java-file.
Print out the whole possibilities (the user should be able to enter the dir of the source file and the target dir, the user should be able to choose the target format).
If everything has been entered by the user, the conversion routine should be started by pushing ENTER.
Help would be really nice. For the moment I just know how to compile (javac helloWorld.java) and print "Hello World!" by exeuting a program with java helloWorld...
The apache commons cli project provides utilities for parsing command line arguments and providing help menu. This makes it pretty simple to handle the args provided to your main method.
You will also need to provide scripts to assemble your class path. You can look at the maven app assembler plugin for ways of doing this.
The interaction between a shell/command prompt and the started Java program is very similar to the way it works in C programs*. The main() method receives arguments as strings from the command line (or from any other parent process which executes the java runtime).
In Java you get an array of strings. You need to decide yourself which string has what meaning.
public static void main(String[] arg) { // traditional or String ... args
System.out.println("You have " + arg.length + " arguments);
if (arg.length >= 1) System.out.println("First: " + arg[0]);
}
When starting a Java runtime with arguments, it is important to note, that arguments start after the class name (or the JAR name):
java -cp . package.Main arg0 arg1 ...
java -jar package.jar arg0 arg1 ...
The Java runtime also has an mechanism to specify system properties on the command line. This is done with the -D option.
java -Dverbose=yes -jar package.jar arg0 arg1 ...
java -jar package.jar -Dverbose=yes arg1 ... //not a system property but arg[0]
It is important, that this option is specified before the class/jar-name, otherwise it will not be processed by the runtime, but you will see another argument.
String verbose = System.getProperty("verbose", "false");
The reason why system properties are useful: you can use them for optional control, so you do not have to worry about recognizing arguments (there are a number of libraries out there which can do that but for small tools I think it is overkill).
BTW: there are some interactions between shells/prompts and started programs when using wildcards (* and ?) and whitespace/quoting - those are OS specific.
* in C the first argument args[0] is the program name, in java arg[0] is the first argument after the class name.

Problem with run DOS command in Java

Dear all
I want to execute a EXE file in Java, but I was not able to do it correctly.
Originally, in DOS command prompt, my command is like this:
C:>\crf_test.exe model <inputfile.txt> outputfile.txt
Note: the input file name must be place in the brackets <>. It always gave me good results when run it in DOS window.
When I want my java program to call above command, I do like this:
Process p = Runtime.getRuntime().exec("crf_test.exe model <inputfile.txt> outputfile.txt");
However, the output of this command is "no such file or directory: "
I guest Java doesn't like the brackets <> in DOS command. I also remove <> out, but exe file did not accept that.
So now how can I deal with this problem? Please give me a sollution
Thank you much much
There are potentially two problems. Firstly, the one that others have mentioned - crf_test.exe may not be in your path. It's hard to tell whether your output of "no such file or directory" is from crf_test.exe or from Java trying to find crf_test.exe.
Secondly though, running it from DOS you're not really putting the filename in brackets - you're redirecting system input from the input file to the output file, so the logical grouping is:
crf_test.exe model < inputfile.txt > outputfile.txt
Now when you're running it from Java, it's genuinely trying to pass <inputfile.txt> as a second command-line argument, and outputfile.txt as a third. My guess is that crf_test.exe is then trying to load those as files, and giving "no such file or directory" as an error.
You'll need to load the data from inputfile.txt yourself and pass it in via Process.getOutputStream, and then read the output from Process.getInputStream and write it to outputfile.txt.
Alternatively, you could run cmd.exe and pass in the whole command as an argument - that way the shell will perform the redirection for you as if you were running from a DOS prompt.
The angle brackets are redirection operators: <inputfile.txt causes the input to be read in from inputfile.txt instead of the keyboard, >outputfile.txt causes the output to be written to outputfile.txt instead of the screen. This facility is provided by the shell, however when invoking your program with the Java runtime the shell is not present. Invoke via the shell, like this:
Runtime.getRuntime().exec("cmd /c crf_test.exe model <inputfile.txt> outputfile.txt");
...or redirect input and output using facilities provided by Java; see e.g. this question.
try this
Process p = Runtime.getRuntime().exec("crf_test.exe","/c","model outputfile.txt");
The problem is that the crf_test.ext is missing in your current execution folder. You need either copy the executable or use the absolute path or set the PATH variable to include the necessary path.
If I understand the problem right, you want to call
crf_test.exe model
with input from file inputfile.txt and output to outputfile.txt
You have to redrect in and out and call only crf_test.exe model. How do redirect in and out is described in how to redirect stdin to java Runtime.exec ?

Categories

Resources