Can javac compile from stdin?
Something like this :
cat myfile | javac
No, there is no option to do that.
From the documentation:
There are two ways to pass source code file names to javac:
For a small number of source files, simply list the file names on the command line.
For a large number of source files, list the file names in a file, separated by blanks or line breaks. Then use the list file name on the javac command line, preceded by an # character.
Source code file names must have .java suffixes, class file names must have .class suffixes, and both source and class files must have root names that identify the class. For example, a class called MyClass would be written in a source file called MyClass.java and compiled into a bytecode class file called MyClass.class.
You might try with /dev/stdin as the source file (and then, you'll need to find the option which forces javac to consider it as Java source code).
But I would just make a shell script which put the stdin on some temporary file suffixed with .java.
But I think (I am not sure) that javac really wants a class Foo to be defined inside a file named Foo.java.
You can't do it with Sun java, but you can write a script to handle the conversion of stdin to something javac can understand.
Something like this Python script:
import fileinput, re, subprocess
class_name = None
buffer = []
class_matcher = re.compile('\w+ class (?P<name>\w+)')
for line in fileinput.input():
if None == class_name:
buffer.append(line)
m = class_matcher.match(line)
if m:
class_name = m.group('name')
print "found %s" % class_name
file_name = '%s.java' % class_name
out = open(file_name, 'wb')
out.writelines(buffer)
else:
out.write(line)
if None == class_name:
print "Error: no class found"
else:
out.close()
print 'javac %s' % file_name
output = subprocess.call(['javac', file_name])
Note that the script will create a file of the name of the class in the current directory. It's probably better to use something in /tmp, but keep in mind that it has to be named the same as the class. If you are testing the script don't do something like this:
cat MyImportantJava.java | python javac-stdin.py
This is not possible with plain javac - the reason is that most Java programs consist of more than one class, which are usually also distributed over more than one source file (compilation unit).
You can probably build a tool which does this, using the Java compiler API for the actual compilation.
You would have to create a JavaFileManager which simulates files by the text from standard input, and pass this to the compiler.
Related
I'm a Uni student trying to multiply two matrices stored in txt files via java and Eclipse. We were given a pre-compiled class file, but not the source code for the class file, essentially making it a blackbox class. We're supposed to use vim and the Linux terminal to program and execute our java code, but I find that Ecplise is far more time-efficient. However, when using the Linux terminal and vim my program works as intended, whereas when using Eclipse it does not.
Here's my source code with only the LOCs using the blackbox class
String fileOne = ArrayReader.getFileName("Enter the file name of matrix one");
int[][] matrixOne = ArrayReader.readArray(fileOne);
String fileTwo = ArrayReader.getFileName("Enter the file name of matrix two");
int[][] matrixTwo = ArrayReader.readArray(fileTwo);
The getFileName function outputs the argument, expecting the user to enter the file name (including the extension) of the file with the elements of the matrix in it. If it doesn't find the file, it returns an error message stating so, then asking for the file name again. The readArray function simply gets the elements and assigns them to the elements of the integer matrix.
I've tried putting the txt files in both my src and bin folders in my project directory, and inputting the file names with and without the file extension multiple times, but to no avail.
Any ideas?
I should put this in a comment but i don't have enough reputations
*Can you provide more details about the error so we can help and try to decompile the class to view it's source code you may find your answer also you can hardcode the file name (write it directly in the code) to test if everything works correctly *
The ArrayReader class expects the computer to be using Linux, not Windows.
java someJavaProgram fsa.fsa <test.txt
That, apparently, is a legitimate command to take with two files as arguments for a Java program in the terminal - one to read in, and then the other (and I think the idea is that it prints the output to the terminal directly). someJavaProgram, fsa.fsa and test.txt are all files in the same directory (being someProject/src, and someJavaProgram in the default package).
However, the response I am given in the terminal just says:
FSA file not found - please scan in the appropriate file.
Testing file not found, please scan in the new relevant file.
My question is two-fold:
What is this command and what is it for?
Does it need refining or modifying or is it the program that needs improvement?
I should note that I wrote the code in Eclipse, where I simply hardcoded filepaths into the program. I'm not sure if that affects anything but it's related.
EDIT: The filepaths and related code are as follows:
private static final String FILE_PATH = "src/test.txt";
private static final String FSA_PATH = "src/fsa1.fsa";
...
public static void main(String[] args) throws FileNotFoundException {
interpretAutomaton();
testAutomaton();
}
...
interpretAutomaton() {
...
Scanner fsaScanner = new Scanner(new BufferedReader(new FileReader(FSA_PATH)));
...
testAutomaton() {
...
Scanner fileScanner = new Scanner(new BufferedReader(new FileReader(FILE_PATH)));
*Both are surrounded by try/catch blocks - which clearly work!
Thanks to anyone who can help clarify on the matter!
Based on the comments so far, to answer your actual questions:
1) The command has four elements:
java - execute the java program
someJavaProgram - the name of the Java class to execute
fsa.fsa - the first argument to the java program, accessible via argv[]
<test.txt - standard input redirection, the contents of the file will be available on the program's standard input, ie. System.in
The net effect is to run your Java program with one argument and one file's contents on the standard input.
2) Both the command line and the program look like they need to change:
change the command line to:
java someJavaProgram fsa.fsa test.txt
That is, remove the <. You will also need to check the paths to the files are correct. This command line assume you are in the same directory as the files when you execute it.
Change your code to use the filenames on the command line rather than the hard-coded names.
I have a Java file Animal.java, and I want to be able to write a terminal command like so:
java Animal -a -print < data.txt
I know that the -a and -print appear as variables in the array arg (which is an input to the main method -- so arg[0] is -a and arg[1] is -print), but how can I access the data from data.txt?
It's is not possible in java, but instead you may pass the location of the file(not required if its already known and fixed) and then access the file's data using InputStream/ readLine() etc..
You can not manipulate the files in the same way that the Unix pipes do. You need treat your arguments so that there is a prefix or a position that defines the name of the file you want to read, so it is possible read the file passed as argument.
// Treating arguments and verify the possibility of reading file
// Get index which is the file name
FileInputStream fstream = new FileInputStream (argv [FileIndex]);
// Handle the file .
See an example here: Passing a file as a command line argument and reading its lines
Imagina the structure src/mypack/Main.java, run on terminal:
$ cd src/mypack/
/src/mypack$ javac Main.java
/src/mypack$ cd ..
/src$ java mypack.Main < path/your/file
I'm creating an xml-file in java using jaxb and XmlStreamWriter. This will become a very large file and has to be split into several pieces of max. 200MB. These pieces shouldn't be readable xml anymore.
The name of this file is very specific using the date and several parameters and at the end they're numbered like this: '3.1', '3.2', '3.3' where the first number is the number of chunks created and the second number is the following-number of the file. The first part of the filename (apart from the numbering) is created in the java application.
Now I want to create a UNIX script that calls the java application with the needed parameters, splits the file and renames the chunks.
I know the commands to call the java application and to split and rename files but I don't know how to combine them because I only now the filename in the Java application so I can't decide which file has to be split and renamed.
Does anyone have an idea how to deal with it?
EDIT:
Ok I'll try to be a bit less vague.
The application I created creates very large xml-files. The name of this files are in the following format: FI.DB2P.107601.20130130.20010.T.1.1 . This name contains some identification numbers and the date when the file is created. The first part of the name is created in the Java application like this: FI.DB2P.107601.20130130.20010.T.
Now this file should be split into several chunks of max. 200 MB each. Then the created chunks should have the same name as the 'base-file' but they have to end with 'T.3.1', 'T.3.2' and 'T.3.3' for example.
My question now is how I can obtain the filename of the file created by the java application in the Unix script. The filename is pretty complex and contains data from the database so I can't define the name in the Unix script.
I hope it's a bit clearer now.
Is it not the case that your Java process will call the Unix script and therefore will be able to pass it the filename on the command line.
The Unix script can take the filename and run something like split on it and then fix-up the filenames to those that your Java process is expecting.
Unless I misunderstand your question that should be fairly easy to do.
When you create your XMLStreamWriter you know (hopefully) the name of the file:
String fileName = "FI.DB2P.107601.20130130.20010.T.1.1";
XMLStreamWriter writer = factory.createXMLStreamWriter(new FileWriter(fileName ));
Then it's not a problem to pass this name as a parameter to your shell script:
Runtime.getRuntime().exec("yourscript.sh " + fileName);
yourscript.sh will have code to split the file and add incrementing variable to the file name, something like this might work:
#!/bin/bash
split -b 200m -a 5 "$1" splited_file
i=1
for file in splited_file*
do
mv $file $1_${i}
i=$(( i + 1 ))
done
ps: this script is not thread safe :)
I am trying to Compress and Archive all the files in a folder, using Java Runtime class. My code snippet looks as this :
public static void compressFileRuntime() throws IOException, InterruptedException {
String date = Util.getDateAsString("yyyy-MM-dd");
Runtime rt = Runtime.getRuntime();
String archivedFile = "myuserData"+date+".tar.bz2";
String command = "tar --remove-files -cjvf "+archivedFile+" marketData*";
File f = new File("/home/amit/Documents/");
Process pr = rt.exec(command, null, f);
System.out.println("Exit value: "+pr.exitValue());
}
The above code doesn't archive and compress the file as expected, though it creates a file myuserData2009-11-18.tar.bz2 in the folder "/home/amit/Documents/".
Also the output is
Exit value: 2.
While if I execute the same command from command line, it gives the expected result.
Please tell me what I am missing.
Thanks
Amit
The problem lies in this part:
" marketData*"
you expect the filenames to be compressed to be globbed from the * wildcard. Globbing is done by the shell, not by the tools themselves. your choices are to either:
numerate the files to be archived yourself
start the shell to perform the command ("/bin/sh -c")
start tar on the folder containing the files to be archived
Edit:
For the shell option, your command would look like:
String command = "sh -c \"tar --remove-files -cjvf "+archivedFile+" marketData*\"";
(mind the \"s that delimit the command to be executed by the shell, don't use single quotes ot the shell won't interpret the glob.)
If really you want to create a bzip2 archive, I'd use a Java implementation instead of a native command which is good for portability, for example the one available at http://www.kohsuke.org/bzip2/ (it is not really optimized though, compression seems to be slower than with Java LZMA).