Run fortran exe in java - java

Respected sir/madam,
I have a fortran exe which takes a input file and produces output file by doing some manipulation on input file.I am able to run the command in linux terminal.(I think fortran compiler is availble in linux).Now please suggest how to run this fortran executable file using java(in Linux machine).
What i attempted is,
String cmd="fortranExe arg1 arg2";
//fortranExe=exe path
//arg1,arg2 are arguments to fortran executable program
Process p=Runtime.getRuntime().exec(cmd);
But i am not getting output.When i tried to run Linux commands such as ls,dir are giving output.Is anything required for running fortran code in java?

Try using something like this
Process process = new ProcessBuilder("C:\\PathToExe\\fortran.exe","param1","param2").start();
Got this from
Java Programming: call an exe from Java and passing parameters
More info on ProcessBuilder: http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ProcessBuilder.html

No, if it's a reqular binary for the platform you are running your JVM on, it shouldn't matter.
How are you running the binary, when you run from console?
Once the process was generated successfully, you can read its stdout like this:
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = br.readLine()) != null)
{
System.out.println(line);
}
br.close();
If there was any runtime problem executing the process, e.g. no permission to run the binary etc., the process.exitValue() will return 127.
EDIT:
seeing the other comments, I can see that you are using redirected in/output to your binary.
So in fact there are no parameters, but you need to open InputFileName.txt and use the process.getOutputStream() Object to write to your process. No need to set OutputFilename.txt, because you read the output from the InputStream and if necessary can write it yourself to a file.
This answer explains it in detail:
https://stackoverflow.com/a/3644288/435583
https://stackoverflow.com/a/6796053/435583
Cheers,

Apart from using Runtime, a more cleaner way will be to use JNA. See specific example for Fortran here.
You can even call individual pieces like subroutines of your Fortan program directly from Java. JNA is generally used to invoke C/C++ programs and are generally suited for this type of use cases and I guess yours use case fits well here.

Related

System.getenv is not supported in Java 1.4. What is the alternative way?

I want to find the value of a particular env variable $ABC in Java code.
Since System.getenv("ABC"); is not an option on Java 1.4 what is the alternative for it?
Commentators of your question are 100% right. If it is possible in any way then upgrade your Java version. If it is not possible to upgrade and if your target environment is known to you, then you can for example execute a bash command and read the result. Something like this:
p = Runtime.getRuntime().exec("echo $" + yourEnvVariable);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
sb.append(line + "\n");
}
String variableValue = sb.toString();
But this is in no way a good practice since it is very dependent of operating system where the program is executed.
P.S
I have not tested if it actually works since I have nowhere to run Java 1.4.
A better idea is to create a wrapper script to launch your program, and have it put the values of specific environment variables into the JVM's system Properties object using -Dname=value parameters.
Obviously you would need to implement different wrappers for each OS family.
And, seriously, you should not be continuing to develop for / on Java 1.4. You are missing ~15 YEARS of security patches.

How to read python dictionary string in JAVA

