Why getting argument when * doesnt work in Java? - java

I am new in Java and I want program to get as argument a different sign. For example:
java program #
And in program I convert string to char like this:
char c = args[0].charAt(0);
or like this:
char [] c = args[0].toCharArray();
But when I put *, it doesn't work. I print and get D or even name of file.

When you use * character in the command line, it becomes expanded - that's why you get a filename/list of filenames.
You may try escaping asterisk:
using backslash \ : java program \*
using double quotes " (which should also be escaped): java program \"*\"
However, in both cases you're likely to get the asterisk along with the escape character.
Other solutions to similar issue are shown here.

Related

Escape character '\' doesn't show in System.out.println() but in return value

In Java, when I replace characters in a String with escaped-characters, the characters show up in the return value, although they were not there according to System.out.println.
String[][][] proCategorization(String[] pros, String[][] preferences) {
String str = "wehnquflkwe,wefwefw,wefwefw,wefwef";
String strReplaced = str.replace(",","\",\""); //replace , with ","
System.out.println(strReplaced);
The console output is: wehnquflkwe","wefwefw","wefwefw","wefwef
String[][][] array3d = new String[1][1][1]; // initialize 3d array
array3d[0][0][0] = strReplaced;
System.out.println(array3d[0][0][0]);
return array3d;
}
The console output is:
wehnquflkwe","wefwefw","wefwefw","wefwef
Now the return value is:
[[["wehnquflkwe\",\"wefwefw\",\"wefwefw\",\"wefwef"]]]
I don't understand why the \ show up in the return value but not in the System.out.println.
Characters in memory can be represented in different ways.
Your integrated development environment (IDE) has a debugger that chooses to represent a String[][][] with a single element that contains the characters
wehnquflkwe","wefwefw","wefwefw","wefwef
as a java-quoted string
"wehnquflkwe\",\"wefwefw\",\"wefwefw\",\"wefwef"
this makes a lot of sense, because you can then copy and paste this string into java code without any loss.
On the other hand, your system's console, and the IDE's built-in terminal emulator, will output the characters in their normal representation, that is, without any java string-escape-characters:
wehnquflkwe","wefwefw","wefwefw","wefwef
As an experiment, you may want to check what happens with other "special" characters, such as \t (a tab break) or \b (backspace). This is just the tip of the iceberg - characters in Java generally translate into unicode points, which may or may not be supported by the fonts available in your system or terminal. The IDE's way of representing characters as java-quoted strings allows it to losslessly represent pretty much anything; System.out.println's output is a lot more variable.
System.out.println prints the String exactly as it is stored in memory.
On the other hand, when you stop the application flow using a breakpoint you are able to look up the values.
Most of the IDEs display escape characters with \ to indicate that it's just one String, not String[] in this case, or not to split the String into two lines if it contains \n in the middle.
Just in case, you still have doubts, I suggest printing strReplaced.length(). This should allow you to count characters one by one.
Possible experiments:
String s = "my cute \n two line String";
System.out.println(s + " length is: " + s.length());

Can't get PowerShell to read the * character

