Reading file input from Java using terminal - java

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

Related

In Java, how do I find the proper path to open a txt file that's name is provided as a command line arguement?

I'm working on a program that is supposed to take two files as command line arguments, open the files, and read data from the files to make a data structure.
So far, I have been able to make the structure using File() to open the files and Scanner to read the data. The problem is that I have been providing a specific path to the call for File like this
File f1 = new File("F:/MinSpan/resources/cities.txt");
Scanner sc1 = new Scanner(f1);
I don't think this is going to work for the person who tries to run this program, because I have provided the path for where my specific txt files are located - they're on my flash drive (F) and in some folders. Is there a way I can program this to pass some kind of args[] value in for File() based on the cmd arguement the user has provided?
I have already tried just doing new File(args[2]) , and it can't find the file because there is no path.
The reason for that is because, if you are passing in only two paths, args[2] wont return anything, because args[] starts at 0. So you'd want to use:
new File(args[0]);
new File(args[1]);
Does that make sense?
If you're going for something like java -jar program.jar FILE, then have the program check for the String in args[] at index 0.
Then, construct your file. Check if the file exists (in java.io, it's File.exists()) and return an error message to the user if it's wrong.

How do we take command line arguments using arg[] from intellij/eclipse

I was asked to run a program using command line arguments. The command line argument could either be a file or stdin.
eg:
Your program must accept input from two sources: a filename passed in
command line arguments and STDIN. For example './program input.txt' and './program < input.txt' should work.
Let me be frank, I am not sure whether I am being asked to pass the location of the file or feed the input to the program using STDIN. I am assuming, for now, it's asking me to input the location of the file. How can I do it using arg[0]? Can I use System.in, will that violate the requirement that is being asked from me?
Instead of running the application directly you can pass the arguments from run configuration. For example, in eclipse you can do the following:
right click on the project > run as > run configuration
In the new windows: java application > "your app"
you can find a tab "arguments"
here you can set the arguments for the app in the "program arguments".
I am not sure whether I am being asked to pass the location of the file or feed the input to the program using STDIN
Both. As stated, "your program must accept input from two sources". So, your program must support both, either taking a file argument or reading from standard in.
For the first variant, the file argument, the file's name will be available in arg[0].
So, if the arg-array contains at least one entry, go with the file argument.
If there is no file argument (arg.length == 0), then read from STDIN.
In code, it could look a bit like this:
public static void main(String[] arg) {
if (arg.length == 0) {
// work with System.in
} else {
File file = new File(arg[0]);
// work with file
}
}

Split and rename java created xml 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 :)

Passing a string from Java to a bash script

So I have a client and a server Java program. The client uses Java processbuilder to execute the script but my problem is that the user inputs information that needs to be passed to the bash script. So, essentially, I need to know how to send three different strings to three different variables that are being read by the bash script. This script is copying a file so I would rather not make a txt file with java and have the script read the file. I would also like a way for this to be able to run on OS X and Windows so improvements are welcome. I am using Java 7 on Ubuntu currently.
Here is a snippet of what I am trying to do:
.java
Scanner bob = new Scanner(System.in);
String workingDirectory = new String(System.getProperty("user.dir"));
File tempDir = new File(workingDirectory);
String script = new String(workingDirectory + "/copyjava.sh");
System.out.print("Designate the location of the file: ");
String loc = bob.next();
System.out.print("Type the name of the file w/ extension: ");
String name = bob.next();
System.out.print("What is the location of THIS file? "); //I know there is a way to do this automagically but I can't remember how...
String wkspace = bob.next();
ProcessBuilder pb = new ProcessBuilder( script, loc, name, wkspace);
pb.start();
File myFile = new File (name);
Script:
read loc
read name
read wkspace
cd $LOC
cp $name $wkspace
There is a problem with your shell script. The read command reads from stdin, but you are passing the input as arguments. You are also changing the case of the loc variable. Variables in the shell are case sensitive. Change your script to the following:
#!/bin/sh
loc=$1
name=$2
wkspace=$3
cd "$loc" || { printf 'failed to cd to %s\n' "$loc" ; exit 1; }
cp "$name" "$wkspace" || { printf 'failed to copy %s\n' "$name" ; exit 1; }
On a side note, you shouldn't need to call an external script written in a different language just to copy a file. You should implement this in java. Implementing this in java will also give your code the platform independence you desire.
You are passing your args on the command line but reading from stdin in your script. How about changing your script to:
cd $1
cp $2 $3
I don't see any client/server interaction but let's focus on what's really important: Your are passing the parameters to the script but your script is trying to read them from the standard input.
To fix your problem modify your script as follows:
#!/bin/sh
LOC=$1
name=$2
wkspace=$3
cd $LOC
cp $name $wkspace
Take a look at the documentation for more details.
But are not doing anything that would really need a system-specific script file. The best way to copy a file is using the own mechanism that Java provides and then you don't need to worry of the underlying operating system.
If you keep on using the script then you'll need another one for Windows systems and then decide which script you should run based on the value of the os.name system property.

Can javac compile from stdin?

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.

Categories