Modify running Java program - java

I have launched my program that have two loop like this :
for(int i=0;i<100;i++)
String[] articles = getArticles(i);
for(int j=0;j<articles.length;j++)
process(articles[j]);
Can I modify the running program so it stop at i = 1? If how to do that?
The program will take days to finish and I want to stop but I must know where it was stoped so the next time I can resume it.

Unfortunately you won't be able to stop a running program at a predictable spot unless debugger is on.
Stop your program, change the code, and start it up again.

It is possible (lots of things are). But it can be very, very hard - unless you are skilled at looking at Java bytecode and know your OS internals, I would not try.
Assuming you are running under linux, you can suspend and restart processes via kill -STOP <pid> and kill -CONT <pid>. You can also take a stack-trace of a running java process via jstack, and look at the running threads and decompiled code.

You could do this
static boolean stopLoop = false;
static int[] runLoop(int i, int j) {
for(;i<100;i++) {
if(stopLoop) return new int[i, j];
String[] articles = getArticles(i);
for(;j<articles.length;j++) {
process(articles[i]);
}
j = 0;
}
}

(You probably wanted to write process(articles[j]); in your inner loop.)
You can save last value of i and j into a file after processing of each article, then you can terminate your program anytime you want, and next time just read the values of i and j from your file and you don't have to process them again.
Or set 100 article processes per program run, or process for 20 minutes, there are so many possibilities.

There is no straightforward way to do this, but with a little extra legwork it can be done. One way is to output the latest successful iteration to persistent storage (like a file), then read the file if it exists to find out where to start. The example below shows one way to do it:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
public class Test
{
public static void main(String[] args)
{
int start;
// Try to get the last successful run
File file = new File(System.getenv("HOME"), ".myprog");
if(file.exists()) {
try(BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line = reader.readLine();
if(line == null) {
throw new NumberFormatException("Empty file, no number");
}
start = Integer.parseInt(line);
} catch(IOException | NumberFormatException ex) {
System.err.println("Unable to read progress: " + ex.getMessage());
System.err.println("Starting from the beginning");
start = 0;
}
} else {
start = 0;
}
// ... Your declarations go here
for(int i = start; i < 100; i++) {
String[] articles = getArticles(i);
for(int j=0;j<articles.length;j++) {
process(articles[i]);
}
// Record last successful run (this reopens the file every time)
try(PrintWriter writer = new PrintWriter(file)) {
writer.println(i);
} catch(IOException ex) {
System.err.println("Unable to record progress: " + ex.getMessage());
}
}
}
}
Note that I run on a Linux machine, so I called my file ~/.myprog. You may want to change that.

Related

JAVA one-line character progressbar works in NetBeans output window but not in CMD

