Compressing and Archiving the files in the folder using Java Runtime - java

I am trying to Compress and Archive all the files in a folder, using Java Runtime class. My code snippet looks as this :
public static void compressFileRuntime() throws IOException, InterruptedException {
String date = Util.getDateAsString("yyyy-MM-dd");
Runtime rt = Runtime.getRuntime();
String archivedFile = "myuserData"+date+".tar.bz2";
String command = "tar --remove-files -cjvf "+archivedFile+" marketData*";
File f = new File("/home/amit/Documents/");
Process pr = rt.exec(command, null, f);
System.out.println("Exit value: "+pr.exitValue());
}
The above code doesn't archive and compress the file as expected, though it creates a file myuserData2009-11-18.tar.bz2 in the folder "/home/amit/Documents/".
Also the output is
Exit value: 2.
While if I execute the same command from command line, it gives the expected result.
Please tell me what I am missing.
Thanks
Amit

The problem lies in this part:
" marketData*"
you expect the filenames to be compressed to be globbed from the * wildcard. Globbing is done by the shell, not by the tools themselves. your choices are to either:
numerate the files to be archived yourself
start the shell to perform the command ("/bin/sh -c")
start tar on the folder containing the files to be archived
Edit:
For the shell option, your command would look like:
String command = "sh -c \"tar --remove-files -cjvf "+archivedFile+" marketData*\"";
(mind the \"s that delimit the command to be executed by the shell, don't use single quotes ot the shell won't interpret the glob.)

If really you want to create a bzip2 archive, I'd use a Java implementation instead of a native command which is good for portability, for example the one available at http://www.kohsuke.org/bzip2/ (it is not really optimized though, compression seems to be slower than with Java LZMA).

Related

"Cannot run program" when using Runtime.exec with spaces in program filename

I am using the below code to open the "sample.html' file.
String filename = "C:/sample.html";
String browser = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe";
Runtime rTime = Runtime.getRuntime();
Process pc = rTime.exec(browser + filename);
pc.waitFor();
However, I am getting the below error.
java.io.IOException: Cannot run program "C:/Program": CreateProcess error=2, The system cannot find the file specified
Could someone please help me figure this. Thanks in advance.
Runtime.exec(String) automatically splits the string at spaces, assuming the first token is the command name and the rest are command line parameters. Also you do not have a space between browser and file, although that is not the root cause of the problem.
It thinks you want to run "C:/Program" with two command line arguments:
"Files"
"(x86)/google/Chrome/Application/chrome.exeC:/sample.html"
Use Runtime.exec(String[]) instead, that way you have full control over what is what:
String[] command = new String[]{browser, filename};
Runtime.exec(command);
Try this.
String filename = "C:\\sample.html";
String browser = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe";
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec(new String[] {browser, filename});
} catch (IOException e) {
e.printStackTrace();
}
Stop using Runtime.exec(String) - the problem is in how it processes the single string input.
The error message indicates how/where it is failing: note that it stops after "C:/Program" (or, the first space). This indicates that exec parsed the string "incorrectly" and thus isn't even looking for the correct executable.
Cannot run program "C:/Program"
Instead, consider the use of ProcessBuilder. While the usage is still system-dependent, ProcessBuilder allows separation of the executable file-name (and need to deal with it specially) and the arguments and does it's darnedest to invoke the target correctly.
String filename = "C:\\sample.html";
String browser = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe";
ProcessBuilder pb = new ProcessBuilder(browser, filename);
// setup other options ..
// .. and run
Process p = pb.start();
p.waitFor();
From what I can tell, in Windows, ProcessBuilder will wraps the individual components in quotes; this can create a different problem when arguments contain quotes..
Parameters must be passed separately:
Process pc = rTime.exec(new String[]{browser, filename});
Using exec() is not like using the command line - you can not use spaces to delimit the command from its parameters. Your attempt would try to execute a command whose path was the concatenation of the exec and the filename as one giant string.

Java: run executable program whit particular parameters

