Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
I tried this:
Process rt = Runtime.getRuntime().exec("cmd /c start C:\\Users\\spacitron\\batchfiles\\mybatch.bat");
But all that happens is the command prompt pops up on the screen.
As to your particular problem, I would suspect the command line arguments are getting mangled. This is actually a faily common problem with Runtime#exec.
Instead, I'd recommend that you use ProcessBuilder instead. It's much more forgiving with the command line parameters and deals with things like spaces much better.
For exammple...
MyBatch.bat
#echo off
echo This is a test message
RunBatchCommand
import java.io.IOException;
import java.io.InputStream;
public class RunBatchCommand {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("cmd", "start", "/c", "MyBatch.bat");
pb.redirectError();
try {
Process p = pb.start();
InputStreamConsumer isc = new InputStreamConsumer(p.getInputStream());
new Thread(isc).start();
int exitCode = p.waitFor();
System.out.println("Command exited with " + exitCode);
if (isc.getCause() == null) {
System.out.println(isc.getOutput());
} else {
isc.getCause().printStackTrace();
}
} catch (IOException | InterruptedException exp) {
exp.printStackTrace();
}
}
public static class InputStreamConsumer implements Runnable {
private InputStream is;
private StringBuilder sb;
private IOException cause;
public InputStreamConsumer(InputStream is) {
this.is = is;
sb = new StringBuilder(128);
}
#Override
public void run() {
try {
int in = -1;
while ((in = is.read()) != -1) {
sb.append((char) in);
System.out.print((char) in);
}
} catch (IOException exp) {
cause = exp;
exp.printStackTrace();
}
}
protected String getOutput() {
return sb.toString();
}
public IOException getCause() {
return cause;
}
}
}
Which generates...
This is a test message
Command exited with 0
This is a test message
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm learning Java and I've a relatively simple Java program that fetches data from an API endpoint that looks like this:
public class Main {
public static String getJSON(String u) {
if (u == null) throw new IllegalArgumentException("URL is null.");
try {
URL url = new URL(u);
URLConnection site = url.openConnection();
InputStream is = site.getInputStream();
Scanner scanner = new Scanner(
new BufferedInputStream(is),
"UTF-8");
String resp = "";
while (scanner.hasNextLine()) {
resp = resp + scanner.nextLine();
}
return resp;
} catch (Exception e) {
System.out.println(e);
return null;
}
}
public static void main(String[] args) {
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() ->
getJSON("https://jsonplaceholder.typicode.com/posts/1")
);
cf.thenAcceptAsync(System.out::println);
// System.out.println(cf.join()); <=== Commenting out this line
}
}
I expect the code above to print out the raw JSON, but instead, it does nothing. However, if I include the line that has been commented out above, the code works, but it prints out the raw JSON twice.
My guess is that the program terminates before the thenAcceptAsync has a chance to complete, which is not the case when the blocking .join() function is included. Is my guess right, and if so, how can I solve this issue?
Your main thread is not waiting for the completion of the service call. You should call join on the CompletableFuture to wait for its execution to finish:
cf.thenAcceptAsync(System.out::println).join();
You can check the behavior using the following modified version of your code (just adding a shutdown hook to print text when VM is exiting):
Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("Shutting down")));
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
System.out.println("running...");
String result = getJSON("https://jsonplaceholder.typicode.com/posts/1");
System.out.println("Completed service call");
return result;
});
cf.thenAcceptAsync(System.out::println).join();
When you run the above code, the following is output:
running...
Completed service call
{ "result json here"}
Shutting down
However, without .join(), the following output appears immediately:
e
running...
Shutting down
In short, thenAcceptAsync(System.out::println) returns immediately and the main thread completes, in this case before the HTTP call completes. If you had work to do after that, it would like like:
cf = cf.thenAcceptAsync(System.out::println);
doSomethingElse();
doYetAnotherThing();
cf.join()
join should eventually be called, either to prevent premature termination of the VM, or to wait for the result to become ready when it's necessary.
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
public class Main {
public static String getJSON(String u) {
if (u == null) throw new IllegalArgumentException("URL is null.");
try {
URL url = new URL(u);
URLConnection site = url.openConnection();
InputStream is = site.getInputStream();
Scanner scanner = new Scanner(
new BufferedInputStream(is),
"UTF-8");
String resp = "";
while (scanner.hasNextLine()) {
resp = resp + scanner.nextLine();
}
return resp;
} catch (Exception e) {
System.out.println(e);
return null;
}
}
public static void main(String[] args) {
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() ->
getJSON("https://jsonplaceholder.typicode.com/posts/1")
);
//cf.thenAcceptAsync(System.out::println);
System.out.println(cf.join());
}
}
just comment and open below line it will print just one line
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm trying to create a program in Java that writes a line of characters, but only certain characters which in this case is "a" or "b". How would I do this?
Right now it writes "ababbbabbaab", but if it writes "oohmtkgfgk" for example, it needs to throw an exception.
public class Writer {
public void writer() {
try {
FileWriter writer = new FileWriter("FSA.txt", true);
writer.write("ababbbabbaab");
writer.close();
} catch (IOException e) {
System.out.println("Error");
}
}
}
Use regex ^[ab]*$ to validate the string instead of splitting and iterating. Saves lines of code. This regex validates whether the text contains only characters inside [], in your case a&b.
public static void main(String[] args) {
try {
FileWriter writer = new FileWriter("FSA.txt", true);
String str = "ababbbabbaabc";
validate(str);
writer.write(str);
writer.close();
} catch (IOException e) {
System.out.println("Error");
}
}
private static void validate(String string) throws IOException {
if(!string.matches("^[ab]*$"))
throw new IOException();
}
Create a method and verify if a or b are present in the string to be stored
Example
// If the 'a' or 'b'are present in string, it returns the index(>=0).
//If not, it returns -1. So, a non-negative return value means that 'a' is
// present in the string.
private boolean checkText(String string) {
final int aIndex = string.indexOf('a');
final int bIndex = string.indexOf('b');
if (aIndex!=-1 && bIndex!=-1) {
return true;
}
else {
return false;
}
}
Split the string and check that all letters are a or b, if not throw a exception.
public static void main(String[] args) {
try {
FileWriter writer = new FileWriter("FSA.txt", true);
String str = "ababbbabbaabc";
checkText(str);
writer.write(str);
writer.close();
} catch (IOException e) {
System.out.println("Error");
}
}
private static void checkText(String string) throws IOException {
for(String str: string.split("")) {
if(str.equals("")) continue;
if(!str.equals("a") && !str.equals("b")) throw new IOException();
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I,m making a library that can restart any class that calls it's method. It just needs the class to build the command off of. Here's what I have so far:
public static void restart(Class a) {
final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
try {
File currentJar = new File(a.class.getProtectionDomain().getCodeSource().getLocation().toURI());
/* is it a jar file? */
if(!currentJar.getName().endsWith(".jar")) {
return;
}
/* Build command: java -jar application.jar */
final ArrayList<String> command = new ArrayList<>(5);
command.add(javaBin);
command.add("-jar");
command.add(currentJar.getPath());
final ProcessBuilder builder = new ProcessBuilder(command);
builder.start();
System.exit(0);
} catch (URISyntaxException | IOException ex) {
Logger.getLogger(a.class.getName()).log(Level.SEVERE, null, ex);
}
}
The problem is that variable 'a' is not being recognized as a parameter. Can anybody help?
See below code snippet
public class Test {
public static void main(String[] args) {
Test test = new Test();
check(test.getClass());
}
public static void check(Class<?> a){
System.out.println(a);
}
}
I have been implementing a program to compile and run other applications. I was wondering if there is a way to terminate a program when my application discovers that there is an issue e.g. infinite loop. I tried to using process.Destroy() but it kills the CMD not that actual program that has infinite loop...
Your help is really appreciated.
Here is a part of my code:
synchronized (pro) {
pro.wait(30000);
}
try{
pro.exitValue();
}catch (IllegalThreadStateException ex)
{
pro.destroy();
timeLimitExceededflag = true;
System.out.println("NOT FINISHED123");
System.exit(0);
}
}
Basically I am making my application to invoke the cmd using a processBuilder. This code terminates the CMD but if it runs a program that has an infinite loop that application will be still running which affects my servers performance.
I'd suggest to use the following solution:
start your program with a title specified
get PID of the process using "tasklist" command. A CSV parser required. There are tons of available I believe, like org.apache.commons.csv.CSVParser etc :)
kill the process by "taskkill" command using PID.
Here is some part of code which may be useful:
public static final String NL = System.getProperty("line.separator", "\n");
public <T extends Appendable> int command(String... cmd) throws Exception {
return command(null, cmd);
}
public <T extends Appendable> int command(T out, String... cmd) throws Exception {
try {
final ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
final Process proc = pb.start();
final BufferedReader rd = new BufferedReader(new InputStreamReader(proc.getInputStream()));
for (;;) {
final String line = rd.readLine();
if (line == null) {
break;
}
if (out != null) {
out.append(line);
out.append(NL);
}
}
return proc.waitFor();
} catch (InterruptedException e) {
throw new IOException(e);
}
}
public void startProcessWithTitle(String pathToExe, String title) throws Exception {
command("cmd.exe", "/C", "start", '"' + pathToExe + '"', '"' + title + '"', ..cmd.params..);
}
public int findProcessByTitle(String title) throws Exception {
final StringBuilder list = new StringBuilder();
if (command(list, "tasklist", "/V", "/FO", "csv") != 0) {
throw new RuntimeException("Cannot get tasklist. " + list.toString());
}
final CSVReader csv = new CSVReader(new StringReader(list.toString()), ',', true, "WindowsOS.findProcessByTitle");
csv.readHeaders(true); // headers
int pidIndex = csv.getHeaderIndex("PID");
int titleIndex = csv.getHeaderIndex("Window Title");
while (csv.nextLine()) {
final String ttl = csv.getString(titleIndex, true);
if (ttl.contains(title)) {
return csv.getInt(pidIndex);
}
}
Utils.close(csv);
return -1;
}
public boolean killProcess(int pid) throws Exception {
return command("taskkill", "/T", "/F", "/PID", Integer.toString(pid)) == 0;
}
How do I know if a software is done writing a file if I am executing that software from java?For example, I am executing geniatagger.exe with an input file RawText that will produce an output file TAGGEDTEXT.txt. When geniatagger.exe is finished writing the TAGGEDTEXT.txt file, I can do some other staffs with this file. The problem is- how can I know that geniatagger is finished writing the text file?
try{
Runtime rt = Runtime.getRuntime();
Process p = rt.exec("geniatagger.exe -i "+ RawText+ " -o TAGGEDTEXT.txt");
}
You can't, or at least not reliably.
In this particular case your best bet is to watch the Process complete.
You get the process' return code as a bonus, this could tell you if an error occurred.
If you are actually talking about this GENIA tagger, below is a practical example which demonstrates various topics (see explanation about numbered comments beneath the code). The code was tested with v1.0 for Linux and demonstrates how to safely run a process which expects both input and output stream piping to work correctly.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.concurrent.Callable;
import org.apache.commons.io.IOUtils;
public class GeniaTagger {
/**
* #param args
*/
public static void main(String[] args) {
tagFile(new File("inputText.txt"), new File("outputText.txt"));
}
public static void tagFile(File input, File output) {
FileInputStream ifs = null;
FileOutputStream ofs = null;
try {
ifs = new FileInputStream(input);
ofs = new FileOutputStream(output);
final FileInputStream ifsRef = ifs;
final FileOutputStream ofsRef = ofs;
// {1}
ProcessBuilder pb = new ProcessBuilder("geniatagger.exe");
final Process pr = pb.start();
// {2}
runInThread(new Callable<Void>() {
public Void call() throws Exception {
IOUtils.copy(ifsRef, pr.getOutputStream());
IOUtils.closeQuietly(pr.getOutputStream()); // {3}
return null;
}
});
runInThread(new Callable<Void>() {
public Void call() throws Exception {
IOUtils.copy(pr.getInputStream(), ofsRef); // {4}
return null;
}
});
runInThread(new Callable<Void>() {
public Void call() throws Exception {
IOUtils.copy(pr.getErrorStream(), System.err);
return null;
}
});
// {5}
pr.waitFor();
// output file is written at this point.
} catch (Exception e) {
e.printStackTrace();
} finally {
// {6}
IOUtils.closeQuietly(ifs);
IOUtils.closeQuietly(ofs);
}
}
public static void runInThread(final Callable<?> c) {
new Thread() {
public void run() {
try {
c.call();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}.start();
}
}
Use a ProcessBuilder to start your process, it has a better interface than plain-old Runtime.getRuntime().exec(...).
Set up stream piping in different threads, otherwhise the waitFor() call in ({5}) might never complete.
Note that I piped a FileInputStream to the process. According to the afore-mentioned GENIA page, this command expects actual input instead of a -i parameter. The OutputStream which connects to the process must be closed, otherwhise the program will keep running!
Copy the result of the process to a FileOutputStream, the result file your are waiting for.
Let the main thread wait until the process completes.
Clean up all streams.
If the program exits after generating the output file then you can call Process.waitFor() to let it run to completion then you can process the file. Note that you will likely have to drain both the standard output and error streams (at least on Windows) for the process to finish.
[Edit]
Here is an example, untested and likely fraught with problems:
// ...
Process p = rt.exec("geniatagger.exe -i "+ RawText+ " -o TAGGEDTEXT.txt");
drain(p.getInputStream());
drain(p.getErrorStream());
int exitCode = p.waitFor();
// Now you should be able to process the output file.
}
private static void drain(InputStream in) throws IOException {
while (in.read() != -1);
}