I have a problem. I try to copy a file and I get a FileNotFound exception. Here is my code:
File file = new File("C:\\.DS\\tmp\\client-" + node_id + ".war");
File dir = new File("D:\\Utils\\Apache\\Tomcat\\webapps");
try {
FileUtils.copyFileToDirectory(file, dir);
} catch (Exception e) {
e.printStackTrace();
}
And the exception is:
java.io.FileNotFoundException: Source 'C:\.DS\tmp\client-022.war' does not exist
at org.apache.commons.io.FileUtils.copyFile(FileUtils.java:1074)
at org.apache.commons.io.FileUtils.copyFileToDirectory(FileUtils.java:1013)
...
But the file is in that folder.
This code is called from JSF in Tomcat, so maybe it's a problem of Tomcat direcories. The file is generated in previous function via external command using ProcessBuilder, so maybe Java tries to parallel and the ProcessBuilder is finishing after the copying is done.
Also, in another method of the same class this code works perfectly:
File file = new File("C:\\.DS\\tmp\\client-" + node_id + ".properties");
File dir = new File("C:\\.DS\\ss\\engines");
try {
FileUtils.copyFileToDirectory(file, dir);
...
I've figured out that Java is "smart", so Process Builder runs in separate thread (or even process), and to fix my problem I have to change
ProcessBuilder pb = ...
pb.start()
to
ProcessBuilder pb = ...
Process p = pb.start()
p.waitFor()
Related
I need to open a video file with my code, and it works perfectly fine in Eclipse but when I export into a runnable JAR, i get an error "URI not hierarchical".
I have seen people suggest using getResourceAsStream(), but i need to have a file object as i am using Desktop.getDesktop.open(File). Can anyone help me out?
Here is the code:
try {
URI path1 = getClass().getResource("/videos/tutorialVid1.mp4").toURI();
File f = new File(path1);
Desktop.getDesktop().open(f);
} catch (Exception e) {
e.printStackTrace();
}
if it helps my folder list is like
Src
videos
videoFile.mp4
EDIT:
I plan to run this on windows only, and use launch4j to create an exe.
You can copy the file from the jar to a temporary file and open that.
Here's a method to create a temporary file for a given jar resource:
public static File createTempFile(String path) {
String[] parts = path.split("/");
File f = File.createTempFile(parts[parts.length - 1], ".tmp");
f.deleteOnExit();
try (Inputstream in = getClass().getResourceAsStream(path)) {
Files.copy(in, f.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
return f;
}
And here's an example of how you'd use it:
Desktop.getDesktop().open(createTempFile("/videos/tutorialVid1.mp4"));
C:\Users\Admin\Downloads\VID_20160226_203631957.mp4
when I execute above line in command prompt the corresponding video gets played with default media player.
But when I try to do same using java Runtime class it doesnt work.
I am using following method.
Runtime r= Runtime.getRuntime();
r.exec("C:\Users\Admin\Downloads\VID_20160226_203631957.mp4")
Use Desktop.open(File) which launches the associated application to open the file. Something like,
File f = new File("C:/Users/Admin/Downloads/VID_20160226_203631957.mp4");
try {
Desktop.getDesktop().open(f);
} catch (IOException e) {
e.printStackTrace();
}
You might prefer to build the path relative to the user's home directory; something like
File downloads = new File(System.getProperty("user.home"), "Downloads");
File f = new File(downloads, "VID_20160226_203631957.mp4");
Try this.
Runtime r= Runtime.getRuntime();
r.exec("cmd /c C:\\Users\\Admin\\Downloads\\VID_20160226_203631957.mp4");
I am having a ProcessBuilder that should delete File.txt and then rename NewFile.txt.
Problem is that both files are deleted. Any idea why and how to fix?
public class MyProcessBuilder {
public static void main(String[] args){
final ArrayList<String> command = new ArrayList<String>();
// CREATE FILES
File file = new File("File.txt");
File newFile = new File("NewFile.txt");
try{
if(!file.exists())
file.createNewFile();
if(!newFile.exists())
newFile.createNewFile();
} catch(Exception e){}
// force remove File.txt
command.add("rm");
command.add("-f");
command.add("File.txt");
// rename NewFile.txt to File.txt
command.add("mv");
command.add("NewFile.txt");
command.add("File.txt");
final ProcessBuilder builder = new ProcessBuilder(command);
try {
builder.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The issue is that you are running a single command, namely
rm -f File.txt mv NewFile.txt File.txt
This unconditionally deletes files named File.txt, mv and NewFile.txt.
You want to split this into two separate commands.
Better still, use File.delete() and File.renameTo(). This will not only give you more control, but will also make your code more portable.
ProcessBuilder.start creates one process. You need to call it twice because you have two commands: first with the first command and then with the second.
Incidentally, why are you not using Java's file API for this? It is a lot easier to do this from Java than to deal with the complexity of launching a separate process, not to mention more efficient.
This question already has an answer here:
Android NDK - Library not found CANNOT LINK EXECUTABLE - how to set LD_LIBRARY_PATH?
(1 answer)
Closed 9 years ago.
edit: I'm aware of the possible duplicate, but the answer it's not directly applicable. I'm using ProcessBuilder and not Runtime.getRuntime().exec:
public int execProcess(List<String> cmds, ShellUtils.ShellCallback sc) {
StringBuilder cmdlog = new StringBuilder();
for (String cmd : cmds) {
cmdlog.append(' ');
}
Utils.logger("v", cmdlog.toString(), DEBUG_TAG);
ProcessBuilder pb = new ProcessBuilder();
pb.directory(mBinFileDir);
pb.command(cmds);
Process process = null;
int exitVal = 1; // Default error
try {
process = pb.start();
StreamGobbler errorGobbler = new
StreamGobbler(process.getErrorStream(), "ERROR", sc);
StreamGobbler outputGobbler = new
StreamGobbler(process.getInputStream(), "OUTPUT", sc);
errorGobbler.start();
outputGobbler.start();
exitVal = process.waitFor();
sc.processComplete(exitVal);
} catch (Exception e) {
Log.e(DEBUG_TAG, "Error executing ffmpeg command!", e);
} finally {
if (process != null) {
Utils.logger("w", "destroyng process", DEBUG_TAG);
process.destroy();
}
}
return exitVal;
}
I have two versions on FFmpeg compiled for android: with and without liblame enabled.
When I load in /data/data/<<my-package-name>>/app_bin/ the FFmpeg binary compiled with NO lame support, it extracts audio from video without an issue. But when I use the one with lame support enabled, I get the error below into the log.
Required libs, also compiled for android, are correctly loaded when shipped into the libs project folder with System.loadLibrary("lame").
I was wondering if there is something else to do in order to properly make the FFmpeg binary find the libs.
Those are the same libs given to the NDK to build the FFmpeg binary.
D/dalvikvm(13741): Trying to load lib /data/app-lib/<<my-package-name>>/liblame.so 0x40ffed08
D/dalvikvm(13741): Added shared lib /data/app-lib/<<my-package-name>>/liblame.so 0x40ffed08
D/dalvikvm(13741): No JNI_OnLoad found in /data/app-lib/<<my-package-name>>/liblame.so 0x40ffed08, skipping init
D/FfmpegController(13741): Trying to chmod '/data/data/<<my-package-name>>/app_bin/ffmpeg' to: 755
V/FfmpegController(13741): /data/data/<<my-package-name>>/app_bin/ffmpeg -y -i /storage/sdcard0/Download/video.webm -vn -acodec copy /storage/sdcard0/Download/audio.ogg
>>>>>> ---------- <<<<<<
D/DownloadsService(13741): soinfo_link_image(linker.cpp:1673): could not load library "liblame.so" needed by "/data/data/<<my-package-name>>/app_bin/ffmpeg"; caused by load_library(linker.cpp:771): library "liblame.so" not foundCANNOT LINK EXECUTABLE
>>>>>> ---------- <<<<<<
I/DownloadsService(13741): FFmpeg process exit value: 255
I'm not attaching code because it's fairly straightforward:
download the FFmpeg binary (it's not shipped with the app);
copy the binary from the download folder to /data/data/<<my-package-name>>/app_bin/;
chmod 755;
execute from there and read the output.
Please comment if something else is required.
It's funny I'm finding all my answers lately... anyway, since it can be useful to others out there, if you want to:
add the path of a shared library like liblame.so
loaded with System.loadLibrary("lame")from libs folder
and you want to use ProcessBuilder
do:
1)
ProcessBuilder pb = new ProcessBuilder("liblame.so");
Map<String, String> envMap = pb.environment();
envMap.put("LD_LIBRARY_PATH", "/data/app-lib/<<my-pkg-name>>/");
or, better, to avoid handling the "-1" or "-2" suffix after the package name (that changes):
2)
ProcessBuilder pb = new ProcessBuilder();
Map<String, String> envMap = pb.environment();
envMap.put("LD_LIBRARY_PATH", "/data/data/<<my-pkg-name>>/lib");
and to not hard-code /data/data/<<my-pkg-name>>/lib
use: Context.getApplicationInfo().nativeLibraryDir
With this solution 2) I found also that System.loadLibrary("lame") it's not needed.
I have a desktop application using Swing library. Application is running a batch file. So I created a lib folder in main project directory and put batch file in it. To run this, I am showing lib\a.exe to run this. It is working on my laptop. I exported .jar and put lib folder next to it. It is working on my laptop, but not working on some other laptops. How to fix this?
Error message is: Windows cannot found lib\a.exe.
String command = "cmd /c start lib\\a.exe";
try {
Runtime.getRuntime().exec(command);
increaseProgressBarValue();
} catch (IOException e) {
e.printStackTrace();
}
You need two things:
find the directory of the jar file of your application
call a.exe with the correct working directory
You can get the location of the jar with the getJar method below:
private static File getJar(Class clazz) throws MalformedURLException {
String name = clazz.getName().replace('.','/') + ".class";
ClassLoader cl = Thread.currentThread().getContextClassLoader();
URL url = cl.getResource(name);
System.out.println(url);
if (!"jar".equals(url.getProtocol())) {
throw new MalformedURLException("Expected a jar: URL " + url);
}
String file = url.getPath();
int pos = file.lastIndexOf('!');
if (pos < 0) {
throw new MalformedURLException("Expected ! " + file);
}
url = new URL(file.substring(0, pos));
if (!"file".equals(url.getProtocol())) {
throw new MalformedURLException("Expected a file: URL " + url);
}
String path = url.getPath();
if (path.matches("/[A-Za-z]:/")) { // Windoze drive letter
path = path.substring(1);
}
return new File(path);
}
To call lib\a.exe, you can do something like this:
File jar = getJar(MyClass.class); // MyClass can be any class in you jar file
File dir = jar.getParentFile();
ProcessBuilder builder = new ProcessBuilder();
builder.command("lib\\a.exe");
builder.directory(dir);
...
Process p = builder.start();
...
Maybe you have to try if this folder lib exists and if it doesn't than create it with
file.mkdir();
This is a just a checking. But your filepath must be like this ../lib/a.exe.