Java Temporary Files, read and write - java

I have this piece of code
package Classes;
import java.io.*;
public class IpAdministrator {
public Boolean isActive(String ipAddress) {
boolean isActive = false;
String cmd;
String OS = System.getProperty("os.name");
System.out.println(OS);
String tmpfolder = System.getProperty("java.io.tmpdir");
System.out.println(tmpfolder);
//iptmp.deleteOnExit();
if (OS.equals("Linux")) {
cmd = "ping " + ipAddress + " -c 1";
} else {
cmd = "cmd /c ping " + ipAddress + " -n 1";
}
try {
String s = null;
Process p = Runtime.getRuntime().exec(cmd);
File iptmp = File.createTempFile("ipresult", ".txt", new File(tmpfolder));
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
s = s.toString();
BufferedWriter writer = new BufferedWriter(new FileWriter(iptmp));
writer.write(s);
}
} catch (Exception ex) {
System.out.println(ex.getMessage().toString());
}
return isActive;
}
}
I want to write the result from the command in the temporary file, I found something related in other questions in this site, and it seems to work fine, but when I run this, the file is created with some random numers (ie: ipresult540677216848957037.txt) and it's empty, I can't figure out why, I also read that it's something related to java 1.7, so that means that I can't fill the file with information, there something that I'm missing?

Every time you open a file for writing that way -- i.e., every time you execute this line:
BufferedWriter writer = new BufferedWriter(new FileWriter(iptmp));
the file is truncated to zero length. Furthermore, since you never explicitly call close() on the BufferedWriter, line you do write will never actually be flushed to the file. As a result, no data ever makes it to the disk.
To do this correctly, first, move the line above to before the loop, so it only executes once. Second, after the loop, include code like
if (writer != null)
writer.close();
Finally, note that your program is needlessly broken on Macs, which are neither Linux, nor do they use cmd.exe. Instead of the way you've written this, you test explicitly for Windows, and use the Windows command line if you find it; otherwise, assume something UNIX-like, and use the Linux version.

You need to close the writer
BufferedReader stdInput = new BufferedReader(new InputStreamReader(
p.getInputStream()));
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(iptmp));
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
s = s.toString();
writer.write(s);
}
} finally {
if (writer != null) {
writer.close();
}
}
If you are using java 7
try (BufferedWriter writer = new BufferedWriter(new FileWriter(
iptmp));) {
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
s = s.toString();
writer.write(s);
}
}

Related

Trying to run an exe file created from a cpp file in java

I'm trying to run an executable file created from a cpp program in java. If I double-click the exe file, it works just fine, but if I run the file using ProcessBuilder, it gets stuck for some reason, it prints most of the expected output and doesn't continue, also making the entire Java program not responding.
here's my code:
String filePath = FirstScreenController.getFile().getPath();
ProcessBuilder launcher = new ProcessBuilder("ClusteringProgram\\Release\\main.exe",filePath);
launcher.redirectErrorStream(true);
try {
/*File file = FirstScreenController.getFile();
Path newPath = Paths.get(System.getProperty("user.dir")+"\\ClusteringProgram").resolve("K12.fasta");//Moving the file to the
Files.copy(Paths.get(file.getPath()), newPath, StandardCopyOption.REPLACE_EXISTING);*/
System.out.println("Execution started");
p = launcher.start();
InputStream stderr = p.getInputStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
p.waitFor();//Waiting for the process to finish running
System.out.println("Execution completed");
} catch (IOException | InterruptedException e) {e.printStackTrace();}
Close your stream. That's what's causing you to hang. I write code like this quite a bit.
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close(); // You need this or p can hang
p.waitFor();
In addition, you called launcher.redirectStandardError(true); so you actually need all this to gather both stdout and stderr together: The whole rest of this answer is wrong. I don't know what is causing the deadlock. I'm leaving the large code fragment here in case it's some strange library bug and it turns out that the dual-thread reading technique is required to work around it.
final object lock = new object();
InputStream stdout = p.getInputStream();
InputStreamReader isr = new InputStreamReader(stdout);
BufferedReader br = new BufferedReader(isr);
final InputStream stderr = p.getErrorStream();
one = new Thread() {
public void run() {
InputStreamReader isr2 = new InputStreamReader(stderr);
BufferedReader br2 = new BufferedReader(isr2);
while ((line2 = br2.readLine()) != null) {
synchronized(lock) {
System.out.println(line2);
}
}
br2.close(); // you need this or p can hang
}
};
one.start();
while ((line = br.readLine()) != null) {
synchronized(lock) {
System.out.println(line);
}
}
br.close(); // You need this or p can hang
for (;;) {
try {
one.join();
break;
} catch (InterruptedException v) {
/* if there's something that might want the main thread's attention handle it here */
}
}
p.waitFor();

