I have this input stream that checks if I have a certain CAD file open or not. I am doing this by using an input stream to run a tasklist command with the name I want to check. I currently have a boolean that returns true if the specific CAD file isn't open. If the CAD file is open, it returns false. However, I want it to be able to loop this until the CAD file is open because as of right now I have to keep running it in order for it to work. I also need to be able to check this boolean from a separate class. I have it in my main right now so i could test it. My code looks like this...
public class AutoCadCheck {
public static void main(String[] argv) throws Exception {
String notOpen = "INFO: No tasks are running which match the specified criteria";
StringBuilder textBuilder = new StringBuilder();
String command = "tasklist /fi \"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]";
int i;
InputStream myStream = Runtime.getRuntime().exec(command).getInputStream();
while ((i = myStream.read()) != -1) {
textBuilder.append((char) i);
}
String output = textBuilder.toString();
boolean logical = output.contains(notOpen);
if (logical) {
System.out.println("DWG Not Open");
} else {
System.out.print(output);
}
myStream.close();
}
}
My other class is going to have an 'if statement' that checks whether my boolean "logical" is false, and if so, print something. I have tried every possible method I could think of, but I cannot get it to function the way I want it to. Every other thing I found involving looping an inputstream didn't really apply to my situation. So hopefully someone can help me out in achieving what I want to do.
I would start by moving everything out of main and into a different class. This will make retrieving values and calling specific functions easier. Then create an object of that class in main. Once that is done, I'd create a get method for the boolean variable. Now to focus on the loop. Once the object is created in main, create a conditional loop inside of main which calls the function you need until a different condition is met. This condition might be met once the file is open. After the condition is met, it exits to another loop that relies on another conditional, such as user input.
public class AutoCadCheck {
public static void main(String[] argv) throws Exception {
AutoCadFile file = new AutoCadFile();
//loop 1
//Some conditional so the program will
//continue to run after the file has been found.
// while(){
//loop 2
//check to see if the file is open or not
//while(logical){
//}
//}
}
}
Other class
import java.io.IOException;
import java.io.InputStream;
public class AutoCadFile {
private String notOpen;
private StringBuilder textBuilder;
private String command;
private int i;
private InputStream myStream;
private String output;
private boolean logical;
public AutoCadFile() {
notOpen = "INFO: No tasks are running which match the specified criteria";
textBuilder = new StringBuilder();
command = "tasklist /fi \"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]";
output = textBuilder.toString();
logical = output.contains(notOpen);
try {
myStream = Runtime.getRuntime().exec(command).getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
public void checkForFileOpen() {
try {
while ((i = myStream.read()) != -1) {
textBuilder.append((char) i);
}
if (logical) {
System.out.println("DWG Not Open");
} else {
System.out.print(output);
}
myStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean getFileBoolean() {
return logical;
}
}
My other class is going to have an if statement that checks whether my boolean logical is false ...
Well, logical is a local variable within a method. So no code in another class is going to be able to see it.
There are two common approaches to this kind of thing:
Make the variable (i.e. logical) a field of the relevant class. (Preferably NOT a static field because that leads to other problems.)
Put your code into a method that returns the value you are assigning to logical as a result.
From a design perspective the second approach is preferable ... because it reduces coupling relative to the first. But if your application is tiny, that hardly matters.
I can see a couple of other significant problems with your code.
When you use exec(String), you are relying on the exec method to split the command string into a command name and arguments. Unfortunately, exec does not understand the (OS / shell / whatever specific) rules for quoting, etcetera in commands. So it will make a mess of your quoted string. You need to do the splitting yourself; i.e something like this:
String[] command = new String{} {
"tasklist",
"/fi",
"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]"
};
Your code potentially leaks an input stream. You should use a "try with resource" to avoid that; e.g.
try (InputStream myStream = Runtime.getRuntime().exec(command).getInputStream()) {
// do stuff
} // the stream is closed automatically ... always
Related
I am designing a controller using the command pattern.
The controller has a while loop inside that is scanning for user input. If user input matches a specific String, then a command class is executed. Here is a code snippit:
public Controller(Readable in, Appendable out) {
this.out = out;
this.scan = new Scanner(in);
this.commandMap = this.generateCommands();
}
public void go(Model m) {
while (scan.hasNext()) {
String input = scan.next();
Command command = this.commandMap.get(input);
command.do(m);
}
}
I usually use return to stop the application. However, when I use return inside one of the Command classes, the application keeps running. I think it just goes back to this upper loop.
By the way, all my commands are public void.
Is there a way to exit/close the application from within the command classes? Like a "super" return? Or do I need to no longer make them void and if/else the return in the controller.
EDIT: system.exit(0) doesn't seem like the right solution for me because it doesn't preserve the appendable log? My JUnit tests no longer print out everything I have appended once system.exit(0) is called.
Use this to terminate the entire program:
System.exit(0);
I Have a question abouth the code for handling erros made by the user.
So the thing is, I need my user to add a name of a program, to add the memory that program takes in the RAM and to add the time he will have that program open.
I need to add in my code defensive programming, so I thought maybe I could do it by checking if the user actually add the type of the variables that the program need, or if it didn't.
Either way I am confused on how to use the try and catch blocks, for now this is what I have...
System.out.println("add program Id");
String programID = scan.next();
try{
String check;
check = programID;
}catch(Exception e){
System.out.println("add a value of String type");
}
That doesn't work.
anything you can type is a string. I can type '5'. That's a string. You may think it is a number, but this entire block of text is a String, and '5' is in it.
No text is a string too. String x = ""; compiles fine.
Thus, no exception would ever occur here, and it's not clear what scenario you are trying to detect.
Perhaps a programID is of the form: "one capital letter (and only english capitals, not Ü for example), and then up to 3 different digits". For example, 'Z5' or 'Y495'.
You'd need to write code to detect this, no need for try/catch. For example, regular expressions:
private static final Pattern PROGRAM_ID_PATTERN = Pattern.compile("^[A-Z]\\d{1,3}$");
public static void main(String[] args) {
....
String programId;
do {
programId = scanner.next();
if (!PROGRAM_ID_PATTERN.matcher(programId).matches()) {
System.err.println("Enter a valid program ID, e.g. A123");
} else {
break;
}
} while (true);
}
Exceptions are for when a method has multiple different ways to exit.
For example, imagine this method:
byte[] contentsOfFile = Files.readFileFully("myfile.txt");
The readFileFully method seems simple: You provide the name of a file, and it returns a byte array with its contents.
However, that's just one way that could go. What if the file doesn't exist? What if the file exists, but your process doesn't have read access rights? What if the disk is failing or it's a removable drive and it's yanked out halfway through reading it?
These somewhat predictable potential alternate ways out are generally done by exceptions. That method would be throwing FileNotFoundException, noReadAccessException, and more generally IOException, for example.
There's no 'that is not a string' variant of scanner.next().
There is scanner.next(Pattern) which you could use:
private static final Pattern PROGRAM_ID_PATTERN = Pattern.compile("^[A-Z]\\d{1,3}$");
public static void main(String[] args) {
....
String programId;
do {
try {
programId = scanner.next(PROGRAM_ID_PATTERN);
break;
} catch (NoSuchElementException e) {
System.err.println("Enter a valid program ID, e.g. A123");
}
} while (true);
}
The javadoc generally explains what exceptions can occur; if a method doesn't mention any, you're not supposed to try/catch there.
This is just for a simple command-line standalone program in Java.
I'd like to open a file to write to, and keep it open. I need to write formatted floats/doubles to it, in human-readable ASCII, like a CSV file.
I have tried various approaches (1) (2) (3) I have found through my favorite search engine, and they have the form:
try {
// some file handle opening sequence
}
catch ( <some exception> ) {
// do something
}
finally {
// do something else
}
(...or in the case of the third example, the file opening/writing/closing is inside a function that throws an exception.) I realize it's good programming style to make sure that you've opened a file ok, but for my purposes that's really not necessary.
Anyway the problem with the above approach is that outside of the try{} block, the filehandle is closed. I'd like to keep it open, because the kernel of my code consists of a huge loop that I go through a few 100,000 times (say), and each time through I'd like to output a single float (in ASCII) to the file.
With the above form, the only way to do that is to enclose my huge for loop inside the try{} block. Which seems silly. Alternatively, I could re-open the file every time through the loop, but that means additional logic, opening the file as a 'new' file the first time, and appending in all subsequent times.
Is there some way to open the file, keep it open to write to it occasionally, and then close it when I'm done?
Something like:
{
// open file "data.out"
}
for (i=0;i<100000;i++) {
// do a lot of stuff
//
// calculate some quantity "x"
//
// output float "x" in ASCII form, appending it to data.out
}
{
// close data.out
}
Does Java allow that? Thanks.
Of course you can simple store your FileWriter somewhere, as any other variable. You can, for example, encapsulate the whole writing logic in its own class, which offers one write method for your specified format.
But why does it seem silly? Perhaps this approach might help...
public void methodA(File myFile) throws IOException{
try ( FileWriter writer = new FileWriter( myFile ) ) {
writeTo(writer);
}
}
private void writeTo(FileWriter writer) throws IOException {
for (i=0;i<100000;i++) {
// do a lot of stuff
//
// calculate some quantity "x"
//
// output float "x" in ASCII form, appending it to data.out
}
}
This way, one method takes care of the opening/closing/exceptions, while the other method can concentrate on the important writing stuff, using the FileWriter given to it.
as you said the file is closed at the end of the try block. Possibly
the FileWriter object is created inside the try block:
(You did not post a real java code, only a pseudo code.)
Example, hope this helps
public static void main(String[] args)
{
...
BufferedWriter ofs=null; // should by outside the try block
try
{
Path logfile = Paths.set("C:\\temp\\log.log");
ofs = Files.newBufferedWriter(logfile); // new in java 8
YourWorker.doYourJob(ofs);
} catch (Exception e)
{ e.printStackTrace();
} finally
{
if (ofs!=null) { try { ofs.close(); } catch (Exception e) {} }
}
System.exit(1);
} //---------- end of main()
} //---- end of class
I am sitting with a little problem here, and i has been searching for hours for any soultion now, but cant seem to find any, and i hope you can help me.
I have these methods:
public String getInput(){
//Wait here somehow
return "Whatever to return";
}
public void keyTrigger(KeyEvent event){
if(event.getCode().equals(KeyCode.ENTER)){
String[] getInput = gameLog.getText().split("\n");
input = getInput[getInput.length - 1]; //Input is a variable in the class
//Tell the getInput() to continue from where i waited
}
}
So if anyone can tell me how the make the first method wait for a response from the other method, i woul be very happy, because none i have tried so far has worked
EDIT...
Sorry guys, i have missed out on some details.
1st: I am developing a GUI in JavaFX, and the gameLog variable is a textarea, and thats why im splitting the String on linebreaks.
2nd: when i call getInput() i want it to wait for the user to press enter, then get the input variable
Your immediate request would be satisfied by a CompletableFuture:
public String getInput(){
final CompletableFuture<String> fut = new CompletableFuture<>();
commonFuture = fut;
return fut.join();
}
In the above, you need to provide a variable commonFuture which is accessible both from the above code and from your KeyEvent listener, and will serve as the point of contact between these two pieces of code. In the listener you would say
commonFuture.complete(getInput[getInput.length - 1]);
and at that point the join call in getInput() would complete, returning this value.
However, I urge you to seriously think through your current design, which demands such synchronous blocking. You may be able to rework so that getInput is replaced by a callback method which gets invoked when the input value is available.
I don't really understand your issue here, from common logic I guess your getInput() should read from command line and return the value as String. You don't need to write any special code for it, for reading from command line you should use BufferedReader, see the example below.
public String getInput(){
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
try{
line = reader.readLine();
}catch(IOException e){
e.printStackTrace();
}
return line;
}
Also this part of your code, input = getInput[getInput.length - 1]; I don't see a point of getInput.length - 1 because getInput() will return a whole string so you don't need to trim it unless you explicitly want to do it. So you can just write input = getInput();, with assumption that variable input is of type String.
Instead of trying to block until the variable changes, you should use a StringProperty and register listeners with it.
Here's some skeleton code:
private final StringProperty input = new SimpleStringProperty();
public StringProperty inputProperty() {
return input ;
}
public final String getInput() {
return inputProperty().get();
}
public final void setInput(String input) {
inputProperty().set(input);
}
// event handler (I'm assuming):
public void keyTrigger(KeyEvent event){
if(event.getCode().equals(KeyCode.ENTER)){
String[] getInput = gameLog.getText().split("\n");
inputProperty().set(getInput[getInput.length - 1]);
}
}
Now you can have code execute when the input is changed:
inputProperty().addListener((obs, oldInput, newInput) -> {
// newInput contains the new value set to the input property....
});
The Properties and Bindings tutorial has more details on using JavaFX properties.
I have a class like this
public class StockCodes
{
public static boolean loaded = false;
public static long lastUpdate = 0;
private static long freq = 1000 * 60 * 60 * 24;
public static HashMap<String, Stock> stockMap = new HashMap<String, Stock>();
public static ArrayList<Stock> getCodes()
{
long now = System.currentTimeMillis();
if ((StockCodes.loaded) && ((now - StockCodes.lastUpdate) < freq))
{
System.out.println(StockCodes.loaded);
return stockList;
}
else
{
HttpFetcher fetcher = new HttpFetcher();
....
log.info("Load " + stockList.size() + " Stocks");
StockCodes.loaded = true;
StockCodes.lastUpdate = now;
return stockList;
}
}
public static void main(String[] args)
{
StockCodes.getCodes();
}
}
When I run the java application , it outputs "true". Telling us the stockcodes have loaded.
But when i debug the java appliction, it goes into the else. I do not understand why it runs in this way, especially why it outputs "true" the first time i run the application. Could someone else give me some help ,thank you ~
With the code given above, the control by default should always go in the else block and print nothing. You can verify it.
Not if you have some more places where you call the getCodes() method, then it will differ. Having said this, please verify if there is no other place with a call to getCodes(). ie its invoked single time via main()
The getCodes() function essentially caches the result if the function has been run more than once. The first getCodes() will not print "true", but all subsequent calls will
Run from the command line
public static void main(String[] args)
{
StockCodes.getCodes();
}
this should output nothing to STDOUT.
Your if statement is clean. When I have one of these type of mistakes I go the old fashion route. I put a series of
System.out.println
statements in that section of the code to track where you code is going when it not in debug mode. It is clunky but it works.
When I run your code it goes through the else whether I run in debug mode or regular.
I think you lost a line of your code. Did you have
System.out.println(StockCodes.loaded);
in your else branch also? If you did, and you had it located below your line StockCodes.loaded = true; then it will be printing true for you.
I suggest you use more detailed debugging, something like System.out.println("In the if branch"); and below that in the else branch, a line like System.out.println("In the else branch"); I think you are tricking yourself by having too little output.