I need to run executable progam (.exe) in java. This program have two different operating modes: GUI and Command line. The syntax to launch the program from the command line is as follows :
C:\Users\Ermanno\Desktop\ "programFolder"\"program.exe" /stext output.txt
in this way the program store the outoput in the file "output.txt".
I tired it:
Process p = new ProcessBuilder("C:\\Users\\Ermanno\\Desktop\\programFolder\\program.exe" ,"/stext a.txt").start();
does not create the output file.
I also tired to use a file batch that contains the command and run it to java but the result is the same.
You need to pass each argument in a single string:
... program.exe", "/stext", "a.txt")...
Also make sure that you start a background thread which reads the output of the child process. If there is a problem, then the child will print an error message to it's standard output and if you don't actively read it, then this output will be lost.
For this, loop over the streams p.getInputStream() and p.getErrorStream().
The latter is especially important since you say "I also tired to use a file batch". Java doesn't do anything different than a batch script. If you can't run the command from batch, it won't work from Java, either.
My experience was horrible with using the JDK ProcessBuilder and Runtime.getRuntime().exec. I then moved to Apache commons-exec. Here is an example:
String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();
CommandLine cmdLine = CommandLine.parse(line);
DefaultExecutor executor = new DefaultExecutor();
int exitValue = executor.execute(cmdLine);
I solved using file bath. This file contains the command.
String [] _s = {"cmd.exe", "/c", "start", "file.bat"};
Process pr = Runtime.getRuntime().exec(_s);

Passing a string from Java to a bash script

So I have a client and a server Java program. The client uses Java processbuilder to execute the script but my problem is that the user inputs information that needs to be passed to the bash script. So, essentially, I need to know how to send three different strings to three different variables that are being read by the bash script. This script is copying a file so I would rather not make a txt file with java and have the script read the file. I would also like a way for this to be able to run on OS X and Windows so improvements are welcome. I am using Java 7 on Ubuntu currently.
Here is a snippet of what I am trying to do:
.java
Scanner bob = new Scanner(System.in);
String workingDirectory = new String(System.getProperty("user.dir"));
File tempDir = new File(workingDirectory);
String script = new String(workingDirectory + "/copyjava.sh");
System.out.print("Designate the location of the file: ");
String loc = bob.next();
System.out.print("Type the name of the file w/ extension: ");
String name = bob.next();
System.out.print("What is the location of THIS file? "); //I know there is a way to do this automagically but I can't remember how...
String wkspace = bob.next();
ProcessBuilder pb = new ProcessBuilder( script, loc, name, wkspace);
pb.start();
File myFile = new File (name);
Script:
read loc
read name
read wkspace
cd $LOC
cp $name $wkspace
There is a problem with your shell script. The read command reads from stdin, but you are passing the input as arguments. You are also changing the case of the loc variable. Variables in the shell are case sensitive. Change your script to the following:
#!/bin/sh
loc=$1
name=$2
wkspace=$3
cd "$loc" || { printf 'failed to cd to %s\n' "$loc" ; exit 1; }
cp "$name" "$wkspace" || { printf 'failed to copy %s\n' "$name" ; exit 1; }
On a side note, you shouldn't need to call an external script written in a different language just to copy a file. You should implement this in java. Implementing this in java will also give your code the platform independence you desire.
You are passing your args on the command line but reading from stdin in your script. How about changing your script to:
cd $1
cp $2 $3
I don't see any client/server interaction but let's focus on what's really important: Your are passing the parameters to the script but your script is trying to read them from the standard input.
To fix your problem modify your script as follows:
#!/bin/sh
LOC=$1
name=$2
wkspace=$3
cd $LOC
cp $name $wkspace
Take a look at the documentation for more details.
But are not doing anything that would really need a system-specific script file. The best way to copy a file is using the own mechanism that Java provides and then you don't need to worry of the underlying operating system.
If you keep on using the script then you'll need another one for Windows systems and then decide which script you should run based on the value of the os.name system property.

