I am writing a command-line matrix manipulation tool in Java, and was wondering if it is possible to run Java statements through console input.
I was thinking of using the java.util.Scanner object since that's what I'm using for the rest of my application, but I am open to any solution.
Here is a copy of my tool's application class, so you can see what I mean:
package projects.matrix.main;
import static java.lang.System.*;
import java.util.Scanner;
import projects.matrix.util.MatrixTool;
/**
* MATRIX :: Application class for the matrix toolset.
* #author toner
* #version May 28 2015
* #since 1.8
**/
public class MarixApp {
public static void main (String [] args) {
out.println("****************************** START*****************"
+ "*************\n");
runCommandLine();
out.println("****************************** END *****************"
+ "*************\n");
}
/**
* MATRIX.MAIN :: runCommandLine runs a loop command line
* #param none
* #return none
**/
public static void runCommandLine () {
// method vars
Scanner scanner = new Scanner(in);
MatrixTool matrixtool = new MatrixTool();
int[][] matrix1 = new int[0][0];
int[][] matrix2 = new int[0][0];
int[][] resultmatrix = new int[0][0];
String command = "";
int executerret = 0;
// welcome prints
out.println("[!] welcome to toner's matrix tool command-line");
out.println("[!] enter 'HELP' to view available commands\n");
// commmand-line loop
do {
out.print(" [?] >> ");
command = scanner.nextLine();
executerret = executecmd(command);
} while (executerret != -1);
}
/**
* MATRIX.MAIN :: executecmd executes the command passed by runCommandLine
* #param cmd : String
* #return returncode : int
**/
public static int executecmd (String cmd) {
// method vars
Scanner scanner = new Scanner(in);
MatrixTool matrixtool = new MatrixTool();
int returncode = 0;
// command executer
switch (cmd) {
case "HELP" :
case "help" :
out.println("\n"
+ " [%] ADD DIVIDE HELP "
+ "MULTIPLY PRINT"
+ " [%] RUNJAVA SUBSTRACT SETMTRX "
+ "SETMTRX1 SETMTRX2"
+ " [%] TRANSPOSE RUNOPS RESET "
+ "EXIT\n");
break;
// rest of commands go here
}
}
}
Regards.
Have you thought about using Groovy? It's a JVM based dynamic language which means you can dynamically execute code - code that comes as a String. Syntactically it's very close to Java. An example code could look like:
new GroovyShell().evaluate("println 'hello'")
If by running console input as java statements, you mean taking the exact input from the console and run it inside your application, you need to compile and run them. You can do so using the Compiler API
Related
I try to open a video stream from a RTSP server into a JAVA application. First I tried to run this example :
package uk.co.caprica.vlcj.test.streaming;
import uk.co.caprica.vlcj.player.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.headless.HeadlessMediaPlayer;
import uk.co.caprica.vlcj.test.VlcjTest;
/**
* An example of how to stream a media file using RTSP.
* <p>
* The client specifies an MRL of <code>rtsp://#127.0.0.1:5555/demo</code>
*/
public class StreamRtsp extends VlcjTest {
public static void main(String[] args) throws Exception {
if(args.length != 1) {
System.out.println("Specify a single MRL to stream");
System.exit(1);
}
String media = args[0];
String options = formatRtspStream("127.0.0.1", 5555, "demo");
System.out.println("Streaming '" + media + "' to '" + options + "'");
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory(args);
HeadlessMediaPlayer mediaPlayer = mediaPlayerFactory.newHeadlessMediaPlayer();
mediaPlayer.playMedia(media,
options,
":no-sout-rtp-sap",
":no-sout-standard-sap",
":sout-all",
":sout-keep"
);
// Don't exit
Thread.currentThread().join();
}
private static String formatRtspStream(String serverAddress, int serverPort, String id) {
StringBuilder sb = new StringBuilder(60);
sb.append(":sout=#rtp{sdp=rtsp://#");
sb.append(serverAddress);
sb.append(':');
sb.append(serverPort);
sb.append('/');
sb.append(id);
sb.append("}");
return sb.toString();
}
}
But I have always the same result :
Specify a single MRL to stream
http://i.stack.imgur.com/8iX0O.png
Even if I delete this section :
if(args.length != 1) {
System.out.println("Specify a single MRL to stream");
System.exit(1);
}
Can you help me please ?
Sounds like you're not actually passing an argument to the program, which it expects from this line:
String media = args[0];
If you don't want to pass an argument, just change it to:
String media = "(location of rtsp to stream)";
...and delete the if statement above it as you already have.
This is a full example with java, include a Java class for streaming (no need to create other functions)
This is an example for a simple streaming :
StreamRTP rtp = new StreamRTP();
rtp.start("10.20.11.142", 5000, "sample.mp3");
You can find the class here : https://github.com/maitmansour/vlcj-audio-rtp-streaming-example
I have a menu-driven program allows the user to add, remove and display the name of a person in a queue.
My program compiles and runs perfectly for me.
However, when my instructor tested it, he stated it won't compile and receives this error?:
QueueProgram.java:24: illegal start of type
MyQueue<String> queue= new MyQueue<>(15);
^
1 error
My code:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JOptionPane;
public class QueueProgram {
/**
* Driver code to test class
*
* #param arguments
* Commandline arguments not used
* #throws IOException
*/
public static void main(String[] arguments) throws IOException {
//Queue Object
MyQueue<String> queue= new MyQueue<>(15);
String name;
//reading file
read(queue,arguments[0]);
String[] array = { "Offer Person", "Poll Person", "Peek person",
"Display Queue", "Exit Program"};
int choice = 0;
// display loop
while (choice != array.length-1) {
choice = JOptionPane.showOptionDialog(null, // put in center of screen
"Press a Button", // message to user
"Queue(Line) of People", // title of window
JOptionPane.YES_NO_CANCEL_OPTION, // type of option
JOptionPane.QUESTION_MESSAGE, // type of message
null, // icon
array, // array of strings
array[array.length - 1]); // default choice (last one)
if(choice==0){
//inserting the new name in queue
name=JOptionPane.showInputDialog(null,"Enter Person's name","Input");
queue.offer(name);
}
else if(choice==1){
//Display and remove the name which is at front of line
JOptionPane.showMessageDialog(null, queue.poll() + " is next in line");
}
else if(choice==2){
//Display name which is at front of line
JOptionPane.showMessageDialog(null, queue.peek() + " is front of the line");
}
else if(choice==3){
//Dispay all the list
JOptionPane.showMessageDialog(null, queue.toString());
}
//JOptionPane.showMessageDialog(null, "Your pressed button #" + choice);
}
//calling writing function
write(queue, arguments[1]);
}// end of main()
/**
* Reads a file
* #param queue
* #param file_name name of file
*/
public static void read(QueueInterface<String> queue, String file_name) throws IOException{
String name;
//creating a buffer reader to read
BufferedReader br= new BufferedReader(new FileReader(file_name));
while((name=br.readLine()) != null){
//putting in the queue
queue.offer(name);
}
//closing buffer reader
br.close();
}
/**
* Writes to file
* #param queue QueueInterface methods
* #param file_name name of file
*/
public static void write(QueueInterface<String> queue, String file_name) throws IOException{
String name;
//creating a buffer writer to write
BufferedWriter bw= new BufferedWriter(new FileWriter(file_name));
while((name=queue.poll()) != null){
//writin in file
bw.write(name);
bw.newLine();
}
//closing buffer
bw.close();
}
}// end of class
class MyQueue<T> extends ArrayQueue<T>{
/**
* Constructor
*
* #param max is the greatest number of elements in the queue
*/
public MyQueue(int max) {
super(max);
}
/**
* Returns a string representation of the object
*
* #return a name on different lines
*/
public String toString() {
// create a variable
String element = "";
int count=frontIndex;
// check to see if not empty
if (!this.empty()) {
// get the address of front element
while(count<=endIndex){
element = element +(String) array[count]+"\n";
count++;
}
}
// return either null or element
return element;
}
}
Any idea what could cause this error?
The diamond operator (<>) was introduced in Java 7 only. You should specify the type argument (new MyQueue<String>(15)) explicitly and your instructor will be able to compile it.
You can find the explanation here - Java SE 7 Features and Enhancements - Type Inference for Generic Instance Creation.
I am creating a custom shell in Java. I have added history to it so that when up arrow is pressed it goes to the previous command, but the up arrow seems to not be working
Here is my code:
public class MyShell {
public static class JavaStringHistory
{
private List<String> history = new ArrayList<String>();
}
public static void main(String[] args) throws java.io.IOException {
JavaStringHistory javaStringHistory = new JavaStringHistory();
javaStringHistory.history.add("");
Integer indexOfHistory = 0;
String commandLine;
BufferedReader console = new BufferedReader
(new InputStreamReader(System.in));
//Break with Ctrl+C
while (true) {
//read the command
System.out.print("Shell>");
commandLine = console.readLine();
javaStringHistory.history.add(commandLine);
//if just a return, loop
if (commandLine.equals(""))
continue;
//history
if (commandLine.equals(KeyEvent.VK_UP))
{
System.out.println("up arrow");
}
//help command
if (commandLine.equals("help"))
{
System.out.println();
System.out.println();
System.out.println("Welcome to the shell");
System.out.println("Written by: Alex Frieden");
System.out.println("--------------------");
System.out.println();
System.out.println("Commands to use:");
System.out.println("1) cat");
System.out.println("2) exit");
System.out.println("3) clear");
System.out.println();
System.out.println();
System.out.println("---------------------");
System.out.println();
}
if (commandLine.equals("clear"))
{
for(int cls = 0; cls < 10; cls++ )
{
System.out.println();
}
}
if(commandLine.startsWith("cat"))
{
System.out.println("test");
//ProcessBuilder pb = new ProcessBuilder();
//pb = new ProcessBuilder(commandLine);
}
else
{
System.out.println("Incorrect Command");
}
if (commandLine.equals("exit"))
{
System.out.println("...Terminating the Virtual Machine");
System.out.println("...Done");
System.out.println("Please Close manually with Options > Close");
System.exit(0);
}
indexOfHistory++;
}
}
}
All I am getting is
Shell>^[[A
Incorrect Command
Shell>
Any thoughts?
There are several problems with your approach:
User blackSmith has mentioned before me that system console handling is platform-dependent when it comes to cursor key handling and similar topics.
BufferedReader.readLine is not a smart choice to use for history cycling in a shell because you want the shell to immediately react to cursor keys and not force the user to press Return or Enter. Reading whole lines is only required for user commands. Thus, you need to scan the keyboard input for each single character or key code and decide by yourself if it is e.g. a cursor key (up/down for history cycling, left/right for cursor movement within the command line) or delete/backspace for command line editing and so forth.
The text strings which are created by reading control characters via readLine can depend on the OS, maybe even on the shell and the character set (UTF-8, ISO-8859-1, US ASCII etc.) on the console.
Built-in shell editing functions like command history might get in the way with readLine, e.g. on Linux I see the "^[[A" stuff for cursor up, on Windows the cursor keys are passed through to the built-in command history feature of cmd.exe. I.e. you need to put the console in raw mode (line editing bypassed and no Enter key required) as opposed to cooked mode (line editing with Enter key required).
Anyway, so as to answer your initial question about how to find out which key codes are produced by BufferedReader.readLine, it is actually quite simple. Just dump the bytes to the console like so:
commandLine = console.readLine();
System.out.println("Entered command text: " + commandLine);
System.out.print ("Entered command bytes: ");
for (byte b : commandLine.getBytes())
System.out.print(b + ", ");
System.out.println();
Under Linux cursor up might be something like "27, 91, 65" or just "91, 65", depending on the terminal. cursor down ends with "66" instead on my system. So you could do something like:
public class MyShell {
private static final String UP_ARROW_1 = new String(new byte[] {91, 65});
private static final String UP_ARROW_2 = new String(new byte[] {27, 91, 65});
private static final String DN_ARROW_1 = new String(new byte[] {91, 66});
private static final String DN_ARROW_2 = new String(new byte[] {27, 91, 66});
// (...)
public static void main(String[] args) throws IOException {
// (...)
// history
else if (commandLine.startsWith(UP_ARROW_1) || commandLine.startsWith(UP_ARROW_2)) {
System.out.println("up arrow");
}
else if (commandLine.startsWith(DN_ARROW_1) || commandLine.startsWith(DN_ARROW_2)) {
System.out.println("down arrow");
}
// (...)
}
}
But all this is just for explanation or demonstration and so as to answer your question - I do like to get the bounty. ;-)
Maybe a way to go is not to re-invent the wheel and use the work of others, e.g. a framework like JLine. It is not perfect either from what I have heard, but goes way further than anything you can develop by yourself in a short time. Someone has written a short introductory blog post about JLine. The library seems to do just what you need. Enjoy!
Update: I gave JLine 2.11 a little try with this code sample (basically the one from the blog post plus tab filename completion:
import java.io.IOException;
import jline.TerminalFactory;
import jline.console.ConsoleReader;
import jline.console.completer.FileNameCompleter;
public class MyJLineShell {
public static void main(String[] args) {
try {
ConsoleReader console = new ConsoleReader();
console.addCompleter(new FileNameCompleter());
console.setPrompt("prompt> ");
String line = null;
while ((line = console.readLine()) != null) {
console.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
TerminalFactory.get().restore();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
It works nicely on Windows and Linux, but for me tab completion only works on Linux, not on Windows. Anyway, command history works well on both platforms.
VK_UP is an integer constant, while in.readLine() is a string.
They won't equal each other. Why don't you try to test for the code that appears in console usually when you click up arrow? So like:
if (in.readLine().equals("^[[A"))
and then you could clear the line, and write the command in the arraylist with the highest index.
Also, I tested this and found a bug. Change your if statements besides the first to else if; after any command it will eventually get to the else and display "Incorrect Command"
I know that command line interfaces like Git and others are able to hide input from a user (useful for passwords). Is there a way to programmtically do this in Java? I'm taking password input from a user and I would like their input to be "hidden" on that particular line (but not on all of them). Here's my code for it (though I doubt it would be helpful...)
try (Scanner input = new Scanner(System.in)) {
//I'm guessing it'd probably be some property you set on the scanner or System.in right here...
System.out.print("Please input the password for " + name + ": ");
password = input.nextLine();
}
Try java.io.Console.readPassword. You'll have to be running at least Java 6 though.
/**
* Reads a password or passphrase from the console with echoing disabled
*
* #throws IOError
* If an I/O error occurs.
*
* #return A character array containing the password or passphrase read
* from the console, not including any line-termination characters,
* or <tt>null</tt> if an end of stream has been reached.
*/
public char[] readPassword() {
return readPassword("");
}
Beware though, this doesn't work with the Eclipse console. You'll have to run the program from a true console/shell/terminal/prompt to be able to test it.
Yes can be done. This is called Command-Line Input Masking. You can implement this easily.
You can uses a separate thread to erase the echoed characters as they are being entered, and replaces them with asterisks. This is done using the EraserThread class shown below
import java.io.*;
class EraserThread implements Runnable {
private boolean stop;
/**
*#param The prompt displayed to the user
*/
public EraserThread(String prompt) {
System.out.print(prompt);
}
/**
* Begin masking...display asterisks (*)
*/
public void run () {
stop = true;
while (stop) {
System.out.print("\010*");
try {
Thread.currentThread().sleep(1);
} catch(InterruptedException ie) {
ie.printStackTrace();
}
}
}
/**
* Instruct the thread to stop masking
*/
public void stopMasking() {
this.stop = false;
}
}
With using this thread
public class PasswordField {
/**
*#param prompt The prompt to display to the user
*#return The password as entered by the user
*/
public static String readPassword (String prompt) {
EraserThread et = new EraserThread(prompt);
Thread mask = new Thread(et);
mask.start();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String password = "";
try {
password = in.readLine();
} catch (IOException ioe) {
ioe.printStackTrace();
}
// stop masking
et.stopMasking();
// return the password entered by the user
return password;
}
}
This Link discuss in details.
JLine 2 may be of interest. As well as character masking, it'll provide command-line completion, editing and history facilities. Consequently it's very useful for a CLI-based Java tool.
To mask your input:
String password = new jline.ConsoleReader().readLine(new Character('*'));
There is :
Console cons;
char[] passwd;
if ((cons = System.console()) != null &&
(passwd = cons.readPassword("[%s]", "Password:")) != null) {
...
java.util.Arrays.fill(passwd, ' ');
}
source
but I don't think this works with an IDE like Eclipse because the program is run as a background process rather than a top level process with a console window.
Another approach is to use the JPasswordField in swing with the accompanying actionPerformed method:
public void actionPerformed(ActionEvent e) {
...
char [] p = pwdField.getPassword();
}
source
Here is an example using console.readPassword(...); in an IDE. I use Netbeans. Note: In your IDE, Scanner will be used and it will show the password!. In the console, console.readPassword(..) will be used and it will not show the password!.
public static void main(String[] args) {
//The jar needs to be run from the terminal for console to work.
Scanner input = new Scanner(System.in);
Console console = System.console();
String username = "";
String password = "";
if (console == null)
{
System.out.print("Enter username: ");
username = input.nextLine();
System.out.print("Enter password: ");
password = input.nextLine();
}
else
{
username = console.readLine("Enter username: ");
password = new String(console.readPassword("Enter password: "));
}
//I use the scanner for all other input in the code!
//I do not know if there are any pitfalls associated with using the Scanner and console in this manner!
}
Note: I do not know if there are any pitfalls associated with using the Scanner and console in this manner!
The class Console has a method readPassword() that might solve your problem.
I am not a good programmer. In school, I learned MATLAB. So i have no idea what I am doing.
I am working with the ThingMagic M6 reader. They have their own API. I wanted to create my own application to read the program. I want to use a sample program that they have supplied (since my program doesn't seem to work). However, the supplied program only accepts command line arguments. How do i change it so I can pass arguments to it in my code.
This is the supplied code: (at the command line I input tmr://10.0.0.101)
/**
* Sample program that reads tags for a fixed period of time (500ms)
* and prints the tags found.
*/
// Import the API
package samples;
import com.thingmagic.*;
public class read
{
static void usage()
{
System.out.printf("Usage: demo reader-uri <command> [args]\n" +
" (URI: 'tmr:///COM1' or 'tmr://astra-2100d3/' " +
"or 'tmr:///dev/ttyS0')\n\n" +
"Available commands:\n");
System.exit(1);
}
public static void setTrace(Reader r, String args[])
{
if (args[0].toLowerCase().equals("on"))
{
r.addTransportListener(r.simpleTransportListener);
}
}
static class TagReadListener implements ReadListener
{
public void tagRead(Reader r, TagReadData t) {
System.out.println("Tag Read " + t);
}
}
public static void main(String argv[])
{
System.out.println(argv.getClass().toString());
// Program setup
TagFilter target;
Reader r;
int nextarg;
boolean trace;
r = null;
target = null;
trace = false;
nextarg = 0;
if (argv.length < 1)
usage();
if (argv[nextarg].equals("-v"))
{
trace = true;
nextarg++;
System.out.println("Trace");
}
// Create Reader object, connecting to physical device
try
{
TagReadData[] tagReads;
r = Reader.create(argv[nextarg]);
if (trace)
{
setTrace(r, new String[] {"on"});
}
r.connect();
if (Reader.Region.UNSPEC == (Reader.Region)r.paramGet("/reader/region/id"))
{
r.paramSet("/reader/region/id", Reader.Region.NA);
}
r.addReadListener(new TagReadListener() );
// Read tags
tagReads = r.read(500);
// Print tag reads
for (TagReadData tr : tagReads)
System.out.println(tr.toString());
// Shut down reader
r.destroy();
}
catch (ReaderException re)
{
System.out.println("Reader Exception : " + re.getMessage());
}
catch (Exception re)
{
System.out.println("Exception : " + re.getMessage());
}
}
}
This is me trying to use it: (arg comes from a JTextField)
String[] argv = new String[1];
argv[0] = arg;
readOnceApp(argv);
I have a feeling there is a really simple answer to this problem, I just can't figure it out. I searched the internet for a few days and read books, and still can't figure it out. Any help is appreciated. Thank You.
edit: readOnceApp is one method I wrote. It is basically just the main method of the supplied code. I can include it, if it will help. I just didn't want to post too much code.
If you want to call the "main" method of a class from another class, do it like this:
String [] args = new String [1];
args[0]= "some param";
readOnceApp.main(args);
This is making the assumption that "readOnceApp" is the name of your class. (BTW, you should follow the convention of using capitalized class names, e.g. ReadOnceApp).
Hope this helps.