In ubuntu unable to write file in specified directory using java

While trying to write file in specified directory i am getting exception.
Java code :-
public void jsonToYaml(JSONObject json, String studioName)
throws JSONException, org.codehaus.jettison.json.JSONException,
IOException {
Yaml.dump(Yaml.dump(JsonToMap.jsonToMap(json)), new File("config.yml"));
BufferedReader br = new BufferedReader(new FileReader("config.yml"));
String line;
studioName = studioName.toLowerCase();
File writeFile = new File("sudo /var/iprotecs/idns2.0","" + studioName + ".yaml");
FileOutputStream fos = new FileOutputStream(writeFile);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
try {
while ((line = br.readLine()) != null) {
String line1 = line.replace("\"", "");
String line2 = line1.replaceAll("!java.util.HashMap", "");
String line3 = line2.replaceAll("---", "");
String line4 = line3.replace("|", "");
System.out.println(line4);
bw.write(line4);
bw.newLine();
}
} catch (FileNotFoundException e) {
System.out.println(e);
}
}
Exception :-
How to create file write content to it.
java.io.FileNotFoundException: sudo /var/iprotecs/idns2.0/asia.yaml (No such file or directory)
Do not name the file sudo var/... but only /var/.... sudo is a shell command.
sudo is not a file you want to write to, It is a program that is used to temporarily elevate privileges. I think you need something like:
File writeFile = new File("/var/iprotecs/idns2.0", studioName + ".yaml");
You cannot write outside of the /home/ directory by default.
Also sudo is a command, you cannot execute a command from a BufferedWriter.
So, launch your jar with sudo java -jar yourJar.jar or launch your IDE in root (for eclipse sudo eclipse).
And try something like that:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
class jsonToYaml
{
public static void main(String args[]) throws Exception
{
String line, allLine;
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new FileReader("config.yml")); // Add config.yml into the BufferedReader
try
{
while ((line = bufferedReader.readLine()) != null) // Read line per line config.yml (from the BufferedReader) until it is over
{
stringBuilder.append(line); // add the line into stringBuilder
stringBuilder.append(System.lineSeparator()); // add a lineSeparator into stringBuilder
}
allLine = stringBuilder.toString(); // allLine is equal to stringBuilder
}
finally
{
bufferedReader.close(); // Close the BufferedReader
}
String studioName = System.getProperty("user.name"); // set studioName
FileWriter fileWriter = new FileWriter("/var/iprotecs/idns2.0/" + studioName + ".yaml", true); // create a FileWriter && true for append a String into your FileWriter or false for ecrase a String into your FileWriter
try
{
fileWriter.write(allLine ,0, allLine.length()); // Write allLine into "/var/iprotecs/idns2.0/ + studioName + .yaml"
}
finally
{
fileWriter.close(); // close the FileWriter
}
}
}
You need to launch Eclipse in sudo mode from your terminal.
It is always the same if you need to write a file outside of /home or /media.

Java Temporary File test passes on OSX, fails on Windows