I wanted to have CMD character-based one-line-updating progressbar that would work not only in CMD once project is compiled but also in NetBeans OutputWindow which basically everybody here was saying simply does not work (well at least those many post I read here before I made my own progressbar below).
The real problem why it does not work normally in NB output window is with System.out.print() together with using \r and by pure coincidence I noticed that when Thread.sleep() is set lower than some 250/300 it stops responding when testing in NB OutputWindow (it outputs as whole only once the code is stopped) but if I increase the value let's say to those 300 it starts work nicely. And as I need quite simple endlessly running DOS one-line progressbar just to let user know something is going on and that the app is not frozen while it is doing its stuff, it suits my needs pretty well.
So I made it like this:
package jthndemo;
import java.io.PrintStream;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
public class JthnDEMO {
public static void main(final String[] args) throws InterruptedException {
SwingUtilities.invokeLater(() -> {
PrintStream out = System.out;
int pause = 300;
int progressbarLength = 15;
boolean cond = true;
String txt = "Extracting...please, wait ";
String character = "█";
String str = null;
while (cond) {
int i = 0;
str = txt;
out.print("\r" + str + character);
try {
Thread.sleep(pause);
} catch (InterruptedException ex) {
Logger.getLogger(JthnDEMO.class.getName()).log(Level.SEVERE, null, ex);
}
while (i < progressbarLength) {
str = txt;
for (int j = 0; j < i + 1; j++) {
str += character;
}
out.print("\r" + str);
try {
Thread.sleep(pause);
} catch (InterruptedException ex) {
Logger.getLogger(JthnDEMO.class.getName()).log(Level.SEVERE, null, ex);
}
i++;
}
}
});
}
}
But to my big surprise when I compiled it and run it from command line via .bat file the output in CMD window makes just one full loop and then just kind-of flicking the whole line without updating and I do not know why.
Can anyone tell me why my progressbar code runs in NetBeans 8 output window but not in Win7 x64 system CMD window once compiled?
P.S.: the value of variable cond would be changed later (I will rewrite that single line of code so that the variable is defined somewhere else outside) in my code once I want my endless progressbar to end, so no worries about that (just saying I know).
I couldn't reproduce this, but the issue could very well be that you are flushing the stream with \r and then print the progressbar, in other words this should be reversed:
E.g. this part from:
out.print("\r" + str);
to:
out.print(str + "\r");
See here: Command line progress bar in Java
The IDE might use a different PrintStream when your command line, therefore might always call out.flush on every call to print.
So, I found solution myself (solution was to add last output in a loop as completely blank line in the length of the last "normal" output string) - this updated code now works both in NetBeans 8 output window (so one can test it right from the IDE without need of perpetual compiling with every change to code) and also as expected in CMD window too, I hope this may help anyone who might run into same "problems" as I did:
package jthndemo;
import java.io.PrintStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
public class JthnDEMO {
public static void main(final String[] args) throws InterruptedException {
SwingUtilities.invokeLater(() -> {
PrintStream out = System.out;
int pause = 300;
int progressbarLength = 15;
boolean cond = true;
String txt = "Extracting...please, wait ";
String character = "█";
String str = null;
while (cond) {
int i = 0;
str = txt;
out.print("\r" + str + character);
try {
Thread.sleep(pause);
} catch (InterruptedException ex) {
Logger.getLogger(JthnDEMO.class.getName()).log(Level.SEVERE, null, ex);
}
while (i < progressbarLength) {
str = txt;
for (int j = 0; j < i + 1; j++) {
str += character;
}
out.print("\r" + str);
try {
Thread.sleep(pause);
} catch (InterruptedException ex) {
Logger.getLogger(JthnDEMO.class.getName()).log(Level.SEVERE, null, ex);
}
i++;
}
String blank = "";
for (int k = 0; k < str.length(); k++) {
blank += " ";
}
out.print("\r" + blank);
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(JthnDEMO.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
}
It works on my Windows 10. I changed the String character = "-"; as it was displaying â??, but this might just be due to my Windows standard CharacterSet. It was a little tricky to see that the cursor restarts at the beginning and prints the same thing again and again, so I also included this:
if (character.equals("-")) {
character = " ";
} else {
character = "-";
}
while (i < progressbarLength) { ..snip..
In my CMD (Command Prompt) it start with this:
Extracting...please, wait
Then a few seconds later it starts to print the first - (updating the line, there is ONLY one line, not 3 like below. I'm just trying to show the progress):
Extracting...please, wait -
Extracting...please, wait --
Extracting...please, wait ---
then it keeps adding -'s about 3 per second until there are 15 of them and it looks like this
Extracting...please, wait ---------------
Then (due to my change) it starts to look like this
Extracting...please, wait --------------
Extracting...please, wait -------------
Extracting...please, wait ------------
Extracting...please, wait -----------
When all the - are overwritten, it just starts over with writing -'s
I'm sorry that my addition isn't working in your NetBeans. I only did it to see that it really keeps updating, and I didn't like the â??. Back before all the graphics, I noticed some installations using - \ | / - to make it look like the line was spinning, sort of like this:
---------------
\--------------
-|-------------
--/------------
---------------
----\----------
I think your program is a really neat waiting feature. I was impressed.
(I don't have NetBeans or Eclipse or any other IDE on my computer at the moment, so I'm not confused about that :)

How to write a program that reads from and write to file

I'm reading a file with numbers checking if the number is a prime number then writing next to the prime numbers "is a prime" and printing that out to a different file,
I keep getting:
Failed to open file in4.txt Exiting...
This is my code:
import java.util.Scanner;
import java.util.ArrayList;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
public class CheckPrimes {
public static void checkPrimes(String in_file, String out_file) {
File temp = new File(in_file);
Scanner input;
try
{
input = new Scanner(temp);
}
catch (Exception e)
{
System.out.printf("Failed to open file %s\n", in_file);
return;
}
while (true)
{
for (int i = 2; i < input.nextInt(); i++)
{
if (input.nextInt() % i != 0)
{
try{
PrintWriter output = new PrintWriter(out_file);
output.print( input.nextInt() + " is prime");
output.close();
}
catch(IOException ex)
{
System.out.printf("Error : %s\n",ex);
}
}
}
}
{
public static void main(String[] args)
{
checkPrimes("in4.txt", "out4.txt");
System.out.printf("Exiting...\n");
}
}
Longshot but might work since someone had that problem on this site yesterday. I referred them to this answer on a different topic where the File URL is formatted differently into a path that java seems to accept better that plaintext filepaths.
For the error you are receiving (Failed to open file in4.txt), just make sure that the file you are reading is on the same file level as your JAR (or file if running in an IDE). Alternatively, you can run the createNewFile() function and edit the created function.
(IntelliJ runs the file from the base of the project, hence why my files aren't where the class file is).
However, upon running the code myself, I was receiving this error: java.util.NoSuchElementException. I was able to correct this by switching from readInt() to readLine(), and having the in4.txt file structured as shown:
1
3
5
7
9
I believe readInt() not working versus readLine() is due to the problem presented in this problem. Also, be wary of calling readLine/readInt multiple times rather than assigning a variable per loop iteration because every call progresses the scanner (more info here).

Java Process Builder

I have a project where program has to open notepad file and after entering text and saving that notepad file program should display number of words in that file and it should delete the entered content in the file.
iam getting this error Error not derjava.lang.NullPointerException after running the program.
though after entering some text in Mytext.txt and saving it?
my question is why BufferedReader is reading empty file even though iam saving the file with some content.
Appreciate the help..
public class Notepad_Example {
public static void main(String[] jfb) {
try {
ProcessBuilder proc = new ProcessBuilder("notepad.exe", "C:\\Java Projects\\Reverse String\\src\\Mytext.txt");
proc.start();
BufferedReader br;
String s;
br = new BufferedReader(new FileReader("C:\\Java Projects\\Reverse String\\src\\Mytext.txt"));
s = br.readLine();
char c[] = new char[s.length()];
int j = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != ' ') {
c[i] = s.charAt(i);
} else {
j++;
}
}
System.out.println("number of words are " + (j + 1));
br.close();
} catch (Exception hj) {
System.out.println("Error not der" + hj);
}
try {
FileWriter fw = new FileWriter("C:\\Java Projects\\Reverse String\\src\\Mytext.txt");
fw.close();
} catch (Exception hj) {
System.out.println("Error not der" + hj);
}
}
}
The issue you are having is here:
ProcessBuilder proc=new ProcessBuilder("notepad.exe","C:\\Java Projects\\Reverse String\\src\\Mytext.txt");
proc.start();
proc.start() is returning the freshly started process. You'll have to give the user the chance to edit and save the file and close the editor before you can read from that file. That is you have to wait for that process to finish before you can start using the results (the saved file) of that process.
So do instead something like this:
Process process = proc.start();
int result = process.waitFor();
if (result == 0) {
// Do your rest here
} else {
// give error message as the process did not finish without error.
}
Some further remarks:
The rest of your code also appears to have some issues.
You are only reading one line of that file. What if the user is using new lines?
The exception handling is not very good, at the very least print the stack trace of the exception which will give you further hints of where an exception was occuring
If you are using Java 7, read on try with resources; if you are using Java 6, add finally blocks to make sure your resources (the streams) are getting closed.
When you run proc.start(); it is not going to block and waitfor the process to end, it will continue running.
You will need to call the proc.waitFor() method, to block until it has finished.
NOTE
we have had some weird behaviour when using the process builder...
we used to start the process with a
new ProcessBuilder("notepad.exe", "C:\\Java Projects\\Reverse String\\src\\Mytext.txt");
but that started to fail wen we upgraded to Win7 and Java7 - we we not sure where this problem really originated, but we changed out Code like this:
String[] cmd = new String[]{"notepad.exe", "C:\\Java Projects\\Reverse String\\src\\Mytext.txt"};
new ProcessBuilder(cmd);
and since then it worked correct!

calling R script from java

I would like to call an R script from Java. I have done google searches on the topic, but almost all of the results I have seen would require me to add a dependency to some third party library. Can anyone show me a good way to accomplish the same thing without adding any dependencies to my code?
I am using a windows machine, so perhaps I might use the command line to start R (if it is not already open) and to run a specific R script. But I have never written command line code (or called it from Java) so I would need code examples.
I am including working sample code that I wrote for one possible approach below, using my command line idea. In my in-line-comments below, you can see that Step Three in AssembleDataFile.java is intentionally left blank by me. If you think that you can make the command line idea work, then please show me what code to write in Step Three.
Also, feel free to suggest another approach that, hopefully, does not involve adding any more dependencies to my code.
And, as always, I very much appreciate any links you might post to articles/tutorials/etc related to this question.
Here is what I have so far:
AssembleDataFile.java
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
public class AssembleDataFile {
static String delimiter;
static String localPath = "C:\\test\\cr\\";
static String[][] myDataArray;
public static void main(String[] args) {
String inputPath = localPath+"pd\\";
String fileName = "MSData.txt";
delimiter = "\\t";
// Step One: Import data in two parts
try {
// 1A: get length of data file
BufferedReader br1 = new BufferedReader(new FileReader(inputPath+fileName));
int numRows = 0;
int numCols = 0;
String currentRow;
while ((currentRow = br1.readLine()) != null) {
numRows += 1;
numCols = currentRow.split(delimiter).length;}
br1.close();
//1B: populate data into array
myDataArray = new String[numRows][numCols+1];
BufferedReader br2 = new BufferedReader(new FileReader(inputPath+fileName));
String eachRow;
int rowIdx = 0;
while ((eachRow = br2.readLine()) != null) {
String[] splitRow = eachRow.split(delimiter);
for(int z = 0;z < splitRow.length;z++){myDataArray[rowIdx][z] = splitRow[z];}
rowIdx += 1;}
br2.close();
// Step Two: Write data to csv
String rPath = localPath+"r\\";
String sFileName = rPath+"2colData.csv";
PrintWriter outputWriter = new PrintWriter(sFileName);
for(int q = 0;q < myDataArray.length; q++){
outputWriter.println(myDataArray[q][8]+", "+myDataArray[q][9]);
}
outputWriter.close();
//Step Three: Call R script named My_R_Script.R that uses 2ColData.csv as input
// not sure how to write this code. Can anyone help me write this part?
// For what it is worth, one of the R scripts that I intend to call is included below
//
//added the following lines here, per Vincent's suggestion:
String rScriptFileName = rPath+"My_R_Script.R";
Runtime.getRuntime().exec("mypathto\\R\\bin\\Rscript "+rScriptFileName);
//
//
//Step Four: Import data from R and put it into myDataArray's empty last column
try {Thread.sleep(30000);}//make this thread sleep for 30 seconds while R creates the needed file
catch (InterruptedException e) {e.printStackTrace();}
String matchFileName = rPath+"Matches.csv";
BufferedReader br3 = new BufferedReader(new FileReader(matchFileName));
String thisRow;
int rowIndex = 0;
while ((thisRow = br3.readLine()) != null) {
String[] splitRow = thisRow.split(delimiter);
myDataArray[rowIndex][numCols] = splitRow[0];
rowIndex += 1;}
br3.close();
//Step Five: Check work by printing out one row from myDataArray
//Note that the printout has one more column than the input file had.
for(int u = 0;u<=numCols;u++){System.out.println(String.valueOf(myDataArray[1][u]));}
}
catch (FileNotFoundException e) {e.printStackTrace();}
catch (IOException ie){ie.printStackTrace();}
}
}
My_R_Script.R
myCSV <- read.csv(file="2colData.csv",head=TRUE,sep=",")
pts = SpatialPoints(myCSV)
Codes = readShapeSpatial("mypath/myshapefile.shp")
write.csv(ZipCodes$F[overlay(pts,Codes)], "Matches.csv", quote=FALSE, row.names=FALSE)
EDIT:
Here is the error message that is being thrown when I add Runtime.getRuntime().exec("Rscript "+rScriptFileName); to the code above:
java.io.IOException: Cannot run program "Rscript": CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at AssembleDataFile.main(AssembleDataFile.java:52)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(Unknown Source)
at java.lang.ProcessImpl.start(Unknown Source)
... 5 more
SECOND EDIT:
The code above now works because I followed Vincent's suggestions. However, I had to put in a sleep command in order to give the R script enough time to run. Without the sleep command, the java code above throws an error saying that the Matches.csv file does not exist. I am concerned that a 30 second sleep period is too rough of an instrument. Can anyone show me code that gets the java program to wait until the R program has a chance to create Matches.csv? I hesitate to use thread tools because I have read that poorly designed threads can cause bugs that are nearly impossible to localize and fix.
You just want to call an external application: wouldn't the following work?
Runtime.getRuntime().exec("Rscript myScript.R");
You can easily adapt this code: http://svn.rforge.net/org/trunk/rosuda/REngine/Rserve/test/StartRserve.java
Among other things it finds R and runs a fixed script in R - you can replace that script with with your script and ignore the last two methods.
Do not wait for the process to finish with Thread.sleep()...
Use the waitFor() method instead.
Process child = Runtime.getRuntime().exec(command, environments, dataDir);
int code = child.waitFor();
switch (code) {
case 0:
//normal termination, everything is fine
break;
case 1:
//Read the error stream then
String message = IOUtils.toString(child.getErrorStream());
throw new RExecutionException(message);
}
BufferedReader reader = null;
Process shell = null;
try {
shell = Runtime.getRuntime().exec(new String[] { "/usr/bin/Rscript", "/media/subin/works/subzworks/RLanguage/config/predict.R" });
reader = new BufferedReader(new InputStreamReader(shell.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
...would require me to add a dependency to some third party library...
Why is that so bad? You make it sound like "...would require me to assault a honeybadger with a baseball bat..." I don't see the harm, especially if it works.
Maybe RCaller can help you. No JNI required.

How to run command line within java using thread async

I am new to java. I am tasked to write java program to run the command lines. I tested the command line under the DOS prompt since i do not have have access to Linux box yet. it worked fine. See the PROGRAM below for full command line syntax. the job will take 6 input files and generate some output files. Next i tried to create a class to and using getruntime and process to process this job. Even it compiled without error but when i run it just show the cursor blinking... i thought i need to use Thread async technique. please provide some advices since i do not have enough time for the projects. I also would like to implement a call back or return values when the job is done. an example would be greatly appreciated. Thanks
import java.io.*;
public class RunJob {
// public static final String PROGRAM = "c:\\wrk\\java.exe Hello";
//one command line below
public static final String PROGRAM = "c:/java.exe -cp \"wrk/jmp.jar;wrk/colt.jar\" gov.lanl.yadas.reliability.UltimateMissileReliabilityModel 10000 \"wrk/\" x1.dat x2c.dat x3.dat x4.dat x5.dat x6.dat true";
// Set to true to end the loop
static boolean done = false;
public static void main(String argv[]) throws IOException {
BufferedReader is;
String line;
String returnMsg = "Start ";
final Process p = Runtime.getRuntime().exec(PROGRAM);
System.out.println("start");
Thread waiter = new Thread() {
public void run() {
try {
p.waitFor();
} catch (InterruptedException ex) {
System.out.println("InterruptedException");
return;
}
System.out.println("Program terminated!");
done = true;
}
};
waiter.start();
is = new BufferedReader(new InputStreamReader(p.getInputStream()));
while (!done && ((line = is.readLine()) != null))
{
System.out.println(line);
returnMsg = returnMsg + line;
}
System.out.println(returnMsg);
System.out.println("End");
return;
}// main
}
I assume that there is a good reason why you want to run a java program from another java program and not just from a shell script, or by invoking an API - but if not - please reconsider.
As to your problem - if your application produces a lot of output (the one you are running as a process) - your application will hang. The p.waitFor() will halt until the process ends. But if you don't read the information from the InputStream - it will overflow and hang!
Advice #1: put the p.waitFor() at the end.
Advice #2: read this article. If I remember correctly it is the one I read when I had a similar problem. You can also google for "StreamGobbler" - it is a common name for a separate thread that "gobbles" your streams.
Advice #3: Don't forget the ErrorStream - if your application will produce too many errors - that stream will cause the process to hang as well.

Categories