I'm a beginner in Java programming and while i was trying to create a calculator i've come across this problem: the powershell manages to read every character properly except for the asterisk, i've tried writing it in many ways: *, "*", '*' but it still acts as a wildcard character and not as a proper asterisk. How do i fix this?
Example: If I write
java Calculator 1 2 *
java Calculator 1 2 "\*"
java Calculator 1 2 '*'
none of these work and it always gets the asterisk as a wildcard character.
Your problem is not related to PowerShell per se, because it passes * through - however, it does so without quoting, whether you use *, "*", or '*'.
Therefore, the question is: What kind of quoting of * does your target program require for it to treat * as a literal rather than as a glob (wildcard expression)?
For instance, if you need to ensure that your target command sees the * as "*", you must use literal (embedded) double quotes:
java Calculate 1 2 `"*`" # `" escapes a literal "
or, using single quotes with embedded literal " instances:
java Calculate 1 2 '"*"'
Note that since Powershell doesn't recognize \ as an escape character, using \* as-is would suffice to pass literal character sequence \* - unquoted - to java.
Optional background information:
PowerShell - unlike POSIX-like shells (in the Unix world) - does not itself automatically expand (unquoted) wildcard-like arguments such as * to matching filenames (it is up to the target commands to interpret such wildcards).
Therefore, when you call external utilities such as java, tokens such as * are passed through.
However, whether you use * unquoted or whether you quote it as '*' or "*" makes no difference in this case, because PowerShell, after it has performed its own parsing, rebuilds the command line, using (double)-quoting around the arguments only if needed.
Token * needs no quoting, because it has no embedded whitespace, therefore, all 3 variations of your command result in the exact same command line when java is invoked: something like c:\path\to\java Calculator 1 2 *
Therefore, the only way to guarantee that an external utility sees an argument as "-enclosed, for instance, is to make the " chars. a literal part of the argument, as demonstrated above.
Have you tried using the escape Character "\*" ?
For example:
java Calculator 1 2 \*

Could someone look at my code and tell me what's wrong?

I am trying to get this simple program to work but I'm not sure what I'm doing wrong; I tried making a new file to see if the problem was with my syntax but it's still happening. Here it is:
public class test {
public static void main(String[] args) {
String operator = args[0];
switch(operator) {
case "*":
System.out.println("Hello");
break;
}
}
}
I'm trying to run this program on my terminal by first doing
$ javac test.java
and then actually running the program along with the argument
$ java test *
and I get nothing after that, any reason why? It seems to work when "*" is replaced with "+".
I also noticed that it would only work if I typed out
$ java test "*" //notice the quotation marks
Why does the asterisk without the parenthesis not work even though it is a string but "+" without the parenthesis works? Is there something I am missing?
The problem is nothing to do with Java. The problem happens because the shell will treat the * character as a filename pattern and expand it to the names of all files in the current directory.
The solution is to escape the * character on the command line. There is nothing that you can do in Java to solve this.
There are a three ways that will work as escaping (for a POSIX compliant shell)
java test "*"
java test '*'
java test \*
There may be other obscure ways to do this .... but the above should suffice.
(The difference between "*" and '*' is that they escape different shell constructs. Double quotes disable just "globbing" of file pathnames. Single quotes also disable parameter substitution and other things.)
Characters that may be need to be escaped if you use them in command line arguments include:
*, ?, [, ], ~, {, } - used in globbing, etc
$ - parameter substitution
shell symbols |, &, ;
# - the comment character
the backquote character.
You should refer to a tutorial or textboox on the shell, or read the manual entry for the shell you are using.

Is there any way to find out an argument passed to a jar was quoted?

I'm trying to pass a number of arguments to my Java application, but I would like to parse them by myself using an intelligent parser that doesn't just rely on whitespace to separate the arguments. An example:
/update source=foo func=(bar, foo ,foo,bar)
This all works nicely by converting everything to tokens and then parse those. However, a problem occurs when I add:
path="./foo/bar/foo bar.txt"
(note the double space between foo and bar).
When I use double quotes, the argument is passed as a single string, preserving the double space. The quotation marks are removed though like this:
path=./foo/bar/foo bar.txt
which makes my parser fail. But when I try to use some other character to use as quotes, like ', the parser works fine but then the shell passes the string as two separate strings, separated at the double space, therefore I lose the information that there were two spaces there.
What can I do to pass an argument using double quotes to keep the literal string representation, but also keep the information that the string was quoted, without the user having to type weird constructions like "'string'"? I'm using Java, maybe there is a way to get the entire line of arguments unparsed by the shell? Or just without the quotes being removed?
Btw, I ran this from microsoft command line, haven't tried a unix shell yet, which might even fail on the single quotes from what I read on the interwebs
On the Windows command line (using cmd.exe), you can escape double quotes with \". For example,
java MyApp path=\"./foo/bar/foo bar.txt\"
will result in
args[0] = path="./foo/bar/foo
args[1] = bar.txt"
while
java MyApp path="\"./foo/bar/foo bar.txt\""
will give you
args[0] = path="./foo/bar/foo bar.txt"
Thanks for the help I got, but I already figured it out:
I know the thing that could be quoted doesn't contain brackets, comma's or equals signs, the things that my parser recognizes.
I know that IF something was quoted and it contained spaces, those spaces would still exist within the split argument.
I know that the original string of arguments is split at every region of whitespace, so the final split arguments don't contain spaces, only those in the quoted parts.
Therefore I can assume that if I parse a split argument, that any space in there does not imply a new token has to be generated, therefore it is retained in the final string-token.
I just have to rewrite my tokenizer now to accept an array of arguments instead of the concatenated string I now create from the args array I get passed in my main() method. That way I can differentiate between skipping real whitespace (going into the next element of the array) and quoted whitespace (any other whitespace).

