My Task:
1 - Read an Excel File, parse it and save the data in txt file.
2 - Read that txt file and pass it to a batch.sh file. This batch.sh file do one thing, it picks the data from the above mentioned txt file and save it in a database's table.
When I run the batch.sh file from the terminal(and give it the txt file), it works fine. It inserts the records in the database just as i want.
Problem is, when I want to do the same with the java code, the batch.sh file does not work. And also, no exception is thrown.
Some Explanation: I am using Java 7, Oracle, SQL-Loader, Linux.
Additional Information: If I rename the batch.sh file to batch.bat file and run it in Windows environment, it works perfectly fine. the batch.sh file also works fine if it is executed from the terminal. The only problem is, its not working from java code.
I am listing the java code snippet, batch.sh file and the control.txt file for the following task.
Java Code:
try{
String target = new String("/path/to/batchFile/batch.sh");
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(target);
proc.waitFor();
}catch(Exception e){
LOG.error("Exception Occured with Message : "+e.getMessage());
}
Batch.sh:
sqlldr username/password#sid control='/path/to/batchFile/control.txt' log='/path/to/batchFile/Results.log' bad='/path/to/batchFile/BadFile.bad' ERRORS=5000
control.txt:
options ( skip=1 )
load data
infile '/path/to/batchFile/TxtFileData.txt'
truncate into table TABLE_NAME
fields terminated by ","
(
column_name "replace(:column_name,'-','')"
)
P.S: I have read many post regarding the same issue, and tried every solution, but non is working. The current example of java code is taken from another StackOverFlow thread.
Any help will be highly appreciated.
You'd want runtime.getRuntime.exec(new String[]{"/bin/bash", "-c", "/path/to/script.txt"})
See here: How to execute command with parameters?
Related
The code I'm writing in Java is is close a file left open by the user. So, here is what typically happens: a user is editing an Excel file, they save it, leave it open, and then close the lid on their laptop. The file is still kept open and locked so no one else can edit it. Is there a way to kick them off and unlock the file? When they are using the file, it is "checked out." Here is what shows up:
What checked out looks like: (image)
The following code, interfacing through WinDAV with SharePoint, tells me if a file is locked or not (I know it's not great code, but it works and I've tried several other solutions including Filelock, Apache IO, FileStream, etc.):
String fileName = String.valueOf(node);
File file = new File(fileName);
boolean replaced;
File sameFileName = new File(fileName);
if(file.renameTo(new File(sameFileName + "_UNLOCK"))){
replaced = true; //file is currently not in use
(new File(sameFileName + "_UNLOCK")).renameTo(sameFileName);
}else{
replaced = false; //file is currently in use
}
So, how would I unlock a file now? The only other solution is PowerShell using SharePoint libraries, but that has a whole lot of other problems...
As per the post, you can use the tool Handle, which is a CLI tool to find out which process is locking the file. Once you have the process ID, you can kill that process. I'm not aware of any Java API that would identify the culprit process. For killing the process you can use taskkill, and you can call it using Runtime like this. Both the operation require you app to run at Administrator or above privilege.
I try to delete a file on OSX via Java and it doesn't work.
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(new String[] { "/bin/bash", "-c", "rm file.pdf" });
Any idea?
You don't need to execute a shell command to do this. In fact, using a shell command to do this will make your app platform-specific, rather than platform-independent.
Simply create a reference to the file, and call the delete() method:
File fileToDelete = new File("/path/to/file").delete();
There are also methods on the File class that allow you to create temporary files.
The delete on exit functions should be avoided, as noted by Alexander's comment, and this bug/proposed fix on the Oracle support pages.
NOTE: All file access (reading, writing, deleting) is run through a SecurityManager, so if the user under which your application is running doesn't have the necessary security rights to the file in question, these operations may fail. If you simply keep your app running in user space, are only accessing files that the user has access to, or are only dealing with temporary files, you should be fine.
You can do this to delete your file.
try{
File f1 = new File("path to file");
boolean success=f1.delete();
if(!success){
// Notify user that the file
}
}catch(SecurityException ex){
// No sufficient rights to do this operation
}
As normalocity had mentioned java.io.File class has a method to delete a file
For fancier file/directory operations you may want to check out FileUtils from apache.
I am making a project for college and have made a program which creates csv files. I would like there to be a button which you can click which then opens the csv file with excel. Thanks
Knowing that MsOffice is installed on the system, you should be able to open a document with it from command line using the command
excel myDoc.csv
to execute such a command from java, you could use this snapshot:
File myCSVFile; //reference to your file here
String execString = "excel " + myCSVFile.getAbsolutePath();
Runtime run = Runtime.getRuntime();
try {
Process pp = run.exec(execString);
} catch(Exception e) {
e.printStackTrace();
}
This is somewhat rough and needs styling, of course, but generally it should work. Besides, to be more graceful you could also check Windows registry, using the java.util.prefs.Preferences class, to know if MsOffice is installed and, if yes, where. But, please, be aware, if you are reckoning for MsExcel (as I understood from your post), this will automatically cancel Java's multiplatform approach. Hopefully, this helps :)
If you are using Java 6 you can use the Desktop class. Read also Opening, Editing, and Printing a File
You can use JExcel API. It will be very easy for you.
For whatever reason, execString's provided did not work for me, but the one below worked:
String execString = "cmd /c start excel \"" + filePathString + "\"";
With the other exeString's I kept getting an exception saying that the runtime cannot find the file - start or excel.
I'm running a windows program from within java:
String command = "cmd /C start "+fileName+".bat";
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(command, null, new File(currWD));
int exitValue = pr.waitFor();
The program completes successfully (exitValue == 0) and creates a file "fileName" in the working directory. I am trying in the same routine to find the size of this file:
xmlFileSize = (new File(fileName)).length();
Java finds the file yet it appear to be empty (xmlFileSize == 0). Once Java finishes I can see, however, that the file is non-empty.
How can I resolve this? All I want is that Java can correctly assesses the size of the file created by the windows program that Java has executed.
A zero-length file indicates that the file may not exist. From the docs:
The length, in bytes, of the file denoted by this abstract pathname, or 0L if the file does not exist.
Note that you use currWD as working directory for your bat-file. You could try to do:
new File(currWD, fileName).length()
to make sure you look for the file in the right directory.
It probably has to do with executing the bat file from a command shell. What does the bat file do? Is it launching a program?
I'm guessing that the script calls or executes another program and returns which allows the shell to die. This in turn let's the java process continue while the process from the script continues executing asynchronously.
According to the Java API for Process, that's allowable which it most definitely should be (link java.lang.Process)
I credit this answer to aioobe and John. As John suggests, the external program started by the batch file spawns a process that seems to be running for a while (50-300 millisec) after the Java sub-process running the batch file has returned. I resolved the problem by introducing a pause (as suggested by aioobe) :
int exitValue = pr.waitFor();
try {Thread.currentThread().sleep(300);} catch (InterruptedException e) {e.printStackTrace();}
After the pause Java seems to be able to see the files created by the external program. Thanks again to both contributors who helped me resolve this issue!
If anyone finds a more elegant solution, please, feel welcome to post.
I'm currently working on a web application that involves mounting a drive and extracting a tar.gz file, all in Java. Since the application runs in a linux environment, I figured I'd try using unix commands like "mount" and "tar".
Runtime runtime = Runtime.getRuntime();
Process proc;
String mountCommand = "mount -t cifs -o username=...";
String extractCommand = "tar xzf ..."
proc = runtime.exec(mountCommand);
proc.waitFor();
proc = runtime.exec(extractCommand);
proc.waitFor();
Running the mount command and extract command in the terminal works fine, but fails when FIRST run in java. The second proc.waitFor() returns exit code 2. However, running this code after the first failed attempt works fine. I have a feeling that the problem is that waitFor() isn't waiting until the mount command is fully completed. Am I missing anything important in my code?
Also, I'd rather do this all in Java, but I had a really hard time figuring out how to untar a file, so I'm taking this approach. (oh if anyone can tell me how to do this i would be very happy). Any suggestions would be muuuuuuuuuuch appreciated!
Making progress. In case anyone was wondering, here is how I am extracting a tar.gz file in Java. Put together from a few online tutorials.
public static void extract(String tgzFile, String outputDirectory)
throws Exception {
// Create the Tar input stream.
FileInputStream fin = new FileInputStream(tgzFile);
GZIPInputStream gin = new GZIPInputStream(fin);
TarInputStream tin = new TarInputStream(gin);
// Create the destination directory.
File outputDir = new File(outputDirectory);
outputDir.mkdir();
// Extract files.
TarEntry tarEntry = tin.getNextEntry();
while (tarEntry != null) {
File destPath = new File(outputDirectory + File.separator + tarEntry.getName());
if (tarEntry.isDirectory()) {
destPath.mkdirs();
} else {
// If the parent directory of a file doesn't exist, create it.
if (!destPath.getParentFile().exists())
destPath.getParentFile().mkdirs();
FileOutputStream fout = new FileOutputStream(destPath);
tin.copyEntryContents(fout);
fout.close();
// Presserve the last modified date of the tar'd files.
destPath.setLastModified(tarEntry.getModTime().getTime());
}
tarEntry = tin.getNextEntry();
}
tin.close();
}
Quick Answer
Since a dependency on external commands exists, simplify it like this:
#!/bin/bash
mount -t cifs -o username=...
tar xzf ...
Name it mount-extract.sh then call it using a single Runtime.exec() call.
Semi-integrated Answer
Use Java APIs.
http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/GZIPInputStream.html
http://www.jajakarta.org/ant/ant-1.6.1/docs/ja/manual/api/org/apache/tools/tar/TarInputStream.html
You will need Runtime.exec to execute the mount command.
Forward Looking
Since Java is a cross-platform software development tool, consider abstracting the mount command in your application to be derived dynamically based on the underlying operating system.
See: How can I mount a windows drive in Java?
See: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#getProperties()
Of course, Agile development would insist that this not be done until it is needed. So keep it in the back of your mind until then (as you might never run the application on anything but Unix-based systems).
Take a look at the org.apache.tools.tar package in the Ant codebase. There is a class in that package, TarInputStream, that can be used to read tar archives.
It may be related to the way you call the method.
See this answer
Basically try using
.exec( String [] command );
instead of
.exec( String command );
I'm not sure if it is even related, because you mention it runs the second time. Give it a try and let us know.
This can all be done in Java, but you have to be aware of caveats when dealing with native processes.
The waitFor() command may not be doing what you hope: if the process you started has a child process that does the actual work you need then the waitFor(), which returns when the parent process has finished, has not allowed enough time for the child process to finish.
One way to get around this is to loop over some test to see that the native processes you started have finished to your satisfaction---in this case perhaps checking if some java.io.File exists.