How to call a class that accepts command line arguments? - java

I am not a good programmer. In school, I learned MATLAB. So i have no idea what I am doing.
I am working with the ThingMagic M6 reader. They have their own API. I wanted to create my own application to read the program. I want to use a sample program that they have supplied (since my program doesn't seem to work). However, the supplied program only accepts command line arguments. How do i change it so I can pass arguments to it in my code.
This is the supplied code: (at the command line I input tmr://10.0.0.101)
/**
* Sample program that reads tags for a fixed period of time (500ms)
* and prints the tags found.
*/
// Import the API
package samples;
import com.thingmagic.*;
public class read
{
static void usage()
{
System.out.printf("Usage: demo reader-uri <command> [args]\n" +
" (URI: 'tmr:///COM1' or 'tmr://astra-2100d3/' " +
"or 'tmr:///dev/ttyS0')\n\n" +
"Available commands:\n");
System.exit(1);
}
public static void setTrace(Reader r, String args[])
{
if (args[0].toLowerCase().equals("on"))
{
r.addTransportListener(r.simpleTransportListener);
}
}
static class TagReadListener implements ReadListener
{
public void tagRead(Reader r, TagReadData t) {
System.out.println("Tag Read " + t);
}
}
public static void main(String argv[])
{
System.out.println(argv.getClass().toString());
// Program setup
TagFilter target;
Reader r;
int nextarg;
boolean trace;
r = null;
target = null;
trace = false;
nextarg = 0;
if (argv.length < 1)
usage();
if (argv[nextarg].equals("-v"))
{
trace = true;
nextarg++;
System.out.println("Trace");
}
// Create Reader object, connecting to physical device
try
{
TagReadData[] tagReads;
r = Reader.create(argv[nextarg]);
if (trace)
{
setTrace(r, new String[] {"on"});
}
r.connect();
if (Reader.Region.UNSPEC == (Reader.Region)r.paramGet("/reader/region/id"))
{
r.paramSet("/reader/region/id", Reader.Region.NA);
}
r.addReadListener(new TagReadListener() );
// Read tags
tagReads = r.read(500);
// Print tag reads
for (TagReadData tr : tagReads)
System.out.println(tr.toString());
// Shut down reader
r.destroy();
}
catch (ReaderException re)
{
System.out.println("Reader Exception : " + re.getMessage());
}
catch (Exception re)
{
System.out.println("Exception : " + re.getMessage());
}
}
}
This is me trying to use it: (arg comes from a JTextField)
String[] argv = new String[1];
argv[0] = arg;
readOnceApp(argv);
I have a feeling there is a really simple answer to this problem, I just can't figure it out. I searched the internet for a few days and read books, and still can't figure it out. Any help is appreciated. Thank You.
edit: readOnceApp is one method I wrote. It is basically just the main method of the supplied code. I can include it, if it will help. I just didn't want to post too much code.

If you want to call the "main" method of a class from another class, do it like this:
String [] args = new String [1];
args[0]= "some param";
readOnceApp.main(args);
This is making the assumption that "readOnceApp" is the name of your class. (BTW, you should follow the convention of using capitalized class names, e.g. ReadOnceApp).
Hope this helps.

Related

How do I run speech recognizer before all other tasks in Java, in such a way that only if the output contains begin, the program continues

I have a login page and a sign up page in my program.
I want to run it only if the user says begin.
These pages are called in the main method of my class, and I have a speech recognizer class.
I want the program to continue only when String output.contains("begin") == true
I tried putting the Class.main(args) in my if(output.contains("begin") == true)) case, there was an unhandled exception, and when i surrounded that section with try and catch, it didn't work.
I was told that Inheriting and implementing the classes from my API will work, but I'm not quite sure how to do it.
final Microphone mic = new Microphone(FLACFileWriter.FLAC);
GSpeechDuplex duplex = new GSpeechDuplex("AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw");
duplex.setLanguage("en");
duplex.addResponseListener(new GSpeechResponseListener() {
String old_text = "";
public void onResponse(GoogleResponse gr) {
String output = gr.getResponse();
if (gr.getResponse() == null) {
this.old_text = response.getText();
if (this.old_text.contains("(")) {
this.old_text = this.old_text.substring(0,
this.old_text.indexOf('('));
}
System.out.println("Paragraph Line Added");
this.old_text = ( response.getText() + "\n" );
this.old_text = this.old_text.replace(")", "").replace("( ", "");
response.setText(this.old_text);
}
if (output.contains("(")) {
output = output.substring(0, output.indexOf('('));
}
if (!gr.getOtherPossibleResponses().isEmpty()) {
output = output + " (" + (String)
gr.getOtherPossibleResponses().get(0) + ")";
}
response.setText("");
response.append(this.old_text);
response.append(output);
System.out.println(output);
if(output.contains("begin") == true){
duplex.stopSpeechRecognition();
mic.close();
Trying_Different_Languages t = new Trying_Different_Languages();
frame.dispose();
}
}
});
Expect The program to begin when i say begin but
It it doesn't begin when I say begin.
The try and catch statements just help in error free compilation.
In a program there should exist only 1 public static void main(String[] args) method. That is the indicator which tells you there starts the program.
Instead of calling the main method you should add a different method which do the stuff you want at a specific point.
So in detail it can look like that:
public class SomeClass {
public static void someMethodName() {
//some stuff you want to execute
}
}
So and where you want to execute the code:
...
SomeClass.someMethodName(); //executes the stuff you want.
In this case it would work if you create different methods which do exactly that you need to do at a specific point.

Writing data to a txt file file using java classes

I am trying to understand why my code is not writing the output to the textfile as I expect it to work. My program takes a filename as a command line argument, and prints some text to the file as well as the screen. It is a bit more complicated since it uses classes and objects to demonstrate how objects work. Can anyone help decipher why it is not writing to the file? Here's my code:-
public class Mamoonp3test {
public static void main(String[] args) throws Exception {
//Create array of 10 guitar (Mamoonp3) objects
final int NUMBER_OF_INSTANCES = 10;
Mamoonp3[] objectNames = new Mamoonp3[NUMBER_OF_INSTANCES];
try
{
String fileName = new String(args[0]);
for(int i=0; i<NUMBER_OF_INSTANCES; i++) {
objectNames[i] = new Mamoonp3(FileName);
System.out.println("This is guitar number: " + i);
objectNames[i].tuneGuitar();
objectNames[i].playGuitar();
objectNames[i].displayAcronym();
objectNames[i].stopGuitar();
System.out.println("---------------------------");
}
}
catch (Exception e)
{
System.out.println("please provide an input file");
System.out.println("Usage: java Mamoonp3test filename.txt");
}
}
}
import java.io.*;
public class Mamoonp3 {
final int NUMBER_OF_STRINGS = 6;
char[] stringNames = {'E','A','D','G','B','E'};
int[] stringNumbers = {6,5,4,3,2,1};
String[] stringPitch = {"Sixth","Fifth","Fourth","Third","Second","First"};
boolean isTuned;
boolean isPlaying;
String stringAcronym = new String("Even After Dinner Giant Boys Eat");
//create a PrintWriter for output
PrintWriter output;
public Mamoonp3(String fileName) throws Exception{
isTuned = false;
isPlaying = false;
// create target file
File targetFile = new File(fileName);
//create a PrintWriter for output
output = new PrintWriter(targetFile);
}
public void tuneGuitar() {
System.out.println("The guitar is now tuned.");
for (int i=0; i<NUMBER_OF_STRINGS; i++) {
System.out.println(stringNames[i] + " is string number " + stringNumbers[i] + " and ranked " + stringPitch[i] + " in pitch");
output.print(stringNames[i] + " is string number " + stringNumbers[i] + " and ranked " + stringPitch[i] + " in pitch");
output.close();
}
}
public void playGuitar() {
System.out.println("The guitar is now playing.");
output.print("The guitar is now playing.");
output.close();
}
public void stopGuitar() {
System.out.println("The guitar is now stoped.");
output.print("The guitar is now stoped.");
output.close();
}
public void displayAcronym() {
System.out.println("Always remember your string names!");
System.out.println("Heres a reminder: " + stringAcronym);
output.print("Always remember your string names!");
output.print("Heres a reminder: " + stringAcronym);
output.close();
}
}
You're setting the File of an object that you then do nothing with, that you're not writing with,
Mamoonp3 newObject = new Mamoonp3(fileName);
... and not setting the File in objects that you try to write with. Check which constructors you are using: every Manoop3 object created in the for loop. To see that this is so, check which constructors you're using
I suggest that you change your approach entirely.
Get all file input and output out of your Mamoonp3 class.
Instead, that class should concern itself with representing the state of the musical instrument, and nothing else.
Give the class a decent toString() override method.
I & O should go elsewhere in a separate class of its own.
Give your I&O class a method that allows you to pass Mamoonp3 objects into it so that they can be written.
As an aside, you almost never would use new String(anything). Just use args[0].
Always close your PrintWriter when you are done writing. This is likely causing your error.
Edit
Possibly another way to solve this:
Create a PrintWriter object in the main method.
Give your Manoop3 class a PrintWriter field and a constructor that takes this PrintWriter and sets its field with it.
Write with the PrintWriter in Manoop3, but don't close it.
Then close the PrintWriter in the main method when all Manoop3 objects have completed their use of it.

How to compile C ar C++ codes in a java program in eclipse and do error logging?

I have to develop a program in java which takes a C or C++ file as input and compiles the file and gives the locations, positions, types of the errors found in the program. I am more concerned with the syntax errors. I need a way to do this in eclipse java. I have installed the Eclipse CDT plugin, and I don't know if I can call the compiler from inside a java program and get the line numbers, locations, positions.
I have tried installing a compiler namely the MinGW compiler and been able to print the errors but I am not getting the errors the way I want.
Here's a link of what I tried a link
Can someone help me out to capture the line numbers, positions of the syntax errors found in the C program in an array?
You have to parse the result from the stdout and from stderr. In the question you linked you can find solutions how to access them.
You also mentioned that you want to have a listener for compiler errors.
public interface CompilerErrorListener {
public void onSyntaxError(String filename, String functionName,
int lineNumber, int position, String message);
public void invalidOutputLine(String line);
}
You can implement this with any implementations:
public class CompilerErrorProcessor implements CompilerErrorListener {
public void onSyntaxError(String filename, String functionName,
int lineNumber, int position, String message) {
....
// your code here to process the errors, e.g. put them into an ArrayList
}
public void invalidOutputLine(String line) {
// your error handling here
}
}
So, let,s parse the compiler output! (note, that this depends on your compiler output, and you provided only 2 lines of output)
BufferedReader stdError = ...
String line;
CompilerErrorListener listener = new CompilerErrorProcessor(...);
String fileName = "";
String functionName = "";
int lineNumber = -1;
int position = -1;
String message = null;
while ((line = stdError.readLine()) != null) {
// the line always starts with "filename.c:"
String[] a1 = line.split(":", 2);
if (a1.length == 2) {
// a1[0] is the filename, a1[1] is the rest
if (! a1[0].equals(fileName)) {
// on new file
fileName = a1[0];
functionName = "";
}
// here is the compiler message
String msg = a1[1];
if (msg.startsWith("In ")) {
// "In function 'main':" - we cut the text between '-s
String[] a2 = msg.split("'");
if (a2.length == 3) {
functionName = a2[1];
} else {
listener.invalidOutputLine(line);
}
} else {
// "9:1: error: expected ';' before '}' token"
String[] a2 = msg.split(":", 3);
if (a2.length == 3) {
lineNumber = Integer.parseInt(a2[0]);
position = Integer.parseInt(a2[1]);
message = a2[2];
// Notify the listener about the error:
listener.onSyntaxError(filename, functionName, lineNumber, position, message);
} else {
listener.invalidOutputLine(line);
}
}
} else {
listener.invalidOutputLine(line);
}
}
This is not a complete example, of course, there may be many more possibilities, but hope that you got the idea. Don't forget to log the invalid/unprocessed branches.
Since you use a specific compiler, you have to adapt to its output. Also, changes in the compiler version may result in changes of the parsing code. Take an extra care to discover the structure of the output, it pays when you want to parse it.

Db4o API can't see dynamically loaded Classes in NetBeans?

I seem to be having what I believe is a ClassLoader problem using db4o with NetBeans. When I run the exact same code from the terminal with the same jar files from .../jre/lib/ext, everything works fine. The issue is that when I make a native query on some Classes that are loaded at runtime using a ClassLoader, I get an empty List from the database where I should definitely be getting a List with some elements (as I said, the same code works fine from the command line). I feel like this may be because the NetBeans ClassLoader works differently than the JVM ClassLoader, but I don't know, I'm certainly no expert on either. Here is the code from my main function.....
////////////////////////////////////////////////////////////////////////////////////////////
package gql;
import java.io.*;
import java.util.*;
import com.db4o.*;
public class GQL {
////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLES
////////////////////////////////////////////////////////////////////////////
private static ObjectSet dbObjects;
private static LinkedList classes = new LinkedList();
private static String dbPath, classPath;
private static ObjectContainer db;
private static ClassLoader coreClassLoader =
ClassLoader.getSystemClassLoader();
private static ClassLoader subClassLoader =
ClassLoader.getSystemClassLoader();
public static void main(String[] args) {
////////////////////////////////////////////////////////////////////////
// CREATE DATABASE OBJECT
////////////////////////////////////////////////////////////////////////
// If no path to a database is provided on the command line, print
// error and exit program
if (args.length < 1) {
System.err.println("\nError: no database path provided.\n");
return;
} else if (args.length > 1) {
dbPath = args[0];
// TODO - dubug command line classpath
classPath = args[1];
db = Db4o.openFile(dbPath);
} else { // We assume that the database Classes are stored somewhere
dbPath = args[0]; // along the CLASSPATH, and therefore classPath
classPath = ""; // can be left empty
db = Db4o.openFile(dbPath);
}
System.out.print("GQL> ");
// The prompt of the interpreter is within a do-while loop, which can
// be terminated by entering "exit"
do {
try {
/////////////////////////////////////////////////////////////////
// READ IN QUERY FILE
/////////////////////////////////////////////////////////////////
// We create a Scanner object to read tokens from the standard in
// stream - these will be our DLOG files provided by the user
Scanner fileScanner = new Scanner(System.in);
String GQLFile = fileScanner.next();
// Break loop and exit program if user enters "exit"
if (GQLFile.equalsIgnoreCase("exit")) {
break;
// If the user input is not preceeded by "#" and teminated with
// ";" then the input is invalid - the user is prompted again
} else if (!(GQLFile.substring(0,1).equals("#")) ||
!(GQLFile.substring(GQLFile.length()-1,
GQLFile.length()).equals(";"))) {
System.out.println("\nInvalid input.\nUsage: "
+ " #filename;\n");
System.out.print("GQL> ");
continue;
} else {
// Parse out the "#" and ";" from the user's input and send
// this to a file Reader object
GQLFile = GQLFile.substring(1,GQLFile.length()-1);
}
// Now we create a reader object and give it the user's parsed
// input - in the event of a FileNotFoundException, the user is
// prompted again
Reader reader;
try {
reader = new FileReader(GQLFile);
} catch (FileNotFoundException e) {
System.out.println("\nFile " + GQLFile +
" does not exist.\n");
System.out.print("GQL> ");
continue;
}
/////////////////////////////////////////////////////////////////
// PARSE QUERY
/////////////////////////////////////////////////////////////////
// The parser and Lexer objects are created in the parser.java
// and Lexer.java files, respectively - The parser takes the
// Lexer as an argument - the value variable generated by the
// parse() method will return the topmost grammar construct,
// which in this case is a Query object
parser p = new parser(new Lexer(reader));
Query query = (Query) p.parse().value;
/////////////////////////////////////////////////////////////////
System.out.println("\n----------------------------Input Query-----" +
"-----------------------\n");
System.out.println("\n SUCCESSFUL PARSE " +
" \n");
System.out.println("--------------------------------------" +
"------------------------------\n");
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// LOAD ALL CLASSES USED IN DATABASE INTO RUNTIME
/////////////////////////////////////////////////////////////////
// databse Classes should be kept on the CLASSPATH, or the path
// to these classes should be provided as a second command line
// argument
boolean coreClassesLoaded = loadCoreClasses(coreClassLoader,
classPath);
if (!coreClassesLoaded) {
System.err.println("\nError: one or more of core Classes"
+ "Node, Egge and SimplePath could not be found.\n");
db.close();
return;
}
//
System.out.println("Core classes loaded.\n");
boolean subclassesLoaded = query.loadSubclasses(subClassLoader,
classPath);
if (!subclassesLoaded) {
System.err.println("\nError: subclasses could not be" +
" loaded.\n");
db.close();
return;
}
//
System.out.println("Subclasses loaded.\n");
/////////////////////////////////////////////////////////////////
// MAKE SURE THE DATABASE ACTUALLY CONTAINS SOME OBJECTS AND,
// IF SO, PUT AN INSTANCE OF EACH CLASS REPRESENTED INTO THE
// LINKEDLIST CLASSLIST - SINCE WE LOADED THE DATABASE CLASSES
// INTO THE RUNTIME ENVIRONMENT, OBJECTS RETURNED BY DATABASE
// QUERIES WILL REMAIN TRUE TO THEIR TYPE; IF WE HADN'T DONE
// THIS, THESE OBJECTS WOULD BE RETURNED AS TYPE GENERICOBJECT
/////////////////////////////////////////////////////////////////
dbObjects = db.queryByExample(Object.class);
if (dbObjects.hasNext()) {
query.addClassesToList(dbObjects, classes);
} else {
System.err.println("\nError: no objects in database.\n");
db.close();
return;
}
//
System.out.println(classes);
/////////////////////////////////////////////////////////////////
// SEMANTIC CHECKS //
/////////////////////////////////////////////////////////////////
boolean headArgsAreSet = query.setHeadArgClasses(classes);
if (!headArgsAreSet) {
db.close();
return;
}
boolean typesMatch = query.checkQueryTypes(db);
if (!typesMatch) {
db.close();
return;
}
/////////////////////////////////////////////////////////////////
// EVALUATION
/////////////////////////////////////////////////////////////////
query.evaluateQuery(db);
} catch (Exception e) {
System.out.println("\nSYNTAX ERROR\n");
e.printStackTrace();
}
System.out.print("GQL> ");
} while (true);
System.out.println("\nExiting...\n");
db.close();
}
private static boolean loadCoreClasses(ClassLoader coreClassLoader,
String classPath) {
try {
coreClassLoader.loadClass("Node");
coreClassLoader.loadClass("Edge");
coreClassLoader.loadClass("SimplePath");
} catch (ClassNotFoundException cnfe) {
return false;
}
return true;
}
}
////////////////////////////////////////////////////////////////////////////////////////////
The strange thing is, the classes I need are definitely getting loaded into the runtime environment, as I use them to set some Class member variables, for example in the "SEMANTIC CHECKS" section. So it's like the application can see the dynamically loaded Classes, but the db4o API/database cannot. Also, I have the Class jar and the db4o jar set up as Netbeans libraries, not just in .../jre/lib/ext. Here's a snippet of the code in the Class where I actually use the db4o native query that's giving me problems...
////////////////////////////////////////////////////////////////////////////////////////////
public void evaluateQuery(ObjectContainer db) {
if (this.hasPredicate) {
;
} else {
if (this.isNode) {
List nodes = db.query(new Predicate() {
#Override
public boolean match(Node node) {
return (node.getName().equals("5"));
}
});
System.out.println("\n_________________RESULT__________________________");
System.out.println("\nNode: " + nodes.get(0).getName()
//+ ".\n");
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////
... if I do the following instead I still get an empty List...
////////////////////////////////////////////////////////////////////////////////////////////
public void evaluateQuery(ObjectContainer db) {
if (this.hasPredicate) {
;
} else {
if (this.isNode) {
List nodes = db.queryByExample(Node.class);
System.out.println(nodes.size());
for (int i = 0; i < nodes.size(); i++) {
System.out.println("\nNode: " + nodes.get(i).getName());
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////
Hmm, I don't see any dynamic class loading problems here. You're using the system's classloader, which should be visible to db4o. You don't even need to load the classes, db4o will do that with the classloaders.
Are you sure that the application picks up the same database? Are you using a relative path?
Btw you can explicitly set the classloader for db4o, like this.
EmbeddedConfiguration configuration = Db4oEmbedded.newConfiguration();
JdkLoader classLookUp = new ClassLoaderLookup(
Thread.currentThread().getContextClassLoader(),
new URLClassLoader(new URL[]{new URL("file://./some/other/location")}));
configuration.common().reflectWith(new JdkReflector(classLookUp));
ObjectContainer container = Db4oEmbedded.openFile(configuration,"database.db4o");
Well it seems like this is a bug in Linux/Netbeans for Linux/Db4o. I used the exact same source files on a windows box and everything worked fine. I'm pretty disappointed, I don't want to have to use windows for this project. :/

Writing Standard Input and waiting for Standard Output

I'm trying to create a Thread that keeps netsh windows command-line tool open so I can execute netsh commands without open it every single time.
The thing is, once I've created the Thread, just the first command call works... the subsequent calls seems to have no effect.
Here is my code:
public class NetshThread implements Runnable{
private static Process netshProcess = null;
private static BufferedInputStream netshInStream = null;
private static BufferedOutputStream netshOutStream = null;
public BufferedReader inPipe = null;
public void run(){
startNetsh();
}
public void startNetsh(){
try {
netshProcess = Runtime.getRuntime().exec("netsh");
netshInStream = new BufferedInputStream(netshProcess.getInputStream());
netshOutStream = new BufferedOutputStream(netshProcess.getOutputStream());
inPipe = new BufferedReader(new InputStreamReader(netshInStream));
} catch (IOException e) {
e.printStackTrace();
}
}
public void executeCommand(String command){
System.out.println("Executing: " + command);
try {
String str = "";
netshOutStream.write(command.getBytes());
netshOutStream.close();
while ((str = inPipe.readLine()) != null) {
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void closeNetsh(){
executeCommand("exit");
}
public static void main(String[] args){
NetshThread nthread = new NetshThread();
nthread.run();
String command = "int ip set address " +
"\"Local Area Connection 6\" static .69.69.69 255.255.255.0";
nthread.executeCommand(command);
command = "int ip set address " +
"\"Local Area Connection 6\" static 69.69.69.69 255.255.255.0";
nthread.executeCommand(command);
System.out.println("*** DONE ***");
}
}
Thank you!!! =)
Update 1:
Ok... I'm now using a PrintWriter instead... so I think I don't need to flush anything anymore, since the constructor is:
new PrintWriter(netshOutStream, true); (just like Mr. Shiny told me)...
Suppose I decide to break the while loop when the first output line is available... I doesn't work either... the next command wont be executed.... My code now looks like:
import java.io.*;
public class NetshThread implements Runnable{
private static Process netshProcess = null;
private static BufferedInputStream netshInStream = null;
private static BufferedOutputStream netshOutStream = null;
public BufferedReader inPipe = null;
private PrintWriter netshWriter = null;
public void run(){
startNetsh();
}
public void startNetsh(){
try {
netshProcess = Runtime.getRuntime().exec("netsh");
netshInStream = new BufferedInputStream(netshProcess.getInputStream());
netshOutStream = new BufferedOutputStream(netshProcess.getOutputStream());
netshWriter = new PrintWriter(netshOutStream, true);
inPipe = new BufferedReader(new InputStreamReader(netshInStream));
} catch (IOException e) {
e.printStackTrace();
}
}
public void executeCommand(String command){
System.out.println("Executing: " + command);
try {
String str = "";
netshWriter.println(command);
while ((str = inPipe.readLine()) != null) {
System.out.println(str);
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void closeNetsh(){
executeCommand("exit");
}
public static void main(String[] args){
NetshThread nthread = new NetshThread();
Thread xs = new Thread(nthread);
xs.run();
String command = "int ip set address " +
"\"Local Area Connection 6\" static .69.69.69 255.255.255.0";
nthread.executeCommand(command);
command = "int ip set address " +
"\"Local Area Connection 6\" static 69.69.69.69 255.255.255.0";
nthread.executeCommand(command);
System.out.println("*** DONE ***");
}
}
and the output I get:
Executing: int ip set address "Local
Area Connection 6" static .69.69.69
255.255.255.0 netsh>.69.69.69 is not an acceptable value for addr.
Executing: int ip set address "Local
Area Connection 6" static 69.69.69.69
Why the second command is not executed???
255.255.255.0
* DONE *
Update 2:
Everything seemed to work just fine until a teacher tried my app in a spanish-windows enviroment....
my code looks like this:
Scanner fi = new Scanner(netshProcess.getInputStream());
public void executeCommand(String command) {
System.out.println("Executing: " + command);
String str = "";
netshWriter.println(command);
fi.skip("\\s*");
str = fi.nextLine();
System.out.println(str);
}
and what i need is to somehow set the netshWriter encoding to the windows default.
Can anyone know who to do this?
You are closing the output stream.
You need to move the stream processing into separate threads. What's happening is that inPipe.readLine() is blocking waiting for netsh to return data. Apache has a package that deals with process handling. I'd look at using that instead of rolling your own (http://commons.apache.org/exec/)
This seems wrong in many ways.
First, why a Runnable object? This isn't ever passed to a Thread anywhere. The only thread you're creating isn't a java thread, it is an OS process created by exec().
Second, you need a way to know when netsh is done. Your loop that reads the output of netsh will just run forever because readLine will only return null when netsh closes its standard out (which is never, in your case). You need to look for some standard thing that netsh prints when it is done processing your request.
And as others mentioned, close is bad. Use a flush. And hope netsh uses a flush back to you...
I'd try:
PrintWriter netshWriter = new PrintWriter(netshOutputStream, true); // auto-flush writer
netshWriter.println(command);
No close()ing the stream, flush the stream automatically, and uses a writer to send character data rather than relying on the platforms "native character set".
You do definitely need to remove the close, else you'll never be able to execute another command. When you say "it won't work" once the close() call removed, do you mean no commands are processed?
Chances are that after you send the bytes for the command, you need to send some kind of confirmation key for the process to start, well, processing it. If you'd normally enter this from the keyboard it might be as simple as a carriage return, otherwise it might need to be a Ctrl-D or similar.
I'd try replacing the close() line with
netshOutStream.write('\n');
and see if that works. Depending on the software you might need to change the character(s) you send to signify the end of the command, but this general approach should see you through.
EDIT:
It would also be prudent to call
netshOutStream.flush();
after the above lines; without the flush there's no guarantee that your data will be written and in fact, since you're using a BufferedInputStream I'm 99% sure that nothing will be written until the stream is flushed. Hence why the code afterwards blocks, as you're waiting for a response while the process has not seen any input yet either and is waiting for you to send it some.
I've used scanner instead of BufferedReader, just because I like it. So this code works:
Scanner fi = new Scanner(netshProcess.getInputStream());
public void executeCommand(String command) {
System.out.println("Executing: " + command);
String str = "";
netshWriter.println(command);
fi.skip("\\s*");
str = fi.nextLine();
System.out.println(str);
}
It executes both commands.

Categories

Resources