The issue of * in Command line argument

I wrote a program in Java that accepts input via command line arguments.
I get an input of two numbers and an operator from the command line.
To multiply two numbers, I have to give input as e.g. 5 3 *, but it's not working as written.
Why is it not accepting * from the command line?
That's because * is a shell wildcard: it has a special meaning to the shell, which expands it before passing it on to the command (in this case, java).
Since you need a literal *, you need to escape it from the shell. The exact way of escaping varies depending on your shell, but you can try:
java ProgramName 5 3 "*"
Or:
java ProgramName 5 3 \*
By the way, if you want to know what the shell does with the *, try printing the content of String[] args to your main method. You'll find that it will contain names of the files in your directory.
This can be handy if you need to pass some filenames as command line arguments.
See also
Wikipedia: glob
For example, if a directory contains two files, a.log and b.log then the command cat *.log will be expanded by the shell to cat a.log b.log
Wikipedia: Escape character
In Bourne shell (sh), the asterisk (*) and question mark (?) characters are wildcard characters expanded via globbing. Without a preceding escape character, an * will expand to the names of all files in the working directory that don't start with a period if and only if there are such files, otherwise * remains unexpanded. So to refer to a file literally called "*", the shell must be told not to interpret it in this way, by preceding it with a backslash (\).
Under MS WINDOWS not quite true: "java.exe" silently expands command line arguments with the wildcards
*
?
[abc]
, but only in the last component, so
a/*/*
does not work as you may expect.
It also ignores the entries "." and "..", but does honor other file names starting with ".".
To avoid misunderstandings: If I look at the command line of the running JAVA process with PROCEXP, I see the unexpanded args!
I found no way to work around this. In other words: As long as you have at least one file or directory in the current directory, "java Calc 3 * 7" will NOT work!
This is VERY ugly, and seems to always having been there in all JRE versions up to and including Java 8.
Does anybody have an idea how to disable Java's nasty command line expansion?
* has special meaning in shell interpreters. How to get a * literally is depending on what shell interpreter you are using. For Bash, you should put single quotes around the *, i.e. '*', instead of double quotes like "*".
Try surrounding the * with quotes like "*". The star is a reserved symbol on the command line.
Use single quotes:
java FooBar 5 3 '*'
This works with most of the popular shells (including bash and ksh).
Expanding on #Arno Unkrig's answer:
On Windows, some JVMs definitely do expand the "*" character, and it is not the shell expanding the path. You can confirm this by writing a small Java program that prints out the arguments:
public class TestArgs {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("Arg " + i + ": " + args[i]);
}
}
}
The good news is, there is a workaround! You can use #filename as an argument to JVM like this:
java #args.txt where args.txt is a text file that contains the arguments for each line. Example content:
TestArgs
*
This is equivalent to calling java with two arguments TestArgs and *. Most importantly, * is not expanded when it is included using the #filename method. I was able to find the details from this page.

Categories