I've got a JUnit test that tests a piece of code I've been working on that uses temporary files to perform certain functions. For whatever reason, the test passes on OSX, but fails on Windows 7. To simplify things, I copied the test into a new file, and boiled it down to be as simple as possible while still demonstrating the error.
Basically, I initialize the temporary file by writing a comma separated key-value pair into the file (and then assert that it exists, which it does). Then, I attempt to replace the value of the line, based on the key. updateValueForKey() has the boolean "checkOldVal", which, if true, requires that oldVal passed in match the one in the file. This test fails on Windows, and passes on OSX whether this is true or false
Windows Java version: 1.6.0_45
OSX Java version: 1.6.0_65
The code is as follows:
public class SimpleTempFileTest {
ReadWriteLock _fileLock = null;
File _file = null;
public SimpleTempFileTest() {
}
#Test
public void simpleTempFileTest() throws Exception {
_file = File.createTempFile("testCsv", null);
_file.deleteOnExit();
_fileLock = new ReentrantReadWriteLock();
BufferedWriter writer = null;
try {
_fileLock.writeLock().lock();
writer = new BufferedWriter(new FileWriter(_file, true));
writer.append("foo,bar");
writer.newLine();
} finally {
if (writer != null) {
writer.close();
}
_fileLock.writeLock().unlock();
}
BufferedReader br = new BufferedReader(new FileReader(_file));
String line = br.readLine();
assertTrue("Unexpected value. Line=" + line, line.equals("foo,bar"));
assertTrue("Unexpected value. Line=" + line, br.readLine() == null);
br.close();
//Fails whether checkOldVal is true or false
updateValueForKey("foo", "bar", "baz", true);
br = new BufferedReader(new FileReader(_file));
line = br.readLine();
//Everything up to this point passes, but the following assertion fails
assertTrue("Unexpected value. Line=" + line, line.equals("foo,baz"));
assertTrue("Unexpected value. Line=" + line, br.readLine() == null);
br.close();
}
String updateValueForKey(String key, String oldVal, String newVal, boolean checkOldVal) throws FileNotFoundException, IOException {
BufferedReader br = null;
BufferedWriter writer = null;
File temp = null;
try {
_fileLock.writeLock().lock();
br = new BufferedReader(new FileReader(_file));
temp = File.createTempFile("csvTmp", ".tmp");
writer = new BufferedWriter(new FileWriter(temp, true));
boolean seek = true;
String line;
while ((line = br.readLine()) != null) {
if (seek) {
String[] nvp = line.split(",");
System.out.println("nvp[0]=" + nvp[0] + ", nvp[1]=" + nvp[1]);
if (nvp[0].equalsIgnoreCase(key)) {
if (nvp[1].equals(oldVal) || !checkOldVal) {
String lineToWrite = key + "," + newVal;
System.out.println("Writing " + lineToWrite);
writer.write(lineToWrite);
writer.newLine();
seek = false;
continue;
} else {
System.out.println("Failed for " + key + ". Val incorrect.");
return "Password incorrect";
}
}
}
writer.write(line);
writer.newLine();
}
_file.delete();
temp.renameTo(_file);
return null;
} finally {
if (br != null) {
br.close();
}
if (writer != null) {
writer.close();
}
if (temp != null) {
temp.delete();
}
_fileLock.writeLock().unlock();
}
}
}
Any ideas guys? Thanks.
The issue is related to differences between the way Windows and Unix handle locks on files. On Unix, One process can be writing to a file, and another can open it to read it. Windows does not allow this.
Full disclosure: I expected Java to throw an IOException if it failed to perform IO-type stuff on files, briefly forgetting that many of those operations return boolean specifying whether or not the operation was successful.
Long story short, near the end of updateValueForKey(), where I delete _file, and rename tmp to _file, temp still has a FileWriter open against it, and _file still has a BufferedReader open against it. Basically, I had to move the _file.delete and temp.renameTo() below the finally block.

Output and error streams on windows console

