I had written several simple java applications named as A.jar, B.jar.
Now i want to write a GUI java program so that user can press button A to execute A.jar and button B to execute B.jar.
Also i want to output the run-time process detail in my GUI program.
Any suggestion?
If I understand correctly it appears you want to run the jars in a separate process from inside your java GUI application.
To do this you can use:
// Run a java app in a separate system process
Process proc = Runtime.getRuntime().exec("java -jar A.jar");
// Then retreive the process output
InputStream in = proc.getInputStream();
InputStream err = proc.getErrorStream();
Its always good practice to buffer the output of the process.
.jar isn't executable. Instantiate classes or make call to any static method.
EDIT:
Add Main-Class entry while creating a JAR.
>p.mf (content of p.mf)
Main-Class: pk.Test
>Test.java
package pk;
public class Test{
public static void main(String []args){
System.out.println("Hello from Test");
}
}
Use Process class and it's methods,
public class Exec
{
public static void main(String []args) throws Exception
{
Process ps=Runtime.getRuntime().exec(new String[]{"java","-jar","A.jar"});
ps.waitFor();
java.io.InputStream is=ps.getInputStream();
byte b[]=new byte[is.available()];
is.read(b,0,b.length);
System.out.println(new String(b));
}
}
Hope this helps:
public class JarExecutor {
private BufferedReader error;
private BufferedReader op;
private int exitVal;
public void executeJar(String jarFilePath, List<String> args) throws JarExecutorException {
// Create run arguments for the
final List<String> actualArgs = new ArrayList<String>();
actualArgs.add(0, "java");
actualArgs.add(1, "-jar");
actualArgs.add(2, jarFilePath);
actualArgs.addAll(args);
try {
final Runtime re = Runtime.getRuntime();
//final Process command = re.exec(cmdString, args.toArray(new String[0]));
final Process command = re.exec(actualArgs.toArray(new String[0]));
this.error = new BufferedReader(new InputStreamReader(command.getErrorStream()));
this.op = new BufferedReader(new InputStreamReader(command.getInputStream()));
// Wait for the application to Finish
command.waitFor();
this.exitVal = command.exitValue();
if (this.exitVal != 0) {
throw new IOException("Failed to execure jar, " + this.getExecutionLog());
}
} catch (final IOException | InterruptedException e) {
throw new JarExecutorException(e);
}
}
public String getExecutionLog() {
String error = "";
String line;
try {
while((line = this.error.readLine()) != null) {
error = error + "\n" + line;
}
} catch (final IOException e) {
}
String output = "";
try {
while((line = this.op.readLine()) != null) {
output = output + "\n" + line;
}
} catch (final IOException e) {
}
try {
this.error.close();
this.op.close();
} catch (final IOException e) {
}
return "exitVal: " + this.exitVal + ", error: " + error + ", output: " + output;
}
}
The following works by starting the jar with a batch file, in case the program runs as a stand alone:
public static void startExtJarProgram(){
String extJar = Paths.get("C:\\absolute\\path\\to\\batchfile.bat").toString();
ProcessBuilder processBuilder = new ProcessBuilder(extJar);
processBuilder.redirectError(new File(Paths.get("C:\\path\\to\\JavaProcessOutput\\extJar_out_put.txt").toString()));
processBuilder.redirectInput();
try {
final Process process = processBuilder.start();
try {
final int exitStatus = process.waitFor();
if(exitStatus==0){
System.out.println("External Jar Started Successfully.");
System.exit(0); //or whatever suits
}else{
System.out.println("There was an error starting external Jar. Perhaps path issues. Use exit code "+exitStatus+" for details.");
System.out.println("Check also C:\\path\\to\\JavaProcessOutput\\extJar_out_put.txt file for additional details.");
System.exit(1);//whatever
}
} catch (InterruptedException ex) {
System.out.println("InterruptedException: "+ex.getMessage());
}
} catch (IOException ex) {
System.out.println("IOException. Faild to start process. Reason: "+ex.getMessage());
}
System.out.println("Process Terminated.");
System.exit(0);
}
In the batchfile.bat then we can say:
#echo off
start /min C:\path\to\jarprogram.jar
If the jar's in your classpath, and you know its Main class, you can just invoke the main class. Using DITA-OT as an example:
import org.dita.dost.invoker.CommandLineInvoker;
....
CommandLineInvoker.main('-f', 'html5', '-i', 'samples/sequence.ditamap', '-o', 'test')
Note this will make the subordinate jar share memory space and a classpath with your jar, with all the potential for interference that can cause. If you don't want that stuff polluted, you have other options, as mentioned above - namely:
create a new ClassLoader with the jar in it. This is more safe; you can at least isolate the new jar's knowledge to a core classloader if you architect things with the knowledge that you'll be making use of alien jars. It's what we do in my shop for our plugins system; the main application is a tiny shell with a ClassLoader factory, a copy of the API, and knowledge that the real application is the first plugin for which it should build a ClassLoader. Plugins are a pair of jars - interface and implementation - that are zipped up together. The ClassLoaders all share all the interfaces, while each ClassLoader only has knowledge of its own implementation. The stack's a little complex, but it passes all tests and works beautifully.
use Runtime.getRuntime.exec(...) (which wholly isolates the jar, but has the normal "find the application", "escape your strings right", "platform-specific WTF", and "OMG System Threads" pitfalls of running system commands.
First we cerate a class FirstFileOutput having a main method that outputs a line to stable output and a line to stable error. With all first procedure, we'll again create a class RuntimeExecCheck that will run our FirstFileOutput class in starting for process, and after that RuntimeExecCheck class will read the stable output and the stable error from FirstFileOutput and output comes.
package check;
public class FirstFileOutput{
public static void main(String[] args) {
System.out.println("This is output to stable output");
System.err.println("This is output to stable error");
}
}
package check;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class RuntimeExecCheck {
public static void main(String[] args) {
try {
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec("java -classpath C:\\projects\\workspace\\check\\bin check.FirstFileOutput");
InputStream inputStream = process.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream);
InputStream errorStream = process.getErrorStream();
InputStreamReader esr = new InputStreamReader(errorStream);
int n1;
char[] c1 = new char[1024];
StringBuffer stableOutput = new StringBuffer();
while ((n1 = isr.read(c1)) > 0) {
stableOutput.append(c1, 0, n1);
}
System.out.println("Stable Output: " + stableOutput.toString());
int n2;
char[] c2 = new char[1024];
StringBuffer stableError = new StringBuffer();
while ((n2 = esr.read(c2)) > 0) {
stableError.append(c2, 0, n2);
}
System.out.println("Stable Error: " + stableError.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
If you are java 1.6 then the following can also be done:
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class CompilerExample {
public static void main(String[] args) {
String fileToCompile = "/Users/rupas/VolatileExample.java";
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int compilationResult = compiler.run(null, null, null, fileToCompile);
if (compilationResult == 0) {
System.out.println("Compilation is successful");
} else {
System.out.println("Compilation Failed");
}
}
}
Related
We are facing an issue where the below code is not able to open Microsoft Edge by running the command.
import java.io.IOException;
import java.io.InputStream;
public class ProcessTest {
private static final String NO_FRAME_MERGING_CMD_EDGE = "cmd.exe /c start microsoft-edge:";
private static final Object DOUBLE_QUOTE = "\"";
public static void main(String[] args) throws IOException {
Runtime rt = Runtime.getRuntime();
String url = "http://google.com";
url = new StringBuilder().append(DOUBLE_QUOTE).append(url).append(DOUBLE_QUOTE).toString();
System.out.println(NO_FRAME_MERGING_CMD_EDGE+ url);
Process process = rt.exec(NO_FRAME_MERGING_CMD_EDGE+ url);
printErrorlog(process);
}
public static void printErrorlog(Process process) {
try {
if (process != null && isProcessTerminated(process)) {
StringBuffer string_error = new StringBuffer();
InputStream errorStream = process.getErrorStream();
if (errorStream != null) {
int c = 0;
while ((c = errorStream.read()) != -1) {
string_error.append((char) c);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static boolean isProcessTerminated (Process process) {
try {
process.exitValue();
} catch (IllegalThreadStateException itse) {
itse.printStackTrace();
return false;
}
return true;
}
}
In the logs we see
cmd.exe /c start microsoft-edge:"http://google.com"
java.lang.IllegalThreadStateException: process has not exited
at java.lang.ProcessImpl.exitValue(Native Method)
at ProcessTest1.isProcessTerminated(ProcessTest1.java:40)
at ProcessTest1.printErrorlog(ProcessTest1.java:22)
at ProcessTest1.main(ProcessTest1.java:16)
But the browser does not open.
When we run the command below in a bash file or on the command line, the windows is able to opening Edge. So I am not able to understand why it is not opening by Java.
cmd.exe /c start microsoft-edge:"http://google.com"
We are using jdk 6 to run the programm.
As described in the question, I have encountered a weird throttling of write speed (even paused entirely) when using java.io.BufferedWriter to write.
My program is trying to read from a bunch of .csv files, and repack them to another bunch of .csv files grouped by the first column.
For example, if I have a line in the .csv file Tom, 86, 87, 88, this line will be written to the .csv file named Tom.csv.
I uses a HashMap<String, BufferedWriter> to cache the writers so that the program only have to open / close the writers once.
(I purposely split the file listing and the process logic for debugging)
The code:
package dev.repackcsv;
import java.io.*;
import java.nio.file.*;
import java.util.*;
public class Main {
private static final Path USER_DIR;
private static final Path PROP_FILE;
private static final Properties PROPERTIES;
private static final Path SCAN_DIR;
private static final Path OUTPUT_DIR;
private static final List<Path> SCANNED_FILE_LIST;
private static final Map<String, BufferedWriter> OUTPUT_FILE_MAP;
private static void loadProperties() {
try (InputStream propFileInputStream = Files.newInputStream(PROP_FILE)) {
PROPERTIES.load(propFileInputStream);
} catch (IOException e) {
System.err.println("[Error] Failed to load properties from \"application.properties\"");
System.exit(1);
}
}
private static String getProperty(String propertyName) {
String property = PROPERTIES.getProperty(propertyName);
if (property == null) {
System.err.println("[Error] Undefined property: " + propertyName);
System.exit(1);
}
return property;
}
static {
USER_DIR = Paths.get(System.getProperty("user.dir"));
PROP_FILE = USER_DIR.resolve("application.properties");
if (!Files.exists(PROP_FILE)) {
System.err.println("[Error] \"application.properties\" file does not exist.");
System.exit(1);
}
PROPERTIES = new Properties();
loadProperties();
SCAN_DIR = Paths.get(getProperty("scan.dir")).toAbsolutePath();
if (!Files.exists(SCAN_DIR)) {
System.err.println("[Error] Scan directory does not exist");
System.exit(1);
}
OUTPUT_DIR = Paths.get(getProperty("output.dir")).toAbsolutePath();
if (!Files.exists(OUTPUT_DIR)) {
System.err.println("[Error] Output directory does not exist");
System.exit(1);
}
SCANNED_FILE_LIST = new LinkedList<>();
OUTPUT_FILE_MAP = new HashMap<>();
}
private static void loadScannedFileList()
throws IOException {
try (DirectoryStream<Path> ds = Files.newDirectoryStream(SCAN_DIR)) {
for (Path path : ds) {
SCANNED_FILE_LIST.add(path.toAbsolutePath());
}
}
}
private static BufferedWriter getOutputFileBufferedWriter(String key, String headLine) throws IOException {
if (OUTPUT_FILE_MAP.containsKey(key)) {
return OUTPUT_FILE_MAP.get(key);
} else {
Path outputFile = OUTPUT_DIR.resolve(key + ".csv");
boolean isNewFile = false;
if (!Files.exists(outputFile)) {
Files.createFile(outputFile);
isNewFile = true;
}
BufferedWriter bw = Files.newBufferedWriter(outputFile);
if (isNewFile) {
bw.write(headLine);
bw.newLine();
bw.flush();
}
OUTPUT_FILE_MAP.put(key, bw);
return bw;
}
}
private static void processScannedCSV(Path csvFile)
throws IOException {
System.out.printf("[Info] Current file \"%s\"%n", csvFile);
long fileSize = Files.size(csvFile);
try (BufferedReader br = new BufferedReader(new InputStreamReader(Files.newInputStream(csvFile)))) {
String headLine = br.readLine();
if (headLine == null) { return; }
String dataLine;
long readByteSize = 0;
while ((dataLine = br.readLine()) != null) {
int firstCommaIndex = dataLine.indexOf(',');
if (firstCommaIndex == -1) { continue; }
BufferedWriter bw = getOutputFileBufferedWriter(dataLine.substring(0, firstCommaIndex), headLine);
bw.write(dataLine);
bw.newLine();
readByteSize += dataLine.getBytes().length;
System.out.print("\r[Progress] " + readByteSize + '/' + fileSize);
}
}
System.out.print("\r");
}
private static void processScannedFiles()
throws IOException {
for (Path file : SCANNED_FILE_LIST) {
if (!Files.exists(file)) {
System.out.printf("[WARN] Scanned file \"%s\" does not exist, skipping...%n", file);
continue;
}
if (!file.toString().endsWith(".csv")) { continue; }
processScannedCSV(file);
}
}
public static void main(String[] args)
throws IOException {
loadScannedFileList();
processScannedFiles();
for (BufferedWriter bw : OUTPUT_FILE_MAP.values()) {
bw.flush();
bw.close();
}
}
}
The output (For this scenario the program is freezed during the line bw.write(dataLine);):
I uses Intellij-IDEA as the editor and executes the program using debug mode.
Connected to the target VM, address: '127.0.0.1:25111', transport: 'socket'
[Info] Current file "..\scan-dir\L2_options_20150102.csv"
[Progress] 8166463/109787564
It would be great if anyone knows the cause / has a solution for this :(
Thanks!
Having many files open can be a heavy load on the disk operating system, the number of file handles (limited!), and "moving the write head around" should one do things concurrently.
About the statics
The code shows experience (also concerning Java), maybe also from a language like C. Because the use of static is unusual. you could in main do a new Main().executeMyThings(); and drop static elsewhere.
Measures to take
Do not use text but binary data, not Writer/Reader, but OutputStream/InputStream. This prevent a Unicode conversion back and forth. Also you risk data loss, when a Windows UTF-8 file on Linux.
Use ArrayList rather LinkedList as for many items it is likely to behave better.
You might want to collect file paths instead of BufferedWriters. Every BufferedWriter is not only a OS resource, but maintains a buffer (memory). It might even be more performant, writing the head line, closing and reopening it in append mode. The headline could be written be with Files.writeString.
System.out is costly. A ConsoleLogger might be safer would be safer with concurrency,
but costs too.
readByteSize misses the line break, 2 for Windows files.
A BufferedWriter can be created with a larger/smaller buffer size.
for (Path path : ds) {
SCANNED_FILE_LIST.add(path.toAbsolutePath());
}
might be better as:
ds.forEach(path -> SCANNED_FILE_LIST.add(path.toAbsolutePath());
Today I meet a problem with "java" command.
I work in Intellij IDEA and think that I wrong classpath to "java" command.
Please, help me.
package ru.mch;
import ru.mch.RunTask;
public class Program {
public static void main(String[] args) {
String taskCode = "class UserProgram{ public static void main(String[] args) { int b = 3 + 1; System.out.println(b);}}";
String packageName = "package ru.mch; ";
String all = packageName + taskCode ;
RunTask runTask = new RunTask(all);
int result = runTask.run();
}
}
I want to get program code from String, create new java class, write code to the class and compile and run new java class.
package ru.mch;
import java.io.*;
public class RunTask {
private String answerFromPage;
private int programExitValue;
public RunTask(String answerFromPage) {
this.answerFromPage = answerFromPage;
this.programExitValue = 0;
}
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
private static int runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(/*command + */" stdout:", pro.getInputStream());
printLines(" stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exit value = " + pro.exitValue());
return pro.exitValue();
}
public int run(){
//String fileName = "src\\main\\java\\ru\\mch\\UserProgram.java";
String fileName = "src\\main\\java\\ru\\mch\\UserProgram.java";
File f = new File(fileName);
f.getParentFile().mkdirs();
try {
f.createNewFile();
} catch (IOException e) {
throw new IllegalArgumentException("File creating error");
}
try(FileWriter writer = new FileWriter(fileName, false))
{
writer.write(this.answerFromPage);
writer.flush();
}
catch(IOException ex){
System.out.println(ex.getMessage());
}
try {
System.out.println(runProcess("javac -sourcepath src src\\main\\java\\ru\\mch\\UserProgram.java"));
System.out.println("------------");
this.programExitValue = runProcess("java src\\main\\java\\ru.mch.UserProgram");
} catch (Exception e) {
e.printStackTrace();
}
return this.programExitValue;
}
}
This is IDEA log :
javac src\main\java\ru\mch\UserProgram.java exit value = 0
0
------------
Error: Could not find or load main class src\main\java\ru.mch.UserProgram
java src\main\java\ru.mch.UserProgram exit value = 1
New class was created and .class too.
I try to write full classpath, try to write '\' instead of '.' in package name, but all is wrong.
Sorry for my bad English.
Use the following command:
java -cp src\main\java ru.mch.UserProgram
I need some help please ! I'm trying to generate classes from xsd in java ( with eclipse ) and I don't know how to do it, I searched in many tutorials but they all speaks about creating firstly the class then using the xsd.
I want to create automatically the classes from a xsd using Jaxb.
do you have any suggestions or tutorials that can help me please ?
Use the xjc command that comes with the JDK:
Compiles an XML schema file into fully annotated Java classes.
I managed to do it !
I will show my solution, in case someone have the same problem.
i used ProcessBuilder in a method in order to execute the command from java :
public class FromXmlToJava implements Runnable {
private final InputStream inputStream;
FromXmlToJava ( InputStream inputStream)
{
this.inputStream = inputStream;
}
private BufferedReader getBufferedReader(InputStream is)
{
return new BufferedReader(new InputStreamReader(is));
}
public void run() {
BufferedReader br = getBufferedReader(inputStream);
String ligne = "";
try
{
while ( (ligne = br.readLine() )!= null)
{
System.out.println(ligne);
}
} catch (IOException e)
{
e.printStackTrace();
}
}
public static class Main {
// chemin de l'emplacement des classes generées
public static final String CHEMIN = "C:\\Users\\****";
public static void main(String[] args) {
try {
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/C",
"C:\\Users\\***\\xjc.bat ***.xsd");
// modifier le repertoire d'execution de la commande
pb.directory(new File(CHEMIN));
/* Map env = pb.environment();
for (Entry entry : env.entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
env.put("MonArg", "Valeur");
*/
Process p = pb.start();
FromXmlToJava fluxSortie = new FromXmlToJava(p.getInputStream());
FromXmlToJava fluxErreur = new FromXmlToJava(p.getErrorStream());
new Thread(fluxSortie).start();
new Thread(fluxErreur).start();
p.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Is there a way to tell whether a file is opened by another application in PHP of Java?
Command fuser -v filename will tell you everything you need to know:
$ fuser -v test.php
USER PID ACCESS COMMAND
test.php: guest 17983 F.... cat
I'd say No. Please read these threads.
How to check if a file is already open by another process in C?
Java: Check if file is already open
How to check if a file has been opened by another application in C++
On windows you could download handle which is a command line tool to identify which windows file handles are owned by which processes.
Output looks like this:
Handle v3.46
Copyright (C) 1997-2011 Mark Russinovich
Sysinternals - www.sysinternals.com
------------------------------------------------------------------------------
System pid: 4 NT AUTHORITY\SYSTEM
84: File (R--) C:\System Volume Information\_restore{5D536487-92AI-5I25-9237-28AHSOU23728}\RP425\change.log
B4: File (RWD) C:\Documents and Settings\All Users\Application Data\avg9\Log\avgldr.log
728: File (-W-) C:\pagefile.sys
7A4: File (---) C:\WINDOWS\system32\config\SECURITY
(etc...)
Here an example application which uses handle.exe to determine if there is a handle on a file or directory (Windows only):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Application which determines which processes have a handle on a file or
* directory. Pass the file or directory to check as the first application
* parameter.
*
* This application uses handle.exe, which can be downloaded here:
* http://technet.microsoft.com/en-us/sysinternals/bb896655
*
* Copy handle.exe to C:/Program Files/handle/
*
* For the Runtime.exec() code I looked at:
* http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=2
*
* #author Adriaan
*/
public class Handle {
private static final String HANDLE_PATH = "C:/Program Files/handle/handle.exe";
private static final String DEFAULT_TARGET = "C:\\WINDOWS";
public static void main(String[] args) throws IOException,
InterruptedException {
checkOS();
String fileName = getFileName(args);
Process proc = executeCommand(fileName);
readResults(fileName, proc);
checkTermination(proc);
}
private static void checkOS() {
String osName = System.getProperty("os.name");
if (!osName.contains("Windows")) {
throw new IllegalStateException("Can only run under Windows");
}
}
private static String getFileName(String[] args) {
String fileName;
if (args != null && args.length > 0) {
fileName = args[0];
} else {
fileName = DEFAULT_TARGET;
}
return fileName;
}
private static Process executeCommand(String fileName) throws IOException {
String[] cmd = new String[] { HANDLE_PATH, fileName };
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
return proc;
}
private static void readResults(final String fileName, final Process proc) {
Thread errorHandler = new Thread() {
public void run() {
try {
BufferedReader br = new BufferedReader(
new InputStreamReader(proc.getErrorStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.err.println(line);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
};
Thread outputHandler = new Thread() {
public void run() {
try {
BufferedReader br = new BufferedReader(
new InputStreamReader(proc.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
if (line.endsWith(fileName)) {
System.out.println(line);
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
};
errorHandler.start();
outputHandler.start();
}
private static void checkTermination(final Process proc)
throws InterruptedException {
int exitVal = proc.waitFor();
if (exitVal != 0) {
throw new IllegalStateException("Exitvalue " + exitVal);
}
}
}
You probably want to use file locking.
http://tuxradar.com/practicalphp/8/11/0
Edit: This is presuming you mean programatically with PHP or Java.
On linux you can scan through all the /proc/{pid}/fd/nnn file descriptors to see if the file in question is already open.
Using files to share data between running programs is generally a bad idea and error prone.