Reading in from System.In - Java

Reading in from System.in - Java

You can use System.in to read from the standard input. It works just like entering it from a keyboard. The OS handles going from file to standard input.

import java.util.Scanner;
class MyProg {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Printing the file passed in:");
while(sc.hasNextLine()) System.out.println(sc.nextLine());
}
}

What is the use of System.in.read()?

May be this example will help you.

import java.io.IOException;

public class MainClass {

public static void main(String[] args) {
int inChar;
System.out.println("Enter a Character:");
try {
inChar = System.in.read();
System.out.print("You entered ");
System.out.println(inChar);
}
catch (IOException e){
System.out.println("Error reading from user");
}
}
}

Problems reading from System.in.read()

I think whether the code will have \r (carriage return), \n (new line) or both \r\n depends upon the platform.

I ran your code on a windows machine and it did print hello twice.

You may want to check the machine you are using and the line separator defined for that environment. Please refer What are the differences between char literals '\n' and '\r' in Java? for further details.

Help on:
1. if
2. switch
3. for
4. while
5. do-while
6. break
7. continue

Choose one (q to quit): 1
choice1
hello
hello

Reading System.out Java Test

Here is a sample how to catch output to the System.out:

java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();    
System.setOut(new java.io.PrintStream(out));

System.out.println("Test output");
System.err.println("Out was: " + out.toString());

Use System.in.read() repeatedly

Here's another one that matches original code intent but provides a Scanner and while loop until there is a match

import java.util.Scanner;

public class GuessTheLetterGame {

public static void main(String[] args) throws java.io.IOException{
Scanner keyboard = new Scanner(System.in);
char answer;
char guess;
boolean right = false;

while(!right){

System.out.print("press a key and press ENTER:");
answer= (char) keyboard.next().charAt(0);

System.out.print("Have a guess and press ENTER: ");
guess= (char) keyboard.next().charAt(0);
if (guess == answer){
System.out.println("**Right**");
right = true;
}
}
}
}

System.in.read() behaviour i can't explain

ENTER on Windows generates 2 characters (CRLF) whereas read() only consumes 1 of them.
You must consume 2 characters for the desired behaviour. Just add another System.in.read() and you will see.

The following explains the generation and consumption of characters when you press ENTER. 13 represents CR and 10 represents LF.

F
13i10r
13s10t
13 10S
13t10r
13i10n
13g10

How to interrupt reading on System.in?

I've written a wrapper InputStream class that allows to be interrupted:

package de.piegames.voicepi.stt;
import java.io.IOException;
import java.io.InputStream;

public class InterruptibleInputStream extends InputStream {

protected final InputStream in;

public InterruptibleInputStream(InputStream in) {
this.in = in;
}

/**
* This will read one byte, blocking if needed. If the thread is interrupted while reading, it will stop and throw
* an {@link IOException}.
*/
@Override
public int read() throws IOException {
while (!Thread.interrupted())
if (in.available() > 0)
return in.read();
else
Thread.yield();
throw new IOException("Thread interrupted while reading");
}

/**
* This will read multiple bytes into a buffer. While reading the first byte it will block and wait in an
* interruptable way until one is available. For the remaining bytes, it will stop reading when none are available
* anymore. If the thread is interrupted, it will return -1.
*/
@Override
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = -1;
while (!Thread.interrupted())
if (in.available() > 0) {
c = in.read();
break;
} else
Thread.yield();
if (c == -1) {
return -1;
}
b[off] = (byte) c;

int i = 1;
try {
for (; i < len; i++) {
c = -1;
if (in.available() > 0)
c = in.read();
if (c == -1) {
break;
}
b[off + i] = (byte) c;
}
} catch (IOException ee) {
}
return i;
}

@Override
public int available() throws IOException {
return in.available();
}

@Override
public void close() throws IOException {
in.close();
}

@Override
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}

@Override
public synchronized void reset() throws IOException {
in.reset();
}

@Override
public boolean markSupported() {
return in.markSupported();
}
}

Adjust the Thread.yield() to sleep as long as the maximum latency you can accept and prepare for some exceptions when interrupting, but apart from that it should work fine.



Related Topics



Leave a reply



Submit