I have a simple python program (hw1.py) as follows:
x = int(input("Enter x value: "))
y = int(input("Enter y value: "))
print("x is " + str(x))
print("y is " + str(y))
print("Output is " + str(x+y))
When I run it from terminal, I get following output as expected:
Enter x value: 10
Enter y value: 20
x is 10
y is 20
Output is 30
However, when I run it from Java with providing inputs ("10" and "20") I get slightly different output. Here is the Java code to compile and run python file:
String osName = System.getProperty("os.name").toLowerCase();
boolean isMacOs = osName.startsWith("mac os x");
String macPythonPath = "/Library/Frameworks/Python.framework/Versions/3.6/bin/python3";
String unixPythonPath = "/usr/bin/python3";
Process p;
if (isMacOs) {
p = Runtime.getRuntime().exec(macPythonPath + " -m py_compile " + "/Users/inanc/Desktop/pythonDocs/hw1.py");
} else {
p = Runtime.getRuntime().exec(unixPythonPath + " -m py_compile " + "/Users/inanc/Desktop/pythonDocs/hw31.py");
}
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
String resError = "", s;
// read any errors from the attempted command
while ((s = stdError.readLine()) != null) {
resError = resError + s + "\n";
}
resError = resError.trim();
stdError.close();
if (resError.equals("")) {
if (isMacOs) {
p = Runtime.getRuntime().exec(macPythonPath + " " + "/Users/inanc/Desktop/pythonDocs/hw1.py");
} else {
p = Runtime.getRuntime().exec(unixPythonPath + " " + "/Users/inanc/Desktop/pythonDocs/hw1.py");
}
String[] inputs = {"10", "20"};
OutputStream out = p.getOutputStream();
for (String input: inputs) {
if (input.equals("") == false)
out.write((input+"\n").getBytes());
}
out.flush();
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
String res = "";
s = null;
while ((s = stdInput.readLine()) != null) {
res = res + s + "\n" ;
}
res = res.trim();
resError = "";
// read any errors from the attempted command
while ((s = stdError.readLine()) != null) {
resError = resError + s + "\n";
}
resError = resError.trim();
stdInput.close();
stdError.close();
p = null;
System.out.println(res);
} else {
System.err.println(resError);
}
After calling this code, the output is as follows:
Enter x value: Enter y value: x is 10
y is 20
Output is 30
How can I get the exactly same output with terminal execution? At least I want to keep the newlines after entering inputs.
Then there is a way only when you make your program such that argument 10 is written to process, then next line is read from the process and then 20 is written to process, and the another line is read from the process,so on
Whereas, in your code, you are writing all the inputs the process needs in a single loop
I solved the problem, here is the solution:
String osName = System.getProperty("os.name").toLowerCase();
boolean isMacOs = osName.startsWith("mac os x");
String macPythonPath = "/Library/Frameworks/Python.framework/Versions/3.6/bin/python3";
String unixPythonPath = "/usr/bin/python3";
String filepath = "/Users/inanc/Desktop/pythonDocs/hw1additionalInputs.py ";
Process p;
if (isMacOs){
p = Runtime.getRuntime().exec(macPythonPath + " -m py_compile " + filepath);
}
else{
p = Runtime.getRuntime().exec(unixPythonPath + " -m py_compile " + filepath);
}
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
String resError = "", s;
// read any errors from the attempted command
while ((s = stdError.readLine()) != null) {
resError = resError + s + "\n";
}
resError = resError.trim();
stdError.close();
if(resError.equals("")) {
if (isMacOs){
p = Runtime.getRuntime().exec(macPythonPath + " " + filepath);
}
else{
p = Runtime.getRuntime().exec(unixPythonPath + " " + filepath);
}
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
String res = "";
s = null;
String[] inputs = {"10", "20"};
OutputStream out = p.getOutputStream();
for(String input:inputs){
if(input.equals("") == false)
{
Thread.sleep(200);
while (stdInput.ready() && (s = "" + (char) stdInput.read()) != null) {
res = res + s ;
}
// read any errors from the attempted command
Thread.sleep(200);
while (stdError.ready() && (s = "" + (char) stdError.read()) != null) {
resError = resError + s;
}
if(resError.equals("") == false)
break;
out.write((input+"\n").getBytes());
out.flush();
res = res + input + "\n";
Thread.sleep(200);
while (stdInput.ready() && (s = "" + (char) stdInput.read()) != null) {
res = res + s ;
}
//res = res.trim();
// read any errors from the attempted command
Thread.sleep(200);
while (stdError.ready() && (s = "" + (char) stdError.read()) != null) {
resError = resError + s;
}
if(resError.equals("") == false)
break;
}
}
Thread.sleep(200);
while (stdInput.ready() && (s = "" + (char) stdInput.read()) != null) {
res = res + s ;
}
//res = res.trim();
// this part is for in case of no inputs
Thread.sleep(200);
while (stdError.ready() && (s = "" + (char) stdError.read()) != null) {
resError = resError + s;
}
stdInput.close();
stdError.close();
if(p.isAlive())
{
System.err.println("Timeout");
p.destroy();
}
p = null;
System.out.println(res);
System.out.println(resError);
}
else {
System.err.println(resError);
}
Related
Im working on converter. I load file, start reading date from it and creating directories by year, month and day(+ another one dir) in witch ends are those converted text files. Everything is fine while creating those directories but in text files is nothing or only chunk of it.
public static void convertFile(File fileToConvert, File whereToSave, long shift) {
BufferedReader reader = null;
BufferedWriter writer = null;
String oldDate = "";
String newDate = "";
boolean boolDate = true;
try {
for (File file : fileToConvert.listFiles()) {
reader = new BufferedReader(new FileReader(file));
boolean block = true;
String line = "";
int lineCounter = 0;
while ((line = reader.readLine()) != null) {
if (lineCounter==0) {
block = true;
} else {
block = false;
}
line = line.replaceAll("[^0-9-,:+NaN.]", "");
String[] data = line.split(",");
if (block) {
data[0] = data[0].substring(0, 10) + " " + data[0].substring(10);
data[0] = SimulatorForRealData.timeShift(data[0], shift);
// ====================================================================================
newDate = data[0].substring(0, 4) + " " + data[0].substring(5, 7) + " "
+ data[0].substring(8, 10);
String savingIn = SimulatorForRealData.createDirs(whereToSave.toString(),
data[0].substring(0, 4), data[0].substring(5, 7), data[0].substring(8, 10));
File f = new File(savingIn + "\\" + FILE_NAME + ".log");
if (!newDate.equals(oldDate) && boolDate == false) {
writer.close();
boolDate = true;
} else {
oldDate = newDate;
boolDate = false;
}
writer = new BufferedWriter(new FileWriter(f));
// =====================================================================================
writer.write("<in date=\"" + data[0].substring(0, 10) + "T" + data[0].substring(11)
+ "\" t=\"1\" >\n");
writer.write(data[0] + "\n");
writer.write(0 + " " + 0 + " " + 0 + "\n");
for (int x = 0; x <= 10; x++) {
writer.write("NaN" + " ");
}
writer.write("\n");
for (String s : data) {
if (s.equals(data[0])) {
continue;
}
writer.write(s + ";");
}
writer.write("\n");
} else {
for (String s : data) {
writer.write(s + ";");
}
writer.write("\n");
}
lineCounter++;
if (lineCounter == 118) {
lineCounter = 0;
writer.write("</in>\n\n");
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
writer.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is method where i perform it. Can someone help me. I tried different "writers" and nothing. I have suspicious that it will be problem in closing file but i dont know for sure.
I think you should close every writer you created, not only last one.
for (File file : fileToConvert.listFiles()) {
reader = new BufferedReader(new FileReader(file));
...
writer = new BufferedWriter(new FileWriter(f));
while ((line = reader.readLine()) != null) {
....
}
writer.close();
}
writer flushes all changes on disk only when buffer is overflowed or it is closed.
I see two main problems:
You create a file every time you read a line. You should put it outside the loop (or loops, if you want only one file)
Always data is written with the same filename. It should have different filenames if you make a file for every file read.
I'm getting a java.lang.OutOfMemoryError: Java heap space. I'm not sure what I'm doing wrong. Here is my code:
StringBuffer finalString = new StringBuffer();
try {
BufferedReader br = new BufferedReader(new FileReader("collegeData 2.txt"));
StringBuffer returnFile = new StringBuffer();
returnFile.append(br.readLine() + br.readLine());
ArrayList<String> allData = new ArrayList<String>();
boolean completedFirstSection = false;
int count = 2;
String addString = "";
String nextLine;
while ((nextLine=br.readLine())!=null) {
if(count < 990) {
addString += nextLine;
count++;
} else {
String sub = nextLine.substring(16);
sub = sub.substring(0, sub.length());
addString = sub + ":{" + nextLine + "," + addString.substring(0, addString.length()-2) + br.readLine();
br.readLine();
allData.add(addString);
count = 2;
}
}
allData.add("}}]");
System.out.println("here");
System.out.println(returnFile.toString());
finalString = returnFile;
br.close();
} catch (IOException e) {
e.printStackTrace();
}
collegeData 2.txt is 44.2 mb and it is a json file. Here is my error message.
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.base/jdk.internal.misc.Unsafe.allocateUninitializedArray(Unsafe.java:1250)
at java.base/java.lang.invoke.StringConcatFactory$MethodHandleInlineCopyStrategy.newArray(StringConcatFactory.java:1605)
at java.base/java.lang.invoke.DirectMethodHandle$Holder.invokeStatic(DirectMethodHandle$Holder)
at java.base/java.lang.invoke.LambdaForm$BMH/754666084.reinvoke(LambdaForm$BMH)
at java.base/java.lang.invoke.LambdaForm$MH/801197928.linkToTargetMethod(LambdaForm$MH)
at RunnerCombined.main(RunnerCombined.java:31)
RunnerCombined.java:31 is 'addString += nextLine' above.
Thank you in advance for your help!
Thank you to twain249! After changing my code to this, my program runs quickly and it's perfect!
StringBuffer finalString = new StringBuffer();
try {
BufferedReader br = new BufferedReader(new FileReader("collegeData 2.txt"));
StringBuffer returnFile = new StringBuffer();
returnFile.append(br.readLine() + "\n" + br.readLine() + "\n");
boolean completedFirstSection = false;
int count = 2;
StringBuffer addString = new StringBuffer();
String nextLine;
while ((nextLine=br.readLine())!=null) {
if(count < 990) {
addString.append(nextLine + "\n");
count++;
} else {
String sub = nextLine.substring(16);
sub = sub.substring(0, sub.length());
// addString = sub + ":{" + nextLine + "," + addString.substring(0, addString.length()-2) + br.readLine();
returnFile.append(sub + ":{" + nextLine + "," + "\n");
returnFile.append(addString.substring(0, addString.length()-2) + "\n");
returnFile.append(br.readLine() + "\n");
addString.setLength(0);
count = 2;
br.readLine();
}
}
returnFile.append("}}]");
finalString = returnFile;
br.close();
} catch (IOException e) {
e.printStackTrace();
}
I am trying to execute a ghostscript command from my Java Program using Runtime.getRuntime().exec(command).
The command that i am using to generate PDF/A File is:
command = "/usr/local/bin/gs -q -dPDFA=2 -dBATCH -dNOPAUSE -sColorConversionStrategy=RGB -sDEVICE=pdfwrite -dPSFitPage -dFastWebView=true -dDOPDFMARKS -sOutputFile=" + mergedPDFFile + " " + pdfaDefFile + " " + inputPDFFile + " " + pdfMarksFile;
It works perfectly fine when the input PDF file size is less than 1 MB. However, when the input PDF File size is greater than 1 MB, the output does not get generated.
The code that i have written in Java is:
private void executeCommand(String command) {
Process p = null;
try {
p = Runtime.getRuntime().exec(new String[]{"bash", "-c", command});
String s1 = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((s1= reader.readLine()) != null) {
slf4jLogger.info("+++++++++++++++++++++++++++++" + s1);
}
String s = null;
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((s = stdError.readLine()) != null) {
slf4jLogger.info("***********************" + s);
}
p.waitFor();
int returnValue = p.exitValue();
slf4jLogger.info("RETURN VALUE : " + returnValue);
} catch (Throwable e) {
slf4jLogger.error("ERROR: ********************" + e.toString(), e);
} finally {
slf4jLogger.info("END MY PROCESS:");
if (p != null) {
p.destroy();
}
}
Any help is greatly appreciated.
I want to change the score of the user, but instead of overwriting the file with new scores, it just makes an empty file.
The lines are written like this: "username-password-wins-losses-ties"
try {
BufferedReader br = new BufferedReader(new FileReader("users.txt"));
PrintWriter pw = new PrintWriter(new FileWriter("users.txt"));
String[] tab = null;
String zlepek = "";
while(br.readLine()!=null) {
String line = br.readLine();
tab = line.split("-");
int countLoss = Integer.parseInt(tab[3]+plusLoss);
int countWin = Integer.parseInt(tab[2]+plusWin);
int countTie = Integer.parseInt(tab[4]+plusTie);
if(tab[0].equals(loginUser.user)) {
String newScore = (tab[0] + "-" + tab[1] + "-" + countWin + "-" + countLoss + "-" + countTie + "\n");
zlepek = zlepek+newScore;
} else {
String oldScore = (tab[0] + "-" + tab[1] + "-" + tab[2] + "-" + tab[3] + "-" + tab[4] + "\n");
zlepek = zlepek+oldScore;
}
}
pw.print(zlepek);
pw.close();
br.close();
plusWin = 0;
plusLoss = 0;
plusTie = 0;
} catch(IOException e) {}
Any help is appreciated.
You are skipping the first line and every odd lines, change the code like below
String line = null;
while ((line = br.readLine()) != null){
// code
}
also you are reading and writing on a same file, you can't read and write simultaneously on a same file. If you want you can write it to a temporary file and rename it later.
If you want write on the same file, you have to close the reader before writing, see below
BufferedReader br = new BufferedReader(new FileReader("users.txt"));
String line = null;
StringBuilder sb = new StringBuilder();
String zlepek = "";
while ((line = br.readLine()) != null) {
zlepek = // logic to get value
sb.append(zlepek).append("\n");
}
br.close();
PrintWriter pw = new PrintWriter(new FileWriter("users.txt")); // pass true to append
pw.print(sb);
pw.close();
The problem is with this line while(br.readLine()!=null), you read the line but didnt save it, so it doesnt know where it is and the line will always be empty after you read the line and dont save it.
try to remove this String line = br.readLine(); and read it in the while. define the String line; and while( (line = br.readLine()) != null){ // do something}
try {
String[] tab = null;
String line = null;
tab = line.split("-");
int countLoss = Integer.parseInt(tab[3]+plusLoss);
int countWin = Integer.parseInt(tab[2]+plusWin);
int countTie = Integer.parseInt(tab[4]+plusTie);
BufferedReader br = new BufferedReader(new FileReader("users.txt"));
StringBuilder sb = new StringBuilder();
String zlepek = "";
while ((line = br.readLine()) != null) {
if(tab[0].equals(loginUser.user)) {
String newScore = (tab[0] + "-" + tab[1] + "-" + countWin + "-" + countLoss + "-" + countTie + "\n");
zlepek = zlepek+newScore;
} else {
String oldScore = (tab[0] + "-" + tab[1] + "-" + tab[2] + "-" + tab[3] + "-" + tab[4] + "\n");
zlepek = zlepek+oldScore;
}
sb.append(zlepek).append("\n");
}
br.close();
PrintWriter pw = new PrintWriter(new FileWriter("users.txt")); // pass true to append
pw.print(sb);
pw.close();
plusWin = 0;
plusLoss = 0;
plusTie = 0;
} catch(IOException e) {}
}
public String runMsg(String fileName, File Path, int option)
{
int x = 0;
String name = " ", ret = "";
if (option == 1) {
x = fileName.indexOf(".c");
name = fileName.substring(0, x);
command = name + ".exe < C:\\iptest\\input.txt > C:\\outtest\\" + name + ".txt";
} else if (option == 2) {
x = fileName.indexOf(".cpp");
name = fileName.substring(0, x);
command = name + ".exe < C:\\iptest\\input.txt > C:\\outtest\\" + name + ".txt";
} else {
x = fileName.indexOf(".java");
name = fileName.substring(0, x);
command = "java " + name + " < C:\\iptest\\input.txt > C:\\outtest\\" + name + ".txt";
}
String output = executeCommand(command, Path);
}
private String executeCommand(String command, File Path)
{
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command, null, Path);
p.waitFor();
BufferedReader reader1 = new BufferedReader(new InputStreamReader(p.getErrorStream()));
BufferedReader reader2 = new BufferedReader(new InputStreamReader(p.getInputStream()));
// BufferedReader reader3 = new BufferedReader(new InputStreamReader(p.getOutputStream()));
String line = "";
while ((line = reader1.readLine()) != null) {
output.append(line + "\n");
}
while ((line = reader2.readLine()) != null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
I am trying to execute a .class file from another java file. The .java file will take input from a txt file located at C:\iptest\input.txt and will produce an output file at the following location C:\outputtest\out.txt but when I run this application nothing happens and the application goes into some kind of infinite loop.