I'm looking for a solution to print the output and error streams on the windows console.
A java program starts a rcp application (.exe) thanks to a command line :
Runtime.getRuntime.exec("example.exe");
Example.exe writes something after being started...
Then I want the java program to get the output stream of example.exe.
My problem is that it doesn't work and if I put the 2 eclipse runtime options: -console and -consoleLog, the output stream is printed in another console so I can't get back the stream...
Any ideas?
Edit: Here is my code to get the outputStream and errorStream (it works for a simple java program but not for a rcp application)
final Process process = Runtime.getRuntime().exec("toto.exe");
new Thread() {
public void run() {
try {
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = "";
try {
while((line = inputReader.readLine()) != null) {
inputText = inputText + line;
}
System.out.println(inputText);
while((line = errorReader.readLine()) != null) {
errorText = errorText + line;
}
System.out.println(errorText);
} finally {
errorReader.close();
inputReader.close();
}
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}.start();

Java Process IO

Im using java to start a GNOME terminal process in linux and redirecting its input and output to my code. Below is a code.
public static void main(String[] args) throws InterruptedException
{
// TODO Auto-generated method stub /usr/bin/telnet
try
{
String line, commandInput;
Scanner scan = new Scanner(new File("/home/Ashutosh/Documents/testfile"));
ProcessBuilder telnetProcessBuilder = new ProcessBuilder("/bin/bash");///home/Ashutosh/Documents/tempScript");
telnetProcessBuilder.redirectErrorStream(true);
Process telnetProcess = telnetProcessBuilder.start();
//Process telnetProcess = Runtime.getRuntime().exec("xterm");///home/Ashutosh/Documents/tempScript");
BufferedReader input = new BufferedReader(new InputStreamReader(telnetProcess.getInputStream()));
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(telnetProcess.getOutputStream()));
while(scan.hasNext())
{
commandInput = scan.nextLine();
output.write(commandInput);
/* if(commandInput.trim().equals("exit"))
{
output.write("exit\r");
}
else
{
output.write("((" + commandInput + ") && echo --EOF--) || echo --EOF--\r");
}
*/ output.flush();
line = input.readLine();
while(line != null && !line.trim().equals("--EOF--"))
{
System.out.println(line);
line = input.readLine();
}
if(line == null)
break;
}
/* Thread.sleep(500);
output.write("/home/Ashutosh/Documents/testfile\r");
Thread.sleep(500);
output.flush();
while((line = input.readLine())!= null)
System.out.println(line);
telnetProcess.destroy();
*/ //String s = input.readLine();
//System.out.print(s + "\r\n");
//s = input.readLine();
//System.out.print(s + "\r\n");
}
the contents of testfile which is bash script is
#!/bin/bash
ls -l
pwd
date
exit
and i also tried the following interactive script which takes input from user which i want to redirect from java code is given
#! /bin/bash
echo "Input any number form 0-3:"
read num
case $num in
0) echo "You are useless";;
1) echo "You are number 1";;
2) echo "Too suspecious";;
3) echo "Thats all man, got to go...!";;
*) echo "Cant't u read english, this is wrong choice";;
esac
read
exit
my code stops at input.readLine(); im not sure but i think i am not able to redirect the output stream
output.write(commandInput);
command is executing well but did not write i intended to on the process redirected input, that is why it hangs at readLine();.
If somebody have already solved please let me know the solution.
From following link i tried to solve the issue but still no luck:
Java Process with Input/Output Stream
Thanks
Ashutosh
readLine() read the contents of a line, without the newline at the end.
write() writes just the text, it doesn't add a new line.
Perhaps you want to add write("\n"); or use PrintStream or PrintWriter.
I imagine, your script is being sent as
#!/bin/bashls -lpwddateexit
which is a comment without a newline.
EDIT: Huge error, not adding the command to the ProcessBuilder!!
Why are you not just running your script as a Linux script? That is,
ProcessBuilder builder = new ProcessBuilder();
LinkedList<String> command = new LinkedList<String>();
command.add("/bin/bash");
command.add("/home/Ashutosh/Documents/testfile");
builder.command(command);
Process myProc = builder.start();
Also, I notice the variable is named 'telnetProcess' yet there is no invocation of telnet anywhere that I can see. Perhaps this is the problem?
EDIT: Added my suggestion below for the interactive script.
ProcessBuilder builder = new ProcessBuilder();
LinkedList<String> command = new LinkedList<String>();
command.add("/bin/bash");
command.add("/path/to/interactiveScript");
builder.command(command);
final Process myProc = builder.start();
// Java input goes to process input.
Thread inputParser = new Thread() {
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(myProc.getOutputStream()));
String line = "";
while(line != null) {
line = br.readLine();
bw.write(line);
bw.newLine();
}
}
}.start();
// Process output must go to Java output so user can see it!
Thread outputParser = new Thread() {
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(myProc.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = "";
while(line != null) {
line = br.readLine();
bw.write(line);
bw.newLine();
}
}
}.start();
hi guys sorry for late response, after some trials i got it working. I am simply letting the process completing its process and exit normally rather than forcefully and then the BufferedReader and BufferedWriter keeps the string buffers in RAM which i can read now after process exit with code 0.
public static void main(String[] args) throws InterruptedException
{
// TODO Auto-generated method stub
try
{
String line, commandInput;
ProcessBuilder telnetProcessBuilder = new ProcessBuilder("/bin/bash");
telnetProcessBuilder.redirectErrorStream(true);
Process telnetProcess = telnetProcessBuilder.start();
BufferedReader input = new BufferedReader(new InputStreamReader(telnetProcess.getInputStream()));
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(telnetProcess.getOutputStream()));
commandInput = "ls -l\n";
output.write(commandInput);
output.flush();
commandInput = "pwd\n";
output.write(commandInput);
output.flush();
commandInput = "whoami\n";
output.write(commandInput);
output.flush();
commandInput = "exit\n";
output.write(commandInput);
output.flush();
while((line = input.readLine())!= null)
System.out.println(line);
}
}

Categories

Resources