Can File handle environment variables? - java

I have the following code in Java:
String path = "$ENV_PATH";
final File f = new File(path);
System.out.println(path);
if (f.isDirectory()) {
System.out.println("A dir");
} else {
System.out.println("Not a dir");
}
If the environment variable is set and points to an actual directory, I get the following output:
$ENV_PATH
/actual/path/of/the/env/: Permission denied
Not a dir
Does File know how to handle environment variables? If not, what is a good alternative for that or how should I handle it? Please note that path can be non-env string. Also I would like to support paths like /some/valid/path/$SUB/to/dir.
EDIT: I understand that File does not support envs. What is the proper way to fix it?

So how should I solve it? I can check if it contains $ in the path and then do getenv but it feels ugly because I will have to check the full string (to support /some/path/$SUB1/and/$SUB2/) Is there a proper way for that?
There is no "proper" way to do this. Basically /some/path/$SUB1/and/$SUB2/ is "shell" syntax and Java does not support it.
I can think of three ways to do this:
Get a shell to deal with is; e.g. run sh -c "echo /some/path/$SUB1/and/$SUB2/" in a subshell and capture the output. (This is very inefficient, but this approach also allows you to so shell wild-card expansion, interpolate the output of shell commands and so on.)
Write a simple parser that understands the syntax that you are using, and use it to interpolate the environment variables (or properties or whatever) into the string.
Some of the answers to Expand environment variables in text take this approach.
Look for a third party Java library that does what you want. One possibility is the StrSubstitutor class in the Apache Commons library: javadoc

Related

Expect Programming: How to expect exactly what is prompted?

I am asking this question particularly for an Expect implementation in Java. However, I would like to know general suggestions as well.
In Expect programming, is it possible to expect exactly what is prompted after spawning a new process?
For example, instead of expecting some pattern or a fixed string, isn't it better to just expect what is prompted. I feel this should be really helpful at times(especially when there's no conditional sending).
Consider the sample java code here that uses JSch and Expect4j java libraries to do ssh and execute list of commands(ls,pwd,mkdir testdir) on the remote machine.
My question here is why is it necessary to specify a pattern for the prompt? Is it not possible it to get the exact prompt from Channel itself and expect it?
I've programmed in "expect" and in "java".
I think you misunderstand what "expect" basically does. It doesn't look for exact items prompted after spawning a new process.
An expect program basically consists of:
Something that reads the terminal
A set of patterns (typically regular expressions), coupled to a blocks of code.
So, when a new process is spawned, there's a loop that looks something like this
while (terminal.hasMoreText()) {
buffered_text += terminal.readInput();
for (Pattern pattern : patterns) {
if (pattern.matches(buffered_text)) {
String match = pattern.getMatch(buffered_text);
bufferedText.removeAllTextBefore(match);
bufferedText.removeText(match);
pattern.executeBlock();
}
}
}
Of course, this is a massive generalization. But it is close enough to illustrate that expect itself doesn't "exactly expect" anything after launching a process. The program provided to the expect interpreter (which primarily consists of patterns and blocks of code to execute when the patterns match) contains the items which the interpreter's loop will use to match the process's output.
This is why you see some pretty odd expect scripts. For example, nearly everyone "expects" "ogin:" instead of "Login:" because there's little consistency on whether the login prompt is upper or lower case.
You don't have to expect anything. You're free to just send commands immediately and indiscriminately.
It's considered good practice to only reply to specific prompts so that you don't accidentally ruin something by saying the wrong thing at the wrong time, but you're entirely free to ignore this.
The main consideration is that while your normal flow might be:
$ create-backup
$ mkdir latest
$ mv backup.tar.gz latest
With no expectations and just blindly writing input, you can end up with this:
$ create-backup
Disk full, cleanup started...
Largest file: precious-family-memories.tar (510MB)
[R]emove, [S]ave, [A]bort
Invalid input: m
Invalid input: k
Invalid input: d
Invalid input: i
Removing file...
$ latest
latest: command not found
$ mv backup.tar.gz latest
whereas a program that expects $ before continuing would just wait and eventually realize that things are not going according to plan.
A few commands are sensitive to timing (e.g. telnet), but other than that you can send commands whenever you want, with or without waiting for anything at all.

How to stringify in Java