How to run bat file from java with arguments (i.e file name with full path) having folder name with space

Am trying to execute the a bat file with some arguments through a JAVA programmes . the arguments are file name with full path, And this path had some folder name with space, which are creating issue and giving me the following error
Error: 'D:\Documents' is not recognized as an internal or external
command
the code is as below
String command = "D:\Documents and Settings\ A.bat" + " " D:\Documents and Settings\B.xml
1. process = Runtime.getRuntime().exec(new String[] {"cmd.exe","/c",command});
2. process.waitFor();
3. exitValue = process.exitValue();
You need to escape the \ in your string (i.e. doubling them: D:\\Documents), but that is not the problem. You can try to escape the spaces Documents\\ and\\ Settings or you use the exec method that does this for you. Just dont build the command line by yourself. Better use ProcessBuilder for starting processes.
String command = "\"D:\Documents and Settings\\" A.bat" + " \"D:\Documents and Settings\B.xml\""
Escape double quotes, so you can include double quotes in the literal, to give:
cmd.exe /x "D:\Documents and Settings\" A.bat "D:\Documents and Settings\B.xml"
I was trying to do the same thing. I googled whole day but didn't make it work. At Last I handled it in this way, I am sharing it if it comes to any use of anybody :
String command = "A.bat D:\\Documents and Settings\\B.xml";
File commandDir = new File ( "D:\\Documents and Settings ");
String[] cmdArray = { "cmd.exe", "/c", command };
1. Process process = Runtime.getRuntime().exec( cmdArray, null, cmdArray );
2. process.waitFor();
3. exitValue = process.exitValue();
I've spent a while searching on SO and the wider Internet and was about to post this as a new question when I came across this, which does seem identical to my issue...
I am trying to call a Windows batch file from Java. The batch file takes several arguments but just the first, which is a path to a data file, is of relevance to this problem. The cut-down command line that I have been experimenting with is essentially:
cmd /c c:\path\to\my\batchfile.bat c:\path\to\my\datafile.mdl
I'm using Apache Commons Exec which ultimately delegates to Runtime.getRuntime().exec(String[] cmdarray, String[] envp, File dir), the 'correct' version as opposed to the overloaded versions taking a single String command. Quoting of the arguments when they contain spaces is therefore taken care of.
Now, both the path to the batch file and/or the path to the data file can have spaces in them. If either the path to the batch file or the path to the data file have spaces in, then the batch file is executed. But if both have spaces in them then the path to the batch file is truncated at the first space.
This has to be a (Java or Windows?) bug, right? I've debugged right down to the native call to create() in java.lang.ProcessImpl and all seems ok. I'm on JDK1.6.

external program from java doesn't terminate

When I try to execute an external program from java I use this code below :
Process p;
rn = Runtime.getRuntime();
String[] unzip = new String[2];
unzip[0]="unzip";
unzip[1]=archive ;
public void dezip() throws IOException{
p = rn.exec(unzip);
int ret = p.exitValue();
System.out.println("End of unzip method");
But my last System.out is never executed, as if we exit from unzip method.
The unzip() call does only the half of the work, only a part of my archive is unzipped.
When I use ps -x or htop from command line I see that unzip process is still here.
Help please.
You probably need to read the InputStream from the process. See the javadoc of Process
Which states:
Because some native platforms only provide limited buffer size for
standard input and output streams, failure to promptly write the input
stream or read the output stream of the subprocess may cause the
subprocess to block, and even deadlock.
Check if the unzip command is prompting for something, perhaps a warning if the file already exists and if you want to overwrite it.
Also, is that a backquote I see in the middle of a java program?
Make sure external program doesn't wait for user input
Check if the the executable path is quoted when launching on Windows systems to handle directories with spaces or special characters.
PS.
I was using the java.lang.Runtime class but found that the java.lang.ProcessBuilder class is far superior. You can specify current working directory, and most importantly the system environment.
Please try the following:
p = rn.exec(unzip);
p.waitFor()
I hope it will change something.

Categories