print is blocking BufferedReader input? - java

I am trying to parallel execute my code, but got now a problem.
The code without parallel execution is waiting for input (1) and then he is printing out something (2).
Now I execute my code parallel with the help of a timer (task2) and for the input (1)I got another loop.
Now if I try to write something down but I am not fast enough, the input isn't reading the whole input which was interrupted by the task2 with the print out.
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static PrintStream out = new PrintStream(System.out);
static void test1(BufferedReader in, PrintStream out) throws IOException {
String input = in.readLine();
if (input.equals("test"))
System.out.println("true input");
else System.out.println("false input");
}
public static void main(String[] args) throws IOException {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
while (true) {
System.out.println("print");
Thread.sleep(1000);}}}, 1000);
while (true)
test1(in, out);
}
https://imgur.com/iyIdWeA

You could read single characters until you press Enter.
StringBuilder strBuilder = new StringBuilder();
char ch;
while((ch = in.read()) != '\n'){
strBuilder.append(ch);
}
String input = strBuilder.toString();

Related

Scanner asks for input twice and im slowly loosing my mind

i am trying to get two inputs from the scanner (multiple times if needed).
The code in Question is in the else section of the main function but i decided to share everything since something may collide, i don't know. the problem is that the first scanner(the timed one) works fine but the other two scanners (scanner1) require me to first press enter once then input the data and press enter again. Also if it has something to do with having two scanners then i would like for scanner1 not to be timed. Its not tragic but a flaw and i would like to fix it. Can somebody help me because i am running out of ideas.
Sorry if i made spelling mistakes or if my gramar sucks.
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class TimedScanner implements Runnable
{
public static void main(String[] args) throws IOException {
TimedScanner scanner = new TimedScanner();
System.out.print("Enter the number of searchagents you want to add in 15 second: ");
String input = scanner.nextLine(15000);
if (input == null)
{
System.out.println("\nNothing was entered. Continuing...");
}
else
{
Scanner scanner1 = new Scanner(System.in);
int number = Integer.parseInt(input);
File myFile = new File("searchagent_list.txt");
if (!(myFile.exists())) {
myFile.createNewFile();
}
for (int i = 0; i < number; i++) {
System.out.println("Press Enter!\nEnter the name of searchagent #"+(i+1));
String name = scanner1.nextLine();
System.out.println("Press Enter!\nEnter the adress of searchagent #"+(i+1));
String adress = scanner1.nextLine();
FileWriter fWrite = new FileWriter(myFile, true);
BufferedWriter bWrite = new BufferedWriter(fWrite);
bWrite.write(name+"##"+adress+"##\n");
bWrite.close();
}
System.out.println("Done");
}
}
private Scanner scanner;
private StringBuilder buffer;
private boolean reading;
private Thread t;
public TimedScanner()
{
scanner = new Scanner(System.in);
buffer = new StringBuilder();
reading = false;
t = new Thread(this);
t.setDaemon(true);
t.start();
}
public String nextLine(long time)
{
reading = true;
String result = null;
long startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime < time && result == null)
{
try
{
Thread.sleep(30);
}
catch (InterruptedException e)
{
}
synchronized (buffer)
{
if (buffer.length() > 0)
{
Scanner temp = new Scanner(buffer.toString());
result = temp.nextLine();
}
}
}
reading = false;
return result;
}
#Override
public void run()
{
while (scanner.hasNextLine())
{
String line = scanner.nextLine();
synchronized (buffer)
{
if (reading)
{
buffer.append(line);
buffer.append("\n");
}
else
{
// flush the buffer
if (buffer.length() != 0)
{
buffer.delete(0, buffer.length());
}
}
}
}
}
}```
The return after reading will solve your issue:
#Override
public void run() {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
synchronized (buffer) {
if (reading) {
buffer.append(line);
buffer.append("\n");
return;
} else {
// flush the buffer
if (buffer.length() != 0) {
buffer.delete(0, buffer.length());
}
}
}
}
}
but there is no benefit to create more than one Scanner reference. It's simply reading input from System.in stream.

How to interrupt thread for console reading?

I have such problem: program should read information from console in separate thread, and when l want to close this thread - input remains active. How to close input after interrupting thread? (programm runs at Eclipse IDE)
public static void main(final String[] args) {
for (int i = 0; i < 10; i++){
ChatRunner.reader = new BufferedReader(
new InputStreamReader(System.in, ChatRunner.charset));
//some treatment
final Thread input = new Thread(() -> {
try {
ChatRunner.answerFromConsole = ChatRunner.reader.readLine();
} catch (final IOException ioe) {
//
}
});
input.start();
// some treatment
input.interrupt();
}
}
If l simply close BufferedReader, i can't use it in next step in loop.

Infinite loop while using Scanner to read file Java

So I am trying to parse text files that could be in the form
words words words werdz words
or
words
words
words
words
words
Because of this, I decided to use Scanner instead of BufferedReader, and I'm not very experienced with using Scanner. I am trying to read a file and save to a Collection. Here is the main code and the supplementary methods.
main:
public static void main(String[] args) throws IOException {
LinkedList<String> unmodDict = readDict(new File(args[0]));
String[] unsorted = readUnsorted(new File(args[1]));
...
}
readDict()
public static LinkedList<String> readDict(File file) throws IOException {
//BufferedReader reader = new BufferedReader(new FileReader(file));
Scanner s = new Scanner(new FileReader(file));
String line = null;
LinkedList<String> ll = new LinkedList<>();
int count = 0;
while(s.hasNext()) {
ll.add(s.next());
}
// this loop seems to run finitely.
s.close();
return ll;
}
readUnsorted()
public static String[] readUnsorted(File file) throws IOException {
//BufferedReader reader = new BufferedReader(new FileReader(file));
Scanner reader = new Scanner(new FileReader(file));
int count = 0;
while (reader.hasNext()) {
count++;
}
reader.close();
// The above loop is running infinitely.
Scanner reader2 = new Scanner(new FileReader(file));
String line2 = null;
String[] unsortedWerdz = new String[count];
int i = 0;
while (reader2.hasNext()) {
unsortedWerdz[i] = reader2.next();
i++;
}
reader2.close();
return unsortedWerdz;
}
For some reason, the first while loop in the readUnsorted method is running infinitely but I can't see why since the first loop in the readDict method seems to run fine. Could someone advise me on what to do?
Thanks
It run's forever, since you check if there's a next String avaiable, but you don't retrieve it!
You need to get it via next() like this:
while (reader.hasNext()) {
reader.next();
count++;
}
Otherwise the Scanner will always point at the same (the first) element it reads and always report: Yes, there's another token in here!

How to close a scanner without closing the underlying System.in? [duplicate]

This question already has answers here:
Close Scanner without closing System.in
(3 answers)
Closed last month.
If I close one scanner object and make a new one and try to read some more input, I'm getting the NoSuchElementException exception.
My code works fine but it gives me a warning if I don't close the scanner. However, if I close it to get rid of the warning, I also close System.in... How do I avoid this?
Also, are there any consequences of not closing the scanner?
EDIT: Here's my code:
This is the NameAddressExists() method:
public void NameAddressExists() {
System.out.println("Enter name");
Scanner sc = new Scanner(System.in);
String n = sc.next();
System.out.println("Enter address");
String a = sc.next();
int flag = 0;
for(int i = 0; i < count; i++) {
if(array[i].name .equals(n) && array[i].address .equals(a)) {
System.out.println("True");
flag = 1;
}
}
if(flag != 1) {
new Agency(n, a);
}
sc.close();
}
This is the PanNumberExists() method:
public boolean PanNumberExists() {
Scanner s = new Scanner(System.in);
String n = "";
System.out.println("Enter the 5 digits");
try {
n = s.nextLine();
}catch(Exception e) {
System.out.println(e);
}finally {
s.close();
}
if(n .equals(this.PAN.subSequence(4,9))) {
return true;
}
else {
return false;
}
}
These methods are called from the following main() method:
public static void main(String args[]) {
Agency obj1 = new Agency("XYZ", "ABCD");
Agency obj2 = new Agency("XYZ", "ABCDEFG", "+91083226852521", "ab 1234567", "abcd12345ab");
// Agency obj3 = new Agency("XYZ", "TSRK", "36", "ab 1234567", "abcd12345ab");
obj1.NameAddressExists();
System.out.println(obj2.PanNumberExists());
}
As you can see, I first call the NameAddressExists() method, in which I open, use and close a Scanner named 'sc'. This works fine and gives me the correct output. Next, I call the PanNumberExists() method, in which I open another Scanner named 's' and try to use it to get some input from the user. This is where I receive the NoSuchElementException exception. If I leave the Scanner 'sc' open in my NameAddressExists() method, then I don't get this error.
You can use the Decorator pattern and create custom InputStream that can't be closed, then pass it to the Scanner
import java.io.IOException;
import java.io.InputStream;
public class PreventClosingInputStream extends InputStream {
private InputStream inputStream;
public PreventClosingInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
#Override
public int read() throws IOException {
return inputStream.read();
}
#Override
public void close() throws IOException {
// Don't call super.close();
}
}
Then, in your code:
PreventClosingInputStream in = new PreventClosingInputStream(System.in);
Scanner s = new Scanner(in);
// ...
s.close(); // This will never close System.in as there is underlying PreventClosingInputStream with empty close() method
Using try-with-resources:
try (PreventClosingInputStream in = new PreventClosingInputStream(System.in);
Scanner s = new Scanner(in);) {
// ...
// resources will be automatically closed except of System.in
}

Read in N Lines of an Input Stream and print in reverse order without using array or list type structure?

Using the readLine() method of BufferedReader, can you print the first N lines of a stream in reverse order without using a list or an array?
I think you can do it through recursion with something like:
void printReversed(int n)
{
String line = reader.readLine();
if (n > 0)
printReversed(n-1);
System.out.println(line);
}
How about recursion to reverse the order?
Pseudo code:
reverse(int linesLeft)
if (linesLeft == 0)
return;
String line = readLine();
reverse(linesLeft - 1);
System.out.println(line);
Nice question. Here you have one solution based on coordinated threads. Although it's heavy on resources (1 thread/line of the buffer) it solves your problem within the given constrains. I'm curious to see other solutions.
public class ReversedBufferPrinter {
class Worker implements Runnable {
private final CountDownLatch trigger;
private final CountDownLatch release;
private final String line;
Worker(String line, CountDownLatch release) {
this.trigger = new CountDownLatch(1);
this.release = release;
this.line = line;
}
public CountDownLatch getTriggerLatch() {
return trigger;
}
public void run() {
try {
trigger.await();
} catch (InterruptedException ex) { } // handle
work();
release.countDown();
}
void work() {
System.out.println(line);
}
}
public void reversePrint(BufferedReader reader, int lines) throws IOException {
CountDownLatch initialLatch = new CountDownLatch(1);
CountDownLatch triggerLatch = initialLatch;
int count=0;
String line;
while (count++<lines && (line = reader.readLine())!=null) {
Worker worker = new Worker(line, triggerLatch);
triggerLatch = worker.getTriggerLatch();
new Thread(worker).start();
}
triggerLatch.countDown();
try {
initialLatch.await();
} catch (InterruptedException iex) {
// handle
}
}
public static void main(String [] params) throws Exception {
if (params.length<2) {
System.out.println("usage: ReversedBufferPrinter <file to reverse> <#lines>");
}
String filename = params[0];
int lines = Integer.parseInt(params[1]);
File file = new File(filename);
BufferedReader reader = new BufferedReader(new FileReader(file));
ReversedBufferPrinter printer = new ReversedBufferPrinter();
printer.reversePrint(reader, lines);
}
}
Here you have another alternative, based on BufferedReader & StringBuilder manipulations. More manageable in terms of computer resources needed.
public void reversePrint(BufferedReader bufReader, int lines) throws IOException {
BufferedReader resultBufferReader = null;
{
String line;
StringBuilder sb = new StringBuilder();
int count = 0;
while (count++<lines && (line = bufReader.readLine())!=null) {
sb.append('\n'); // restore new line marker for BufferedReader to consume.
sb.append(new StringBuilder(line).reverse());
}
resultBufferReader = new BufferedReader(new StringReader(sb.reverse().toString()));
}
{
String line;
while ((line = resultBufferReader.readLine())!=null) {
System.out.println(line);
}
}
}
it will also require implicit data structures, but you can spawn threads, run them inorder, and make each thread read a line and wait a decreasing amount of time. the result will be: the last thread will run first, and the first one will run last, each one printing its line. (the interval between them will have to be large enough to ensure large "safety margins")
I have no idea how, if any, that can be done with no explicit/implicit data storage.
Prepend each line you read to a string, and print the string. If you run out of lines to read, you just print what you have.
Alternatively, if you are certain of the number of lines you have, and you do not wish to use a string:
void printReversed(int n, BufferedReader reader)
{
LineNumberReader lineReader = new LineNumberReader(reader);
while (--i >= 0)
{
lineReader.setLineNumber(i);
System.out.println(lineReader.readLine());
}
}

Categories

Resources