A have four classes: Main, Read, Author, Commands.
In Read class:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
public class Read {
static ArrayList<String> arAuthor = new ArrayList<>();
static ArrayList<String> arCommand = new ArrayList<>();
public static ArrayList<String> getArAuthor() {
return arAuthor;
}
public static void setArAuthor(ArrayList<String> arAuthor) {
Read.arAuthor = arAuthor;
}
public static ArrayList<String> getArCommand() {
return arCommand;
}
public static void setArCommand(ArrayList<String> arCommand) {
Read.arCommand = arCommand;
}
public static void main(String[] args) {
BufferedReader author;
BufferedReader command;
String thisLine;
String thisLine1;
try {
author = new BufferedReader(new FileReader(args[0]));
command = new BufferedReader(new FileReader(args[1]));
while ((thisLine = author.readLine()) != null) {
System.out.println(thisLine);
arAuthor.add(thisLine);
}
while ((thisLine1 = command.readLine()) != null) {
System.out.println(thisLine1);
arCommand.add(thisLine1);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
My code works as Read.java args[0] args[1] but i want it to work like Main.java args[0] args[1]. I am new to Java so ı can't figure how can i pass this arguments to Main.java
Solution:
public class Reader {
public List<String> arAuthor = new ArrayList<>();
public List<String> arCommand = new ArrayList<>();
public void read(String first, String second) throws IOException {
String thisLine;
String thisLine1;
try (BufferedReader author = new BufferedReader(new FileReader(first));
BufferedReader command = new BufferedReader(new FileReader(second));){
while ((thisLine = author.readLine()) != null) {
System.out.println(thisLine);
arAuthor.add(thisLine);
}
while ((thisLine1 = command.readLine()) != null) {
System.out.println(thisLine1);
arCommand.add(thisLine1);
}
}
}
}
public class Main {
public static void main(String[] args) throws IOException {
Reader reader = new Reader();
reader.read(args[0], args[1]);
System.out.println(reader.arAuthor);
System.out.println(reader.arCommand);
}
}
In my idea IDE, I can see the compile error with red font in the console.But when I deploy the jar in the linux server.I can not see the compile log.How to print the compile error log?
public static void main(String[] args) throws Exception {
String compliePath="D:\\testFole";
String filename="D:\\test.java";
String[] arg = new String[] { "-d", compliePath, filename };
System.out.println(com.sun.tools.javac.Main.compile(arg));
}
Well if I got your question right, here is an approach to the outcome.
I think this will be platform-independent.
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
private static Process process;
public static void main(String[] args) {
runCommand();
getErrorMessage();
}
/**
* This method executes/runs the commands
*/
private static void runCommand()
{
File file = new File("D:\\\\test.java");
String changeDirectory = "cmd start cmd.exe /c cd D:\\";
String compile = " && javac D:\\test.java";
String run = " && java "+file.getName().replace(".java","");
String command = changeDirectory + compile + run;
try {
process = Runtime.getRuntime().exec(command);
}catch (IOException e){}
}
/**
* This method will get the errorStream from process
* and output it on the console.
*/
private static void getErrorMessage()
{
try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())))
{
String line;
if(errorReader.readLine() != null)
while ((line = errorReader.readLine()) != null)
System.out.println(line); //display error message
}catch (IOException e){}
}
}
I'm using MessageConsole.java to redirect standard output stream to a text pane. After finishing it, I thought it would be nice to redirect the error stream as well. To do so, I added another buffered reader to a modified version of this answer. Next is where my problem is - I need another "version" of the process() method which prints to System.err instead of System.out. I tried Googling it, but my results were nill. How would I add in another version of a Overridden method that requires specific arguments? The code might look something like the second example.
My current code
class ConsoleThread extends SwingWorker<Void, String> {
String command;
ConsoleThread(String cmd) {
command = cmd;
}
#Override
protected Void doInBackground() throws Exception {
Process ps = Runtime.getRuntime().exec(command);
BufferedReader is = new BufferedReader(new InputStreamReader(ps.getInputStream()));
BufferedReader es = new BufferedReader(new InputStreamReader(ps.getErrorStream()));
String outputLine;
String errorLine;
while ((outputLine = is.readLine()) != null) {
publish(outputLine);
}
while ((errorLine = es.readLine()) != null) {
publish(errorLine);
}
is.close();
return null;
}
#Override
protected void process(List<String> chunk) {
for (String string : chunk) {
System.out.println(string);
}
}
}
What the answer might look like (a snippet of code is worth a thousand words)
class ConsoleThread extends SwingWorker<Void, String> {
String command;
ConsoleThread(String cmd) {
command = cmd;
}
#Override
protected Void doInBackground() throws Exception {
Process ps = Runtime.getRuntime().exec(command);
BufferedReader is = new BufferedReader(new InputStreamReader(ps.getInputStream()));
BufferedReader es = new BufferedReader(new InputStreamReader(ps.getErrorStream()));
String outputLine;
String errorLine;
while ((outputLine = is.readLine()) != null) {
publish(outputLine);
}
while ((errorLine = es.readLine()) != null) {
publish2(errorLine);
}
is.close();
return null;
}
#Override
protected void process(List<String> chunk) {
for (String string : chunk) {
System.out.println(string);
}
}
#Override
protected void process2(List<String> chunk) {
for (String string : chunk) {
System.err.println(string);
}
}
}
Where process2() would be treated like the original process().
To be clear, the current code works but sends any error messages to the output stream rather than the error stream. (See this)
You don't need "another version of Process" at all. All you need are two new threads, one for each Stream, both the InputStream and the ErrorStream. Create two Runnables, put the while loops in those Runnables, pass your Streams into them, and run the Runnables in their own threads.
You could wrap the messages that you wish to publish in a wrapper object that identifies the stream origin of the method, allowing you to use the same publish/process pair, or you could use other notification methods such as PropertyChangeListeners and PropertyChangeSupport.
For what it's worth, I've used this code in previous attempts to read error and output streams:
enum GobblerType.java
public enum GobblerType {
ERROR, OUTPUT
}
class StreamGobbler.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
public class StreamGobbler implements Runnable {
private InputStream is;
private GobblerType type;
private OutputStream os;
public StreamGobbler(InputStream is, GobblerType type) {
this(is, type, null);
}
public GobblerType getType() {
return type;
}
public StreamGobbler(InputStream is, GobblerType type, OutputStream redirect) {
this.is = is;
this.type = type;
this.os = redirect;
}
public void run() {
try {
PrintWriter pw = null;
if (os != null) {
pw = new PrintWriter(os, true);
}
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
if (pw != null) {
pw.println(line);
}
// System.out.println(type + "> " + line);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
class TextAreaOutputStream.java -- I have most doubts about this one
import java.io.IOException;
import java.io.OutputStream;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TextAreaOutputStream extends OutputStream {
private final JTextArea textArea;
private final StringBuilder sb = new StringBuilder();
private String title;
public TextAreaOutputStream(final JTextArea textArea, String title) {
this.textArea = textArea;
this.title = title;
sb.append(title + "> ");
}
#Override
public void flush() {
}
#Override
public void close() {
}
#Override
public void write(int b) throws IOException {
if (b == '\r')
return;
if (b == '\n') {
final String text = sb.toString() + "\n";
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(text);
}
});
sb.setLength(0);
sb.append(title + "> ");
return;
}
sb.append((char) b);
}
}
None of this is professional code, just junk I've played with.
I wanted to create a web page in Struts2.0 which contains a textarea, a property field and submit button. User will enter a java code in this text area and my code will compile it and execute it and will give the result of this code on my property field... the above code works fine in a standalone application. but it does not shows any thing in my web application. plz any one can address it... thanks in advance.
package org.controller;
import com.opensymphony.xwork2.ActionSupport;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
public class JCompilerAction extends ActionSupport
{
String program;
String MSg;
public JCompilerAction() {
}
public String getProgram() {
return program;
}
public void setProgram(String program) {
this.program = program;
}
public String getMSg() {
return MSg;
}
public void setMSg(String MSg) {
this.MSg = MSg;
}
public String Compile() {
try {
byte[] bFile = program.getBytes();
File f = new File("D:/nullprog.java");
FileOutputStream fileOuputStream = new FileOutputStream(f);
fileOuputStream.write(bFile);
fileOuputStream.close();
Process p1 = Runtime.getRuntime().exec("javac D:/nullprog.java");
BufferedReader in = new BufferedReader(new InputStreamReader(p1.getErrorStream()));
String line = null;
boolean isError = false;
while ((line = in.readLine()) != null) {
MSg = line;
isError = true;
return SUCCESS;
}
p1.waitFor();
if (!isError)
{
Process p2 = Runtime.getRuntime().exec("cmd /c start nullprog");
BufferedReader in1 = new BufferedReader(new InputStreamReader(p2.getInputStream()));
String line1 = null;
while ((line1 = in1.readLine()) != null) {
MSg += line1;
}
return SUCCESS;
}
} catch (Exception e) {
e.printStackTrace();
}
return SUCCESS;
}
public String execute() {
return SUCCESS;
}
}
Below is a simple program that first compiles a code and then executes it:
Executer.java
import java.lang.reflect.Method;
public class Executer {
public static void main(String args[]) {
try{
java.lang.Process p1 = Runtime.getRuntime().exec("javac MyClass.java");
p1.waitFor();
Class<?> c = Class.forName("MyClass");
Object obj = c.newInstance();
Method[] mArr = obj.getClass().getMethods();
for(Method m : mArr){
if(m.getName().equalsIgnoreCase("main")){
m.invoke(obj, new Object[]{new String[]{}});
}
}
} catch (Exception e){
e.printStackTrace();
}
}
}
MyClass.java
import javax.swing.JOptionPane;
public class MyClass {
public static void main(String[] args) {
JOptionPane.showMessageDialog(null, "Hii");
}
}
For simplicity both the classes are in same package. When I execute Executer class, it first compiles MyClass.java and then runs the main method.
If your requirement is to have the Java files in some folder outside of the project, the to load the compiler class file, you need to follow as mentioned in this answer.
Does any one know how do I get the current open windows or process of a local machine using Java?
What I'm trying to do is: list the current open task, windows or process open, like in Windows Taskmanager, but using a multi-platform approach - using only Java if it's possible.
This is another approach to parse the the process list from the command "ps -e":
try {
String line;
Process p = Runtime.getRuntime().exec("ps -e");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line); //<-- Parse data here.
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
If you are using Windows, then you should change the line: "Process p = Runtime.getRun..." etc... (3rd line), for one that looks like this:
Process p = Runtime.getRuntime().exec
(System.getenv("windir") +"\\system32\\"+"tasklist.exe");
Hope the info helps!
Finally, with Java 9+ it is possible with ProcessHandle:
public static void main(String[] args) {
ProcessHandle.allProcesses()
.forEach(process -> System.out.println(processDetails(process)));
}
private static String processDetails(ProcessHandle process) {
return String.format("%8d %8s %10s %26s %-40s",
process.pid(),
text(process.parent().map(ProcessHandle::pid)),
text(process.info().user()),
text(process.info().startInstant()),
text(process.info().commandLine()));
}
private static String text(Optional<?> optional) {
return optional.map(Object::toString).orElse("-");
}
Output:
1 - root 2017-11-19T18:01:13.100Z /sbin/init
...
639 1325 www-data 2018-12-04T06:35:58.680Z /usr/sbin/apache2 -k start
...
23082 11054 huguesm 2018-12-04T10:24:22.100Z /.../java ProcessListDemo
On Windows there is an alternative using JNA:
import com.sun.jna.Native;
import com.sun.jna.platform.win32.*;
import com.sun.jna.win32.W32APIOptions;
public class ProcessList {
public static void main(String[] args) {
WinNT winNT = (WinNT) Native.loadLibrary(WinNT.class, W32APIOptions.UNICODE_OPTIONS);
WinNT.HANDLE snapshot = winNT.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new WinDef.DWORD(0));
Tlhelp32.PROCESSENTRY32.ByReference processEntry = new Tlhelp32.PROCESSENTRY32.ByReference();
while (winNT.Process32Next(snapshot, processEntry)) {
System.out.println(processEntry.th32ProcessID + "\t" + Native.toString(processEntry.szExeFile));
}
winNT.CloseHandle(snapshot);
}
}
The only way I can think of doing it is by invoking a command line application that does the job for you and then screenscraping the output (like Linux's ps and Window's tasklist).
Unfortunately, that'll mean you'll have to write some parsing routines to read the data from both.
Process proc = Runtime.getRuntime().exec ("tasklist.exe");
InputStream procOutput = proc.getInputStream ();
if (0 == proc.waitFor ()) {
// TODO scan the procOutput for your data
}
YAJSW (Yet Another Java Service Wrapper) looks like it has JNA-based implementations of its org.rzo.yajsw.os.TaskList interface for win32, linux, bsd and solaris and is under an LGPL license. I haven't tried calling this code directly, but YAJSW works really well when I've used it in the past, so you shouldn't have too many worries.
You can easily retrieve the list of running processes using jProcesses
List<ProcessInfo> processesList = JProcesses.getProcessList();
for (final ProcessInfo processInfo : processesList) {
System.out.println("Process PID: " + processInfo.getPid());
System.out.println("Process Name: " + processInfo.getName());
System.out.println("Process Used Time: " + processInfo.getTime());
System.out.println("Full command: " + processInfo.getCommand());
System.out.println("------------------");
}
There is no platform-neutral way of doing this. In the 1.6 release of Java, a "Desktop" class was added the allows portable ways of browsing, editing, mailing, opening, and printing URI's. It is possible this class may someday be extended to support processes, but I doubt it.
If you are only curious in Java processes, you can use the java.lang.management api for getting thread/memory information on the JVM.
For windows I use following:
Process process = new ProcessBuilder("tasklist.exe", "/fo", "csv", "/nh").start();
new Thread(() -> {
Scanner sc = new Scanner(process.getInputStream());
if (sc.hasNextLine()) sc.nextLine();
while (sc.hasNextLine()) {
String line = sc.nextLine();
String[] parts = line.split(",");
String unq = parts[0].substring(1).replaceFirst(".$", "");
String pid = parts[1].substring(1).replaceFirst(".$", "");
System.out.println(unq + " " + pid);
}
}).start();
process.waitFor();
System.out.println("Done");
This might be useful for apps with a bundled JRE: I scan for the folder name that i'm running the application from: so if you're application is executing from:
C:\Dev\build\SomeJavaApp\jre-9.0.1\bin\javaw.exe
then you can find if it's already running in J9, by:
public static void main(String[] args) {
AtomicBoolean isRunning = new AtomicBoolean(false);
ProcessHandle.allProcesses()
.filter(ph -> ph.info().command().isPresent() && ph.info().command().get().contains("SomeJavaApp"))
.forEach((process) -> {
isRunning.set(true);
});
if (isRunning.get()) System.out.println("SomeJavaApp is running already");
}
Using code to parse ps aux for linux and tasklist for windows are your best options, until something more general comes along.
For windows, you can reference: http://www.rgagnon.com/javadetails/java-0593.html
Linux can pipe the results of ps aux through grep too, which would make processing/searching quick and easy. I'm sure you can find something similar for windows too.
The below program will be compatible with Java 9+ version only...
To get the CurrentProcess information,
public class CurrentProcess {
public static void main(String[] args) {
ProcessHandle handle = ProcessHandle.current();
System.out.println("Current Running Process Id: "+handle.pid());
ProcessHandle.Info info = handle.info();
System.out.println("ProcessHandle.Info : "+info);
}
}
For all running processes,
import java.util.List;
import java.util.stream.Collectors;
public class AllProcesses {
public static void main(String[] args) {
ProcessHandle.allProcesses().forEach(processHandle -> {
System.out.println(processHandle.pid()+" "+processHandle.info());
});
}
}
String line;
Process process = Runtime.getRuntime().exec("ps -e");
process.getOutputStream().close();
BufferedReader input =
new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line); //<-- Parse data here.
}
input.close();
We have to use process.getOutputStream.close() otherwise it will get locked in while loop.
package com.vipul;
import java.applet.Applet;
import java.awt.Checkbox;
import java.awt.Choice;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class BatchExecuteService extends Applet {
public Choice choice;
public void init()
{
setFont(new Font("Helvetica", Font.BOLD, 36));
choice = new Choice();
}
public static void main(String[] args) {
BatchExecuteService batchExecuteService = new BatchExecuteService();
batchExecuteService.run();
}
List<String> processList = new ArrayList<String>();
public void run() {
try {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("D:\\server.bat");
process.getOutputStream().close();
InputStream inputStream = process.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(
inputStream);
BufferedReader bufferedrReader = new BufferedReader(
inputstreamreader);
BufferedReader bufferedrReader1 = new BufferedReader(
inputstreamreader);
String strLine = "";
String x[]=new String[100];
int i=0;
int t=0;
while ((strLine = bufferedrReader.readLine()) != null)
{
// System.out.println(strLine);
String[] a=strLine.split(",");
x[i++]=a[0];
}
// System.out.println("Length : "+i);
for(int j=2;j<i;j++)
{
System.out.println(x[j]);
}
}
catch (IOException ioException)
{
ioException.printStackTrace();
}
}
}
You can create batch file like
TASKLIST /v /FI "STATUS eq running" /FO "CSV" /FI "Username eq LHPL002\soft" /FI "MEMUSAGE gt 10000" /FI "Windowtitle ne N/A" /NH
This is my code for a function that gets the tasks and gets their names, also adding them into a list to be accessed from a list. It creates temp files with the data, reads the files and gets the task name with the .exe suffix, and arranges the files to be deleted when the program has exited with System.exit(0), it also hides the processes being used to get the tasks and also java.exe so that the user can't accidentally kill the process that runs the program all together.
private static final DefaultListModel tasks = new DefaultListModel();
public static void getTasks()
{
new Thread()
{
#Override
public void run()
{
try
{
File batchFile = File.createTempFile("batchFile", ".bat");
File logFile = File.createTempFile("log", ".txt");
String logFilePath = logFile.getAbsolutePath();
try (PrintWriter fileCreator = new PrintWriter(batchFile))
{
String[] linesToPrint = {"#echo off", "tasklist.exe >>" + logFilePath, "exit"};
for(String string:linesToPrint)
{
fileCreator.println(string);
}
fileCreator.close();
}
int task = Runtime.getRuntime().exec(batchFile.getAbsolutePath()).waitFor();
if(task == 0)
{
FileReader fileOpener = new FileReader(logFile);
try (BufferedReader reader = new BufferedReader(fileOpener))
{
String line;
while(true)
{
line = reader.readLine();
if(line != null)
{
if(line.endsWith("K"))
{
if(line.contains(".exe"))
{
int index = line.lastIndexOf(".exe", line.length());
String taskName = line.substring(0, index + 4);
if(! taskName.equals("tasklist.exe") && ! taskName.equals("cmd.exe") && ! taskName.equals("java.exe"))
{
tasks.addElement(taskName);
}
}
}
}
else
{
reader.close();
break;
}
}
}
}
batchFile.deleteOnExit();
logFile.deleteOnExit();
}
catch (FileNotFoundException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException | InterruptedException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
catch (NullPointerException ex)
{
// This stops errors from being thrown on an empty line
}
}
}.start();
}
public static void killTask(String taskName)
{
new Thread()
{
#Override
public void run()
{
try
{
Runtime.getRuntime().exec("taskkill.exe /IM " + taskName);
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
}