In c++ we could use macro as
#define check_and_log_warning(x) if (!(x)) {log_error(#x); cout<<__LINE__;}
I want to get values of a boolean expression and also use it as a string.
Getting the line number inside macro would be added benefit.
Can something like this macro be written in Java ?
I recently moved from c/c++ to java, so I am wondering could such thing be done in c++ without macro ?
Preprocessor is what I miss from C/C++ in Java. There are ways ..., but they are Java ways.
1/ Assertions:
http://docs.oracle.com/javase/7/docs/technotes/guides/language/assert.html
2/ Logs:
The one that I use is https://commons.apache.org/proper/commons-logging/
(over log4J or whatever you want)
To print line numbers in log messages, you can use something like:
int lineNo = Thread.currentThread().getStackTrace()[2].getLineNumber();
Edit:
Be warned: unlike __LINE__ in C++ getting the stack trace incurs a performance penalty. Be nice :)
There is no macro facility in Java.
You would be using a logging framework (of which there are plenty to choose from).
if (! theActualConditionNotJustX) myLogger.error("describe problem here");
The logging backend (if configured that way) makes sure to capture and display line numbers. There is some runtime cost for this, but it is usually negligable, especially where actual "errors" are involved (it can get a bit costly for trace-level logging).

Using libsvm in Java for String classification

Looking around I was not able to find a good way to use libsvm with Java and I still have some open questions:
1) It is possible to use only libsvm or I have to use also weka? If any, what's the difference?
2) When using String type data how can I pass the training set as Strings? I was using matlab for a similar problem for proteins classification and there I just gave the strings to the machine without problem. Is there a way to do this in Java?
Here is an incomplete example of what I did in matlab (it works):
[~,posTrain] = fastaread('dataset/1.25.1.3_d1ilk__.pos-train.seq');
[~,posTest] = fastaread('dataset/1.25.1.3_d1ilk__.pos-test.seq');
trainKernel = spectrumKernel(trainData,k);
testKernel = spectrumKernel(testData,k);
trainKf =[(1:length(trainData))', trainKernel];
testKf = [(1:length(testData))', testKernel];
disp('custom');
model = libsvmtrain(trainLabel,trainKf,'-t 4');
[~, accuracy, ~] = libsvmpredict(testLabel,testKf,model)
As you can see I read the file in fasta format and feed them to libsvm but libsvm for java look like it wants something called Node that is made of double. What I did is to take byte[] from the String and then transform them into Double. Is it correct?
3) How to use a custom kernel? I've found this line of code
KernelManager.setCustomKernel(custom_kernel);
but with my libsvm.jar I don't find. Which lib do I have to use?
Sorry for the multiple questions, I hope you will give me a brief overview of what is going on here.
Thanks.
Please note that I've used LIBSVM for MATLAB, but not for Java. I can only really answer question 1, but hopefully this still helps:
It definitely is possible to use libsvm only, and the code is located here: https://www.csie.ntu.edu.tw/~cjlin/libsvm/. Note that jlibsvm is a port of libsvm, and it seems to be easier to use and more optimized for Java. As far as I can tell, weka just has a wrapper class that runs libsvm anyways (it even requires the libsvm.jar), though I mainly based it off of this: https://weka.wikispaces.com/LibSVM.

How to check Directory exits with proper case in java

I want to copy one folder to another location in java,
but when I use
File f = new File(userInputFilePath);
and checks
if(f.isDirectory())
it returns true.
For example for the userInputPath as "C:\To\TesT" while the directory path is "C:\to\Test".
Please suggest me ASAP
On Windows systems the case of filenames is irrelevant; try renaming the directory from Test to TesT and you'll see what I mean. You can of course go against this manually by comparing Strings (something like f.getPath().equals(userInputFilePath) && f.isDirectory()) but that's not necessarily a good idea as most programs will not differentiate between the two and this could cause unexpected behavior.

Multiple File Type Parser

this is my first post here. I'm excited to finally take part.
I'm working on a project where I'm parsing obscure files types. I need to be able to parse word (which I've already done), .sbs, .day, .cmp, and more. All of these types can be opened simply with notepad and displayed.
Since I'm so new to this stuff, is there a way I can use some generic library (or two) to open all of these up? And if so what library would it be?
What's a best practice in this sort of circumstance?
Thanks!
You could use the Apache Commons IO library. FileUtils class has several methods that receives the file path and optionlly the file encoding.
If you just want to only read text files and save them to a text variable
java.io.File file = new java.io.File("C:\\dir\\file.cmp");
String allWordAndLines = org.apache.commons.io.FileUtils.readFileToString(file);
If you want each line separately and store them in a collection:
java.util.List<String> lines = org.apache.commons.io.FileUtils.readLines(file);
for(String line : lines) {
// do something with line
}
To specify the encoding, you need to add another parameter:
org.apache.commons.io.FileUtils.readFileToString(file, "UTF-8");
org.apache.commons.io.FileUtils.readLines(file, "Cp1252");
Java include several classes for read files, see more in http://docs.oracle.com/javase/tutorial/essential/io/index.html
I hope this can help you if you are looking for only to have your text file is available in memory.

Categories