I am trying to print out a message based on whether or not a previous specific message was printed. Here is my code:
public class Main {
public static Runnable getRunnable() {
return () -> {
System.out.println("Hello from a thread");
};
}
public static void main(String[] args){
new Thread(getRunnable()).start();
Scanner scanner = new Scanner(System.in);
String name = scanner.next();
if (name.equals("Hello from a thread")) {
System.out.println("Hi!");
} else {
System.out.println("That's not nice");
}
}
}
I know that Scanner is probably no the solution here, but whenever I try something else like System.console.readLine(), which is probably also not correct, it prints out a NullPointerException. What am I supposed to use here to read previous output?
UPDATE: Hey, I tried it again but it didn't work out... not sure why again. Here's my updated code
public static ByteArrayOutputStream baos = new ByteArrayOutputStream();
public static PrintStream ps = new PrintStream(baos);
public static PrintStream old = System.out;
public static Runnable getRunnable() {
System.out.println("Hello from a thread");
return () -> {
System.setOut(ps);
System.out.println("Hello from a thread");
};
}
public static void main(String[] args){
new Thread(getRunnable()).start();
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
System.out.println("Somethings wrong!");
}
System.out.flush();
System.setOut(old);
if (baos.toString().equals("Hello from a thread")) {
System.out.println("Hello other thread!");
}
}
}
System.out is not System.in
System.out is the standard output stream, which usually prints to console. System.in is the standard input stream, which usually is taken from console. You can do setOut, setIn, and setErr to change the I/O streams, so for your case, you would need to redirect in to read from a source and out to output to that source. You may consider using an ArrayList to store and retrieve the output / input:
final List<Integer> list = new ArrayList<>();
System.setOut(new PrintStream(new OutputStream() {
public void write(int b) {
list.add(b);
}
}));
System.setIn(new InputStream() {
public int read() {
if (list.size() == 0) return -1;
return list.remove(0);
}
});
(Note that for various reasons, you probably want to do setErr so you can still output things properly.)
You can try a working example of this here
Related
I am having an issue with my instance of BufferedReader not waiting for the user to input before moving forward.
static BufferedReader in;
public class {
public static void main(String[] args) {
try{
in = new BufferedReader(new InputStreamReader(System.in));
String input;
System.out.println("prompt");
input = in.readLine();
if(input.equals("Y")){
//do something
}else {
//do something else
}
}catch(IOException ioe) {
ioe.printStackTrace();
}
}
}
What happens is I when I run the program, it simply skips over the in.readLine() and throws a null exception at the if statement. I am at a loss on what is happening, as I used the same code for another project that still works.
Thanks!
Found the answer. Using gradle to run the program and my task didn't have the parameter for standardInput = System.in. Still getting used to project building software!
Yes you have to treat the exception, just add this:
public static void main(String[] args) throws IOException {
in = new BufferedReader(new InputStreamReader(System.in));
String input;
System.out.println("prompt");
input = in.readLine();
if(input.equals("Y")){
System.out.println("it works !!");
}else {
System.out.println("it's not a Y :(");
}
}
I have a piece of practice code that is supposed to accept 1010 as the code when a user enters the code on the keyboard. The thread that keeps checking if the code was entered right wont run unless i put a Thread.sleep(1); in the run()
I wanted to know whats the reason behind this.
Class1:
import java.util.Scanner;
public class Class1 {
private static boolean valid = true, accepted = false, exit = false;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
newThread t1 = new newThread();
t1.start();
do {
try {
int code = Integer.parseInt(input.nextLine());
if(code == 1010)
accepted = true;
else
System.out.println("Please try again!");
}catch(Exception e) {
System.out.println("Please try again!");
}
}while(!exit);
}
public static boolean getValid() {
return valid;
}
public static void setValid(boolean input) {
valid = input;
}
public static boolean getAccepted() {
return accepted;
}
public static void setAccepted(boolean input) {
accepted = input;
}
}
newThread:
public class newThread extends Thread{
public void run() {
do {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(Class1.getAccepted())
Class1.setValid(false);
}while(Class1.getValid());
System.out.println("Code accepted");
}
}
Expected without Thread.sleep(1);:
1010
Code accepted
Actual results:
1010
Without sleep the newThread consumes all cpu and has no natural break point. In the
Java Language Specification you can read more about it.
I'm writing a Java program in which I read a line from Console, and do some processing around it. The processing might take 1-2 seconds (i.e. takes longer than the input rate), while I might keep receiving 50 lines per second.
Although there were some similar questions, they were addressing C/C++ and not Java. So my fundamental question is below:
While still processing an input/line, am I blocked from receiving new inputs? Or somehow they are queued in the system/JVM? Or better ask this way: Do I miss any lines while processing takes time? I don't want to miss any lines by any means.
Here is my code snippet:
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
//process line. Can take 1-2 seconds.
processInput(sc.nextLine());
}
sc.close();
UPDATE:
As suggested, I came up with making my code more thread-friendly, using Executors:
ExecutorService executorService = Executors.newFixedThreadPool(10);
while (sc.hasNext()) {
executorService.submit(new Runnable() {
public void run() {
processInput(sc.nextLine());
}
});
}
Just compare these two samples:
Frist, linear without multiple threads:
public class SampleClass {
public static void main(String[] args) {
SampleClass instance = new SampleClass();
instance.start();
}
private void start() {
Scanner sc = new Scanner(System.in);
String input;
while (!(input = sc.nextLine()).equals("exit")) {
processInput(input);
}
sc.close();
}
private void processInput(String input) {
try {
Thread.sleep(2000);
System.out.println("input: " + input);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Then, using a new thread for every input processing:
public class SampleClass {
public static void main(String[] args) {
SampleClass instance = new SampleClass();
instance.start();
}
private void start() {
Scanner sc = new Scanner(System.in);
String input;
while (!(input = sc.nextLine()).equals("exit")) {
processInput(input);
}
sc.close();
}
private void processInput(String input) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("input: " + input);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
}
Just try it. In both cases you don't miss input, but the difference is that without new threads the processing time adds up (of course) - it doesn't run parallel.
It is blocking, although the documentation could have been clearer: It keeps saying "A scanning operation may block waiting for input." While it could theoretically throw a NoSuchElementException instead of blocking, it seems to me that this is up to the implementation.
Is there a way to save the whole console output to a file when multithreading? I'm working with 5 threads. I had this idea that i can put a printstream in the run-method.
example:
public void run() {
try{
PrintStream out = new PrintStream(file);
stopExecute stop = new stopExecute();
Thread t = new Thread(stop);
Scanner in = new Scanner(System.in);
t.start();
while (!in.hasNextLine())
{
classThatUsingMultipleThrads();
System.out.println("Finished");
anotherClassThatUsingThreads();
System.out.println("Finished");
}
System.out.prinln("User stopped the execution");
stop.keepRunning = false;
System.setOut(out);
}
catch(IOException e){System.out.println(e);}
Problem here is that it's only saving the output "User stoped the execution" and everything in the whileloop are not saved. Or the outputstream from other classes.
I've tried to put the
System.setOut(out);
in the while-loop, but didn't help.
Edit: Spell correction
try {
System.setOut(new PrintStream(new File("output-file.txt")));
}
catch (Exception e) {
e.printStackTrace();
}
thanks to: System.out to a file in java
You should probably look into using a logging library such as Log4J. However you could also use something like a TeeOutputStream. This type of output stream writes to 2 other streams when called. A few libraries have great implementations but you can also write one yourself. I whipped this one up real quick.
You could set the output stream for your entire program in your main method to use this TeePrintStream, then all calls to System.out.* will write data to the usual System.out and your FileOutputStream.
Theres also an implementation of the TeePrintStream here http://www.java2s.com/Code/Java/File-Input-Output/TeePrintStreamteesallPrintStreamoperationsintoafileratherliketheUNIXtee1command.htm
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
public class SO34042494 {
public static void main(String[] args) throws FileNotFoundException {
System.setOut(new TeePrintStream(System.out, new FileOutputStream(new File("x:\\output.txt"))));
System.out.println("Check check");
System.out.println("1");
System.out.println(2);
System.out.println(3L);
}
public static class TeePrintStream extends PrintStream {
private final OutputStream tee;
public TeePrintStream(PrintStream original, OutputStream tee) {
super(original);
this.tee = tee;
}
#Override
public void write(byte[] b) throws IOException {
super.write(b);
tee.write(b);
}
#Override
public void write(byte[] buf, int off, int len) {
super.write(buf, off, len);
try {
tee.write(buf, off, len);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
public void write(int b) {
super.write(b);
try {
tee.write(b);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
public synchronized void close() {
try {
tee.close();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
super.close();
}
}
}
}
The TeePrintStream I have here is something I just threw together, please if your going to use this in a production project polish it up and test it thoroughly
Okej i think i solved it. In my main i just did like this:
public static void main(String[] args) {
Prinstream out = new Prinststream(file);
/*
Do some things like start threads, call objects etc..
.
.
.
.
*/
System.setOut(out);
I think that when all threads are started and doing their things(i do assign a object to each thread) the printstream will catch every console-output that occurs in other classes.
This didn't work before i edited my stopExecute class.
public class stopExecute implements Runnable {
Scanner scan = new Scanner(System.in);
private Object[] obj;
public stopExecute(Object[] obj)
{
this.obj = obj;
}
public void run() {
while(true){
stop();
}
}
public void stop() {
if(scan.hasNextLine()){
System.out.println("Stopped");
System.exit(0);
}
}
}
Thank you for your help guys. I will look into your suggestions and try them. In this solution i'm unable to use Log4J. But i will definitely check it out.
I have made a program that is supposed to create a file, write to it, and then read from it. The problem comes with readFile(), where suddenly hasNext() is undefined for Formatter? I thought that
while (file.hasNext()) {
String a = file.next();
System.out.println(a);
would go as long as there was something in the file, copy it to a and then print a? What am I doing wrong?
import java.util.*;
import java.io.*;
class Oppgave3
{
public static void main(String[] args)
{
Kryptosystem a = new Kryptosystem();
a.createFile();
a.writeFile();
a.openFile();
a.readFile();
a.closeFile();
}
}
class Kryptosystem
{
public Kryptosystem(){}
Scanner keyboard = new Scanner (System.in);
private Formatter file;
private Scanner x;
public void createFile(){
try {
file = new Formatter("kryptFil.txt");
}
catch (Exception e) {
System.out.println("could not create file");
}
}
public void writeFile(){
System.out.println("what do you want to write");
String tekst = keyboard.nextLine();
file.format(tekst);
}
public void openFile() {
try {
x = new Scanner (new File("kryptFil.txt"));
}
catch (Exception e) {
System.out.println("something is wrong with the file");
}
}
public void readFile() {
while (file.hasNext()) {
String a = x.next();
System.out.println(a);
}
}
public void closeFile() {
file.close();
}
}
You state:
where suddenly hasNext() is undefined for Formatter?
Please have a look at the Formatter API as it will show you that this class has no hasNext() method, and your Java compiler is correctly telling you the same thing. Similarly, the Scanner API will show you that it in fact has the method you need.
You're opening the same File in a Scanner, called x, and this is what you want to use to read from the file. So the solution is to call hasNext() on the Scanner variable:
while (x.hasNext()) { // x, not file
String a = x.next();
System.out.println(a);
}
Note I'm not sure why you opened the file a second time and placed it into a Formatter object. Please clarify your motivation for this. I believe that you wish to write to the file with this, but you certainly would not try to use it to read from the File, which is what you're use of hasNext() is trying to do. I think you were just a little confused on which tool to use is all.