I am trying to get some data from registry .The problem is while loop ,because when the application is running in debug mode I can view the value of a line variable .But end of the loop line variable is assigned null
private final String DESKTOP_PATH="\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\"
+ "CurrentVersion\\Explorer\\Shell Folders\" /v Desktop";
private final String REG="REG_SZ";
private final String EXACUTE_STR="reg query "+DESKTOP_PATH;
private String getDesktopPath() throws IOException {
Process p = null;
String line = null;
try {
p = Runtime.getRuntime().exec(EXACUTE_STR);
p.waitFor();
InputStream stream=p.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(stream));
while((line=reader.readLine())!=null){
line+=reader.readLine();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return line;
Consider using jna the Java Native Access library which provides Registry handling utilities.
The reason that I suggest a different toolkit instead of simply solving your problem has to do with a few items. When launching an external executable, you have to handle input and output in a buffered manner, and there are two streams of output (normal and error).
In short, typically all of these input and output streams might need to be available, but you won't typically notice failures when they are not present in the typical development environment. Later, in production environments (headless, console-less, etc) these problems become apparent.
To solve these problems with a CLI call, you typically then set up Buffer collectors to capture the output in independent threads, and sometimes you need to stand up a fake buffer provider (some programs check that input is readable, even if they don't read any input!). The JNA library uses JNI, which greatly reduces the issues by side-stepping the CMD shell that wraps your executable call.
However, if you only wanted to know about the logic error in your code, JimW did a good job explaining it.
You are replacing the contents of line with what you read from reader.readLine(), when that finally returns null you return line which is of course null.
Instead create a StringBuilder before starting the loop and append to that.
StringBuilder buffer = new StringBuilder();
while ((line = reader.readLine())!=null) {
buffer.append(line);
}
// buffer.toString() is the String you are looking for
You could also .trim() inside the append if you want to remove end lines.
Related
on netbeans, im trying to read a file and display its contents on a swing graphics tab. This is how im reading the file
FileReader reader;
ArrayList<String> file = new ArrayList<String>();
Scanner scan = null;
try
{
reader = new FileReader(filename);
scan = new Scanner(reader);
while(scan.hasNext())
{
file.add(scan.nextLine());
}
return file;
}
catch (IOException e)
{
e.printStackTrace();
}
finally {
scan.close();
}
return null;
This is how I'm writing the file
public String writeFile(ArrayList<String> data)
{
String writer = "";
for (String line : data)
{
writer += (line + lineSeparator);
}
return writer;
}
This is how I'm trying to display it
FileIO file = new FileIO();
String filePath="squeeze.txt";
ArrayList<String> data = file.readFile(filePath);
jTextField1.setText(file.writeFile(data));
And I getting an error on
scan.close();
Your problem here is that scan has not been initialized prior to the try block. Anything in the try block might throw an exception, so therefore you have to write your code assuming that all code in the try block will never be run. Luckily, Java has a syntax just for this situation called try-with-resources. Try-with-resources handles your resources for you, and automatically closes them at the end of the try block. Here is your code, modified to use try-with-resources:
try (FileReader reader = new FileReader(filename);
Scanner scan = new Scanner(reader)) {
while(scan.hasNext()) {
file.add(scan.nextLine());
}
return file;
} catch (IOException e) {
e.printStackTrace();
}
return null;
I also notice that in your catch block, you simply print the stack trace. This is perfectly fine as far as syntax goes, and the compiler will accept it, but I wouldn't recommend swallowing errors like this. If you don't want to do anything special, the best all-purpose line you can use is throw new RuntimeException();. This just throws a generic runtime exception, which will print the stack trace and then terminate the program. This also has the added benefit that you don't need the return null; line at the bottom, since the runtime exception will exit the program anyway, and then any method that calls this method can safely assume that this method returns a non-null value.
jTextField1.setText(file.writeFile(data));
A JTextField is for single lines of text. For multiple lines, use a JTextArea.
As to the problem at hand, the easiest solution is to use methods available to any JTextComponent (which includes both of the above).
Namely JTextComponent.read(Reader,Object) & JTextComponent.write(Writer).
I'd like to know if there's a way where the Java SE allows a passage to be printed out and then in between the line we can allow the user to type the answer on the line.
To be more clear :
Here's an example:
____ reading, Alice also enjoys listening to classical music.
So, when the text is being drawn out using the buffer reader, the user is able to enter the answer on the line itself.
Here's the method of buffer reader:
public void getCloze(){
File file = new File("cloze.txt");
StringBuffer contents = new StringBuffer();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String text = null;
// repeat until all lines is read
while ((text = reader.readLine()) != null) {
contents.append(text)
.append(System.getProperty(
"line.separator"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
// show file contents here
System.out.println(contents.toString());
}}
Hope someone can advise me how to and best if there's any tutorial to show the steps.
I dont think it is possible to prompt the user to type in between the already printed line in Java. you have to stop your priniting to take user input and then print further string to the user
It is not entirely clear what your problem is, but you seem to want to know how to write a question or prompt and allow the user to enter the answer on the same line. If so, the "trick" is to use System.out.print(prompt) rather than System.out.println(prompt); i.e. DON'T output a line break after the prompt.
UPDATE - I see what you are asking now.
Well the bad news is that there is no simple way to do that. However, it is doable using something like the charva library or a "curses for Java" library - What's a good Java, curses-like, library for terminal applications?
Lets say that I have this code
moveDirectory.setOnClickListener(new OnClickListener(){
public void onClick(View v)
{
try{
Process send = Runtime.getRunetime().exec(new String[] {"cd /sdcard/music/", "cp pic1 /sdcard/pic1"});
send.waitFor();
} catch (Exception ex){
String toast = null;
Log.i(toast, "Couldn't copy file", ex);
}
}
});
If it fails to copy "pic1" how can I check it? so I can let the user know using a Toast? My only thought is to write code after that one to check if "pic1" is in the right path ("/sdcard/" in this case), but maybe there's an easier way.
you could read the command output. In cp command no output means no error, if there is output you could show it to the user to inform the error.
To read the command output you should add something like:
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(send.getInputStream()));
String line;
ArrayList<String> output = new ArrayList<String>();
while ((line = bufferedReader.readLine()) != null){
output.add(line);
}
good luck.
First it looks like your invocation of exec is not the one intended. Based on the docs if you pass it an String array, the first element of the array is the command and the rest the parameters. Here you have two commands instead.
You can write it just using one command very easily and using the single String invocation of exec:
Process send = Runtime.getRuntime().exec("cp /sdcard/music/pic1 /sdcard/pic1");
Second, no exeception is thrown by waitFor in order to indicate that the command did not succeed. Based on documentation they only checked exception that will be thrown is to indicate that the current thread has been interrupted and in that case there is the possibility that the command has not even finished.
What you need to do is to check the exit status code of the process. This is the value returned by waitFor method. Is common practice that processes/programs return exist status 0 to indicate success and some other value to indicate an error. So the code should be instead:
Process send = Runtime.getRunetime().exec("cp /sdcard/music/pic1 /sdcard/pic1");
try {
if (send.waitFor() != 0) {
String toast = null;
Log.i(toast, "Couldn't copy file", ex);
}
} catch (InterruptedException e) {
// up to you how to recover this situation.
}
Third and foremost ... if what you want to do is to copy a file there is no need to call the system for that. You can use the java.io API to write you own file copying program... but better to reuse apache commons FileUtils helping class.
import org.apache.commons.io.FileUtils;
import java.io.File;
...
FileUtils.copyFile(new File("/sdcard/music/pic1"),new File("/sdcard/music"))
...
Have you tried send.exitValue() and then check if it is an error code like -1
byte[] bytes = value.getBytes();
Process q = new ProcessBuilder("process","arg1", "arg2").start();
q.getOutputStream().write(bytes);
q.getOutputStream().flush();
System.out.println(q.getInputStream().available());
I'm trying to stream file contents to an executable and capture the output but the output(InputStream) is always empty. I can capture the output if i specify the the file location but not with streamed input.
How might I overcome this?
Try wrapping your streams with BufferedInputStream() and BufferedOutputStream():
http://download.oracle.com/javase/6/docs/api/java/lang/Process.html#getOutputStream%28%29
Implementation note: It is a good idea for the output stream to be buffered.
Implementation note: It is a good idea for the input stream to be buffered.
Even with buffered streams, it is still possible for the buffer to fill if you're dealing with large amounts of data, you can deal with this by starting a separate thread to read from q.getInputStream(), so you can still be reading from the process while writing to the process.
Perhaps the program you execute only starts its work when it detects the end of its input data. This is normally done by waiting for an EOF (end-of-file) symbol. You can send this by closing the output stream to the process:
q.getOutputStream().write(bytes);
q.getOutputStream().close();
Try this together with waiting for the process.
I dont know if something else may also be wrong here, but the other process ("process") does not even have time to respond, you are not waiting for it (the method available() does not block). To try this out you can first insert a sleep(2000) after the flush(), and if that works you should switch to query'ing q.getInputStream().available() multiple times with short pauses in between.
I think, you have to wait, until the process finished.
I implemented something like this this way:
public class ProcessReader {
private static final int PROCESS_LOOP_SLEEP_MILLIS = 100;
private String result;
public ProcessReader(Process process) {
BufferedReader resultReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder resultOutput = new StringBuilder();
try {
while (!checkProcessTerminated(process, resultReader, resultOutput)) {
}
} catch (Exception ex1) {
throw new RuntimeException(ex1);
}
result = resultOutput.toString();
}
public String getResult(){
return result;
}
private boolean checkProcessTerminated(Process process, BufferedReader resultReader, StringBuilder resultOutput) throws Exception {
try {
int exit = process.exitValue();
return true;
} catch (IllegalThreadStateException ex) {
Thread.sleep(PROCESS_LOOP_SLEEP_MILLIS);
} finally {
while (resultReader.ready()) {
String out = resultReader.readLine();
resultOutput.append(out).append("\n");
}
}
return false;
}
}
I just removed now some specific code, that you dont need, but it should work, try it.
Regards
I have a class that manages the creation of RTF documents and a method in that class that calls the RTF editor with a XML file for display.
All but one user can access this editor without any issues. This one user consistently runs into an issue where their application just hangs. There are no errors in any logs. Normally this kind of problem is easily identified, reproduced and corrected, however, I can't for the life of my reproduce it so my attempts at debugging are failing.
Basically the code is as follows:
int exitVal = CUBSRTFEditor.runRTFEditor("c:\\tmp\\control"+ap_doc_id+".xml", xml,"I:\\AppealsLetters.exe /process \"c:\\tmp\\control"+ap_doc_id+".xml\"");
public static int runRTFEditor(String xmlLocation, String xmlContent, String executePath)
{
int exitVal = 0;
createLocalFile(xmlLocation, xmlContent);
try
{
System.out.println("executePath must = "+executePath);
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(executePath);
System.out.println("after executePath runs");
//exhaust that stream before waiting for the process to exit
InputStream inputstream = proc.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
// read the ls output
String line;
while ((line = bufferedreader.readLine())!= null)
{
System.out.println(line);
}
exitVal = proc.waitFor();
}
catch (Throwable t)
{
t.printStackTrace();
}
CUBSRTFEditor.deleteTempFile(xmlLocation);
return exitVal;
}
The last output is the first System.out. When I take the xml file and execute this on any other PC it executes without issue. I see no useful info in proc.getErrorStream() or proc.getOutputStream().
The JDK's Javadoc documentation on this problem (exec hanging):
Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.
I try exhausting that stream before waiting for the process to exit and that does not seem to help as it never seems to get to that point (the second System.out is not displayed)
Have I implemented this incorrectly? Am I missing something important? Any ideas on how to get more info out of the process would be great.
I am stuck....
Runtime.exec() is a deceptively nasty little spud to work with. I found this article (old, but still relevant) to be quite helpful. You can always skip to Page 4 for some highly gankable sample code. :-)
At a glance, your code needs to handle both proc.getOutputStream() and proc.getErrorStream(), which is a good reason to handle those streams in separate threads.
I wanted to update this because the change went into Production today and worked. Based off of BlairHippo's suggestions I got it to work with an anonymous inner class to create a separate thread to exhaust both the Error and Input streams.
new Thread(new Runnable(){
public void run()
{
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
String line;
while ((line = br.readLine())!= null)
{
System.out.println(line);
}
}
catch (Throwable t)
{
t.printStackTrace();
}
}
}).start();