I want to read python dictionary string using java. Example string:
{'name': u'Shivam', 'otherInfo': [[0], [1]], 'isMale': True}
This is not a valid JSON. I want it to convert into proper JSON using java code.
well, the best way would be to pass it through a python script that reads that data and outputs valid json:
>>> json.dumps(ast.literal_eval("{'name': u'Shivam', 'otherInfo': [[0], [1]], 'isMale': True}"))
'{"name": "Shivam", "otherInfo": [[0], [1]], "isMale": true}'
so you could create a script that only contains:
import json, ast; print(json.dumps(ast.literal_eval(sys.argv[1])))
then you can make it a python oneliner like so:
python -c "import sys, ast, json ; print(json.dumps(ast.literal_eval(sys.argv[1])))" "{'name': u'Shivam', 'otherInfo': [[0], [1]], 'isMale': True}"
that you can run from your shell, meaning you can run it from within java the same way:
String PythonData = "{'name': u'Shivam', 'otherInfo': [[0], [1]], 'isMale': True}";
String[] cmd = {
"python", "-c", "import sys, ast, json ; print(json.dumps(ast.literal_eval(sys.argv[1])))",
python_data
};
Runtime.getRuntime().exec(cmd);
and as output you'll have a proper JSON string.
This solution is the most reliable way I can think of, as it's going to parse safely any python syntax without issue (as it's using the python parser to do so), without opening a window for code injection.
But I wouldn't recommend using it, because you'd be spawning a python process for each string you parse, which would be a performance killer.
As an improvement on top of that first answer, you could use some jython to run that python code in the JVM for a bit more performance.
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.eval("to_json = lambda d: json.dumps(ast.literal_eval(d))")
PyObject ToJson = interpreter.get("to_json");
PyObject result = ToJson.__call__(new PyString(PythonData));
String realResult = (String) result.__tojava__(String.class);
The above is untested (so it's likely to fail and spawn dragons 👹) and I'm pretty sure you can make it more elegant. It's loosely adapted from this answer. I'll leave up to you as an exercise to see how you can include the jython environment in your Java runtime ☺.
P.S.: Another solution would be to try and fix every pattern you can think of using a gigantic regexp or multiple ones. But even if on simpler cases that might work, I would advise against that, because regex is the wrong tool for the job, as it won't be expressive enough and you'll never be comprehensive. It's only a good way to plant a seed for a bug that'll kill you at some point in the future.
P.S.2: Whenever you need to parse code from an external source, always make sure that data is sanitized and safe. Never forget about little bobby tables
In conjunction to the other answer: it is straight forward to simply invoke that python one-liner statement to "translate" a python-dict-string into a standard JSON string.
But doing a new Process for each row in your database might turn into a performance killer quickly.
Thus there are two options that you should consider on top of that:
establish some small "python server" that keeps running; its only job is to do that translation for JVMs that can connect to it
you can look into jython. Meaning: simply enable your JVM to run python code. In other words: instead of writing your own python-dict-string parser; you simply add "python powers" to your JVM; and rely on existing components to that translation for you.

How do I pass an arg to convert between numbers and strings

I am reading through the java tutorials, and I don't understand when it says
"The following is the output from the program when you use 4.5 and 87.2 for the command-line arguments:"
What I mean is how do I pass the values to the program. A piece of the code is this.
float a = (Float.valueOf(args[0])).floatValue();
float b = (Float.valueOf(args[1])).floatValue();
I have tried changing "args[0]" to "4.5" and "args[1]" to "87.2" which are the given values from this page.
https://docs.oracle.com/javase/tutorial/java/data/converting.html
Upon doing so I receive "requires two command-line arguments." which is the else part of the code. I'm pretty sure I am being oblivious to this. I have tried looking for anything regarding passing arguments but i can't find exactly what to do.
I have also tried creating two "string" values named one and two with the same values as above and inputting the string name into the args positions but still received the same outcome.
Is it something simple such as requesting an input from the user or should I manually put the values in there and if I need to add the values into the argument then how would I go about doing so.
The arguments passed to the main methods are the one typed when starting your java application from command line. An revelant example for your case would be :
java YourProgram 4.5 87.2
Then you will be able to access them from args[0] and args[1] as explained in the tutorial.
For more examples read the Command-Line arguments part of the java tutorial.
If you're running the program from a command line (typing something like java ValueOfDemo into a terminal), you would type java ValueOfDemo 4.5 87.2 to pass 4.5 and 87.2 as the first and second arguments, respectively. If you're running the program using an IDE such as Eclipse or NetBeans, search for that program's documentation on how to pass command line arguments to the program.
In general, command line arguments are arguments that are passed to the program you're running when the program is started. You can also ask the user for input while your program is running, but you would explicitly write code to do so and accept the value.
See this page for more information: https://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html
Open cmd(window key + r) and compile by command: javac yourClass.java and then execute by command: java yourClass 4.5 87.2 you will see result

Communicating with Jython/Java from Python (Subprocess)

My problem is somewhat similar to this question.
I try to communicate from Python with a Jython program (that needs to keep running because it communicates with a Java API).
However, i can't get the output in realtime, whatever i try:
p2=Popen([path_jython],stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False)
p2.stdin.write('test="hallo"\n')
p2.stdin.write('print test\n')
p2.stdin.flush()
for line in p2.stdout:
print line
Nothing happens, the program blocks. It doesn't change when i iterate over p2.stdout.readlines() or iter(md5.stdout.readline, '') or when I repeatedly call p2.stdout.read(1) like suggested in the linked question.
If i add print p2.communicate() after the flush() however, i get the desired output:
>>> ('hallo\r\n', '\r\n')
but the program terminates afterwards...
Does anyone have a solution for this problem? Or are there alternatives to communicate effectively with a running Jython process? Happy for any advice!
EDIT: Python 2.7.5, Jython 2.7.1b
try to make jython stdout/stderr unbuffered, pass -u command-line argument
if you set stderr=PIPE then you should read it, otherwise a deadlock may occur if the child process fills the OS pipe buffer corresponding to its stderr. You could redirect it to stdout: stderr=STDOUT
set Python side buffering explicitely: bufsize=1 (line-buffered)
use iter(p.stdout.readline, '') to avoid read-ahead bug on Python 2
from subprocess import Popen, PIPE, STDOUT
p = Popen(['jython', '-u', ...], stdin=PIPE, stdout=PIPE, stderr=STDOUT,
bufsize=1)
print >>p.stdin, 'test="hallo"' #NOTE: it uses `os.linesep`
print >>p.stdin, 'print test'
p.stdin.close() # + implicit .flush()
for line in iter(p.stdout.readline, ''):
print line, #NOTE: comma -- softspace hack to avoid duplicate newlines
p.stdout.close()
rc = p.wait()

How to make Windows file associations work with non-ASCII file names?

I need to register the file association for a certain file type - in fact, I just need to launch a certain Java program with certain arguments and a name of that file.
I got as far as the following:
// in fff-assoc.cmd file:
assoc .fff=SomeFile
ftype SomeFile=java -jar some.jar <arguments1> "%%1" <arguments2>
It works properly for ASCII file names. But when I try to double-click some file with non-ASCII symbols in name, the argument passed looks like "????" (int value of each char = 63).
How can I fix those associations?
If what bobince says is accurate and you cannot reliably get the data to java directly, one alternative solution would be to write a small "shim" program in another language (e.g. C, C++ or C#).
The idea is that the program grabs the input as UNICODE, encodes it so that it's expressible using only ASCII characters (e.g. by using base64, or even something as simple as encoding every character as its numerical equivalent) and then assembles the command line argument to use and launches java itself using CreateProcess.
Your Java code could "undo" the encoding, reconstructing the UNICODE name and proceeding to use it. It's a bit of a roundabout way and requires an extra component for your software, but it should work around the restriction detailed above, if indeed that is an actual restriction.
Update: This is the basic code for the shim program. It encodes input as a sequence of integers, separated by colons. It doesn't do much in the way of error checking and you might want to improve it slightly, but it should at least get you started and going in the right direction.
You should grab Visual Studio Express (if you don't already have Visual Studio) and create a new Visual C++ project, choose "Win32" and select "Win32 Project". Choose "Win32 application". After the project is created, replace everything in the .cpp file that is displayed with this code:
#include "stdafx.h"
#include <string>
int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR lpCmdLine, int)
{
std::string filename;
while((lpCmdLine != NULL) && (*lpCmdLine != 0))
{
if(filename.length() != 0)
filename.append(":");
char buf[32];
sprintf(buf, "%u", (unsigned int)(*lpCmdLine++));
filename.append(buf);
}
if(filename.length() == 0)
return 0;
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
STARTUPINFOA si;
memset(&si, 0, sizeof(STARTUPINFOA));
si.cb = sizeof(STARTUPINFOA);
char *buf = new char[filename.length() + 256]; // ensure that 256 is enough for your extra arguments!
sprintf(buf, "java.exe -jar some.jar <arguments1> \"%s\" <arguments2>", filename.c_str());
// CHECKME: You hard-coded the path for java.exe here. While that may work on your system
// is it guaranteed that it will work on every system?
if(CreateProcessA("C:\\Program Files\\Java\\jre7\\bin\\java.exe", buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
delete[] buf;
return 0;
}
You should be able to figure the details on how to compile and so on fairly easily.
I just need to launch a certain Java program with certain arguments and a name of that file.
Unfortunately this 'just' is not actually possible, due to the MS implementation of the standard C library that Java uses to receive argument input (amongst other things). Unless you go straight to the native Win32 API, bypassing standard Java or C interfaces,
See this question for background.
When calling java from the command line, you can specify the encoding of the parameters (which will be used to create the strings in args[]):
java -jar -Dsun.jnu.encoding=cp1252 yourFileName
When using non-ASCII characters, the specified charset has an impact on the value of args[0]. Not sure if that would apply to file associations though.
Note: I'm not sure what other uses that parameter has - this post seems to say none.

Categories

Resources