Run batch File using Java (space in arguements issue) - java

I am trying to run a batch file from Java. The following works:
Process p1 = java.lang.Runtime.getRuntime().exec("D:\\Users\\xx\\Documents\\NetBeansProjects\\Test1\\New folder\\batch.bat");
The following does not work:
Process p1 = java.lang.Runtime.getRuntime().exec("D:\\Users\\xx\\Desktop\\Jar Test\\New folder\\batch.bat");
The error I get is "Windows cannot find 'D:\Users\xx\Desktop\Jar'. Make sure you typed the name correctly, and then try again."
Although there are spaces in both paths, for some reason the second one is not running. I have read numerous threads about escaping spaces, but none of the solutions there worked with me.
Note: I have tried to use process builder but I am also facing the same issue.

Try
Process p1 = Runtime.getRuntime().exec(new String[] {"D:\\Users\\xx\\Documents\\NetBeansProjects\\Test1\\New folder\\batch.bat"});
This form of exec() wont tokenize your input by spaces for you.

Related

How to enter UTF-8 characters inside a jar file using Scanner(System.in)

I have a java project in which i want to take input from the user.
I wrote the code in eclipse and it was running without any problems at all.
However, when I export my classes into an executable-jar file using eclipse and try to run it in the windows cmd, the Scanner(System.in) can't read charachters in UTF-8 (greek characters) or something else that i haven't thought about.
This is the part of the code where i run into the problem :
String yesORno = inp.stringScanner(); // basically a nextLine()
while (!(yesORno.equals("ΝΑΙ") || yesORno.equals("ΟΧΙ"))) { // ΝΑΙ and OXI are greek characters not latin
System.out.println("Παρακαλώ πληκτρολογίστε 'ΝΑΙ' ή 'ΟΧΙ'"); // please type ΝΑΙ or ΟΧΙ in greek
yesORno = inp.stringScanner(); // take input again
}
inp is an object of an other class which i use to take inputs, in this case with the method stringScanner()
public String stringScanner() {
Scanner in = new Scanner(System.in);
return in.nextLine();
}
So when i run the code in eclipse and enter some sample characters for testing i get :
And that's what i want to happen every time.
But when i run the jar file i get :
As you can see the jar file for some reason doesn't recognise greek NAI and yesORno.equals("ΝΑΙ") doesn't return true to stop the while loop.
The same happens with OXI
I have tried running the jar file by using a .bat file like :
start java -Dfile.encoding=UTF-8 -jar Myfile.jar
but no solution.
I've done a lot of reserch to resolve this problem but I have found nothing.
I would appreciate your help
The JVM argument -Dfile.encoding tells the JVM what is the default encoding for (text) files it may encounter. This includes stdin, stdout and stderr – mapped to System.in, System.out and System.err. But the argument will not change anything in the operating system.
Most probably, your Windows CMD is using the Windows-1253 encoding, not UTF-8. When you tell the JVM with the -Dfile.encoding argument that it would be UTF-8, that would be an outright lie …
Try start java -Dfile.encoding=Windows-1253 -jar Myfile.jar or start java -Dfile.encoding=ISO-8859-7 -jar Myfile.jar.
If you setup your system with Windows-1253, the second option may cause other problems, as ISO-8859-7 and Windows-1253 are not fully compatible. But for your test it should do the job.
According to the documentation, the way you use the scanner will always depend on the operating system's encoding settings.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Scanner.html#%3Cinit%3E(java.io.InputStream)
Look at the alternative constructors - you can define the encoding there directly. Your code could look like
Scanner in = new Scanner(System.in, "UTF-8");

Take screenshot with ADB and retrieve it in java WITHOUT writing a file

I know that one can take a screenshot from the Android device via ADB with
$ adb shell screencap -p /mnt/sdcard/sc.png
$ adb pull /mnt/sdcard/sc.png
However this writes a file on your phone and on your PC, which I want to avoid.
So I found the following SO question and the answer suggested that the image gets printed to the Std output when you do not specify a file.
I tested this from console and it really printed binary data to the console.
Android: It there a way to read screenshot from memory without saving to internal/external storage?
Now I want to utilize this technique and start a process from java, execute the
adb shell screencap
command, read the output and create a BufferedImage from the output.
I tried something like this
ProcessBuilder pb = new ProcessBuilder("cmd");
Process start = pb.start();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));
bw.write("adb shell screencap");
bw.newLine();
bw.flush();
// wait some time for the process to print the image to the console
start.waitFor(10, TimeUnit.SECONDS);
StringBuilder sb = new StringBuilder(9000000);
Scanner s = new Scanner(start.getInputStream());
while (s.hasNext()) {
sb.append(s.next());
}
String result = sb.toString();
Unluckily there are quite a few issues with my Code.
the program does not terminate after getting the screenshot - so start.waitFor does not quite work as I wanted it to work
currently my code reads characters, where i actually want to read bytes
reading with scanner seems kind of slow when reading millions of characters/bytes
Maybe someone can point me in a direction such that I can get it to work.
Thanks!
Why complicating things. If you are invoking adb and want its output just run
adb exec-out screencap -p > myimg.png
exec-out is used instead of shell to get raw data (i.e. the image).
After searching some more time I came across ddmlib which already has the functionality to take screenshots and perform various other tasks via ADB built in.
The library works great and definitely made it easier for me to execute commands via ADB.

Java ProcessBuilder Error When Space(s) In Path

So I spent half a day trying to get this to work with no positive result. I am using a Java ProcessBuilder to execute some .exe file with a couple of arguments, but the file-path contain space(s) and somehow I can't get it to work properly. I have checked a number of other SO posts and implemented solutions like surround code with escaped quotes and splitting it up in command and arguments etc. My code is below:
try {
ProcessBuilder pBuilder = new ProcessBuilder(
// Main Command.
"C:\\namewith space\\database\\postgres_db\\bin\\pg_ctl.exe",
// Command Parameters.
"start",
"-D C:\\namewith space\\database\\database",
/*The quotes in the next argument are necessary, the -o stands for 'options' and everything between the quotes are the actual database parameters which to start the Database with.*/
"-o \"-p 15000\"",
"-l C:\\namewith space\\database\\postgres_db\\bin\\postgres_log.txt");
File log = new File("\"C:\\folder\\log.txt\"");
pBuilder.redirectErrorStream(true);
pBuilder.redirectOutput(Redirect.appendTo(log));
Process p = pBuilder.start();
} catch (IOException ex) {
System.out.println("Exception Occurred: " + ex);
}
I have tried so far:
Surrounding and not surrounding each/any of the paths in the above code with escaped quotes just in case that matters (something tells me it does...).
Using the Runtime.getRuntime().exec("full command with/without any/all escaped quotes"); method, but when searching on SO I found out everyone is saying you should use the ProcessBuilder instead.
Adding parts of the above code together in different ways in the ProcessBuiler's first command String, like "\"C:\\namewith space\\database\\postgres_db\\bin\\pg_ctl.exe\" start"
The files are 100% located at the given paths, I checked this by hand and by pasting the paths in the File Explorer over 10 times.
Splitting up the command into setting the working directory of the command to C:\namewith space\ and then adding the args without that part.
The error (via the System.out.println("Exception Occurred: " + ex); ) I keep getting is: java.io.IOException: Cannot run program "C:\namewith space\database\postgres_db\bin\pg_ctl.exe": The filename, directory name, or volume label syntax is incorrect.
Please let me know if you need any extra parts/code and I will do my best to provide it in detail.
Try to break the problem down.
First just read the absolute path shown in the IOException into a File object and call the exists() method to check that the file really exists and the JVM has access to it.
If that didn't work, fix your path or the access permissions. If the file really exists and you can access it then create the ProcessBuilder without any parameters, just with absolute path to your exe.
You shouldn't get the IOException now. Then add the parameters one by one. If you find one that breaks the thing, then fix the parameter (maybe the double quotes are missing) and go onto the next until you finish.

How to read/open files with space in name

I'm trying to develop a server for mplayer using Java but I can't open files that have spaces in name (e.g. "File with space.mp3").
I'm following this tutorial here. The problem is, every time I try to open a file with spaces in name the getInputStream() read only the string before the space, generating a "file not found" error.
The path are correct in command, I tried even different formats (e.g. "File\ with\ space.mp3", "$PATH/File with space.mp3", etc), but nothing works.
What can I do to get data properly from getInputStream? How to avoid getInputStream to block when it founds a space in the String?
Ps. I use a linux system and the codes are the same as the link above (ctrl+c , ctrl+v).
thanks for the help.
The problem is the use of Runtime#exec. It thinks that the space in the file is another parameter.
Process mplayerProcess = Runtime.getRuntime().exec("/path/to/mplayer -slave -quiet -idle file/to/play.avi");
Instead, you should use ProcessBuilder which allows you to specify each parameter as a separate String eliminating the need to mess about with quotes.
ProcessBuilder pb = new ProcessBuilder("/path/to/mplayer", "-slave", "-quiet", "-idle", "file/to/play.avi");
// Other configuration options...
Process p = pb.start();

BAT File not executed fully using Runtime.exec()

I have a BAT file, which creates a number of csv files by reading DB tables. bcp.exe is used for this purpose, thus, for each CSV created from a table, there's a separate bcp.exe call. All these are found in the BAT file, which I invoke using Runtime.exec().
Now the issue I face is random. It can't be recreated in developer environment, but occurs once in a while in the production environment.
Sometimes after the BAT file is executed, only few of the CSV files have been created, and the rest is missing. But when you re-execute the same, you get all the CSVs.
Here's the code:
String command = "cmd /C " + batFilePath + " " + batParams;
LOGGER.info("Executing : " + command);
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(command);
process.getInputStream();
is = process.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
LOGGER.info(line);
}
Would really appreciate it if anyone can enlighten me on how this might happen, since I am all at sea regarding this.
Thanks in advance,
-Raj.
Just a couple of points.
The first is that I've never understood why Java insists on getting the process's output stream with getInputStream - that's just bizarre. But that's just me ranting, there's not much you can do about that :-)
Secondly, I'm not sure why you have a "naked" process.getInputStream(); in your code. I don't think it's bad but it seems unnecessary.
Thirdly (and, to be honest, this is the only one I think may help), you need to debug the batch file itself rather than your Java code.
This can be done with the following two suggestions.
First, get the error stream and look at it. It's quite possible that cmd is delivering error information which you're just ignoring.
Secondly, change the batch file to output copious amounts of debug statements, one after each line if necessary. This will hopefully pinpoint the problem down to a specific place in the batch file.
If it only happens in production (and intermittently), that's harder, but we generally find that our customers are more than willing to accept debug-style temporary patches so we can collect the information to fix the problems they're seeing.
Output from a batch file which is simply logged is also a low-risk change. Some debug code is not so low-risk and we have to test that very thoroughly before involving the customer production systems. Some will refuse point blank, a not-unwise position to take.
It might be that you are exiting your input stream code before the batch script has completed executing.
After:
Process process = rt.exec(command);
you should probably add:
process.waitFor();
If this is the case, then you could verify it in your developer environment by deliberately slowing down your batch script and checking whether you experience the problem. Try sticking something like this:
PING 1.1.1.1 -n 1 -w 5000 > NUL
into your batch file. It will pause your script for 5 seconds.

Categories

Resources