How to give a blank line to an InputStream using IOUtils.toInputStream - java

I have code which consumes an InputStream through a Scanner which looks like
String input = scanner.nextLine().toLowerCase();
if (input.isEmpty()) {
return defaultAnswer;
} else if (input.startsWith("y")) {
return true;
} else if (input.startsWith("n")) {
return false;
}
where the scanner is initialized by a given InputStream coming from IOUtils.toInputStream("someString").
How would I be able to test the if (input.isEmpty()) path?
EDIT:
I swapped two lines in my code, and empty string ("") results in a NoSuchElementException, and a newline or carriage return results in an empty string being returned.

Either using IOUtils.toInputStream("") or new ByteArrayInputStream(new byte[0]) may work.
The latter would certainly provide an empty stream, but it may make your code fail because there isn't an empty line to read - there's no line terminator. For example:
import java.io.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
InputStream stream = new ByteArrayInputStream(new byte[0]);
Scanner scanner = new Scanner(stream, "UTF-8");
String line = scanner.nextLine();
System.out.println(line);
}
}
That fails with:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at Test.main(Test.java:10)
You can use Scanner.hasNextLine() to check whether a call to nextLine() is appropriate or not. You may want to do that in your code. It really depends on whether you're trying to model "input ended without a line" or "the user entered an empty line". Those are significantly different situations, and you should consider both of them.
If you want to provide a stream which contains a line break (i.e. "the user entered an empty line") then you might want to use IOUtils.toInputStream("\n") instead. I'm nervous about the fact that that's not specifying a Charset though - you should carefully consider what encoding you expect your input to be in.

Related

How to allow Java to take in /n from scanner and print ASCII value

I'm doing a java project on codeZinger where I need to take in a character value from the scanner and print the ASCII value. So far the code I have works for everything besides the "/n" character. In that case, codezinger returns the error "Exception in thread "main" java.lang.NullPointerException scanner".
I have attached my code below, I've tried everything and it won't work. I'm new to java from c++.
I tried even manually testing for /n using an if statement and that didn't work
public class Solution {
public static void main(String[] args) {
//creating input stream
Scanner input = new Scanner(System.in);
// allows character input from input stream
char charIn = input.findInLine(".").charAt(0);
if(input.equals("\\n"))
{
System.out.print("10");
}
// casts character to type int to get ascii value
int intVal = (int)charIn;
System.out.print(intVal);
}
}
input.equals() method in java never takes its parameter in apostrophe.
Please go through this once :
https://www.jquery-az.com/learn-java-equals-method-5-examples/
Moreover /n doesn't exist in java. If you have to print a line(Give a break) then you have to use System.out.println() , simply, and it will be printed in next line.
Also go through this for printing ASCII value
https://www.javatpoint.com/how-to-print-ascii-value-in-java
int code;
while ((code = System.in.read()) != -1) {
System.out.format("0x%02X ", code);
}

Scanner.nextLine() ignores whitespace? (Java)

I have a command-line game and am testing with JUnit, this is the test:
#Test
public void testBattle() throws IOException{
String input = "go forward\ngo left\ntake Pointy Stick\ngo backward\ngo " +
"right\nnormal attack\nnormal attack\nquit\n";
provideInput(input);
actual = new File("src/main/testFiles/testBattle.txt");
expected = new File("src/main/testFiles/testBattleExpected.txt");
PrintStream o = new PrintStream(actual);
System.setOut(o);
ui.gameLoop();
assertTrue(FileUtils.contentEqualsIgnoreEOL(actual, expected, null));
}
And this is the provide input method:
private void provideInput(String data) {
String newdata = data.trim();
testIn = new ByteArrayInputStream(newdata.getBytes());
System.setIn(testIn);
}
I'm doing scanner nextline so:
command = input.nextLine().toLowerCase().trim();
where "input" here represents the scanner object
but I'm still getting this error, specifically when the first "normal attack" is passed into System.in
java.util.NoSuchElementException: No line found
on that line above. I thought nextline ignored whitespace? If not did I format my string wrong to not include it?
EDIT:
From the first few lines of UI.gameLoop() I only initialize the scanner once.
public void gameLoop() throws IOException, JsonSyntaxException {
input = new Scanner(System.in);
engine = new GameEngine(path);
I thought nextline ignored whitespace?
Nope. According to the javadocs, it reads past the next end-of-line sequence (or to EOF), and then returns everything up to but not including the end-of-line sequence.
If you are getting
java.util.NoSuchElementException: No line found
that means that the Scanner has already reached the end of the input stream, or (maybe) the Scanner is trying to read from an input stream that was prematurely closed somewhere else in your code.
We can make guesses about what the real problem is, but without seeing >>your<< minimal reproducible example, we can't take this much further.
Actually, I just spotted a clue:
... I am testing with JUnit ...
This is possibly at the root of your problems. A JVM can only "read to the end of System.in" once in its lifetime. If you have two or more JUnit tests that need to do this, it is going to be difficult, unless you can find a way to "mock" the System.in variable.
It may be simpler to reorganize your code so that you take the input from some stream that is passed to your game code as a parameter. By reorganizing you can make it easier to write unit tests.
There's not a lot to go on, but I'm guessing you're creating multiple Scanners, one for each time you want to read a line. This usually works ok interactively since humans are slow typers, but fails when each Scanner's readahead ends up consuming multiple lines.
You can see the difference in this MCVE:
import java.util.*;
import java.io.*;
class Foo {
public static void main(String[] args) throws Exception {
String newdata = "go forward\ngo left\ntake Pointy Stick\ngo backward\ngo " +
"right\nnormal attack\nnormal attack\nquit\n".trim();
ByteArrayInputStream testIn = new ByteArrayInputStream(newdata.getBytes());
System.setIn(testIn);
boolean includeBug = Boolean.valueOf(args[0]);
if (includeBug) {
for(int i=0; i<8; i++) {
Scanner input = new Scanner(System.in);
System.out.println("Read: " + input.nextLine());
}
} else {
Scanner input = new Scanner(System.in);
for(int i=0; i<8; i++) {
System.out.println("Read: " + input.nextLine());
}
}
}
}
When includeBug is true, it creates a new Scanner for each line and crashes like you say. If it's false, it creates a single Scanner and works correctly:
$ javac Foo.java
$ java Foo true
Read: go forward
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1540)
at Foo.main(Foo.java:17)
$ java Foo false
Read: go forward
Read: go left
Read: take Pointy Stick
Read: go backward
(etc)
Are you checking if it has a next line? With Scanners, you usually either have to handle the exception (not really something I'd prefer) or you have to use the hasNextLine() method to avoid the exception.
while (input.hasNextLine()) {
command = input.nextLine().toLowerCase().trim();
}

Java Scanner for peeking something (int, double, line, etc) without advancing position

We know that nextInt(), nextDouble(), nextLine(), etc methods of Java Scanner class parses something (int, double, line, etc) and advances the position of the scanner. But I need a way only for parsing something but not for advancing the position. That means, I need some way for something like peekInt(), peekDouble(), peekLine(), etc methods.
Here is an example for why it may be necessary. Suppose, I have an abstract class Server which has an abstract method respond(Scanner in, PrintWriter out, String clientIp) to be implemented by other classes. Here is the portion of code:
public abstract class Server {
// ... (some initialization variables)
public static final String endSocketMarker = "END";
public final void runServer() {
// ... (multithreading code)
clientSocket = serverSocket.accept();
Scanner in = new Scanner(new BufferedReader(new InputStreamReader(clientSocket.getInputStream())));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String clientIp = in.nextLine();
String marker = "";
do {
respond(in, out, clientIp); // call abstract method
marker = in.nextLine(); //TODO: find a way so that input line is peeked (but not skipped)
} while(!marker.equals(endSocketMarker));
// ... (close client socket)
}
protected abstract void respond(Scanner in, PrintWriter out, String clientIp);
// ... (other methods)
}
Here marker = in.nextLine(); parses the line until a line separator found and then advances the position to the beginning of the next line. If marker.equals(endSocketMarker) is false, then the string assigned in marker cannot be read inside respond(in, out, clientIp) method at all. It must be avoided somehow. I may pass the variable marker into respond(in, out, clientIp), but it will make the code cluttered.
Is there any better way for achieving my goal?
The java.util.Scanner.hasNext() method Returns true if this scanner has another token in its input. This method may block while waiting for input to scan. The scanner does not advance past any input.
There's an example here,
hasNext() example
You can do this by checking for the next token via a Pattern with the corresponding hasNext. This way you are not advancing the position, but you are able to peek the next token (via its pattern)...
import java.io.ByteArrayInputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.util.regex.Pattern;
public class Main {
public static void main(final String[] args) {
final Charset charset = StandardCharsets.UTF_8;
final String endSocketMarker = "END";
final String testString = "This is some test text.\n1234567890\n" + endSocketMarker + "\nThis is still writing...";
final Scanner scan = new Scanner(new ByteArrayInputStream(testString.getBytes(charset)), charset.name());
final Pattern endPattern = Pattern.compile(Pattern.quote(endSocketMarker));
while (!scan.hasNext(endPattern))
System.out.println("Processing input, with first line being: \"" + scan.nextLine() + "\".");
System.out.println("Reached the \"" + scan.nextLine() + "\".");
}
}
The point of converting the testString to an InputStream which is supplied to the Scanner exists just to demonstrate how to use an InputStream with the Scanner. Otherwise I could just simply supply the testString directly to the Scanner's constructor.
I was thinking also about supplying the Scanner with a BufferedInputStream and using mark/reset on the latter, but after some tests and a bit of searching, I found out that Scanner internally uses a buffer. Which means that the Scanner's buffer is getting filled with all the data from the BufferedInputStream, thus advancing the position of the BufferedInputStream without letting us mark the proper location. Even if you create a new Scanner object every time, using the same BufferedInputStream will have the same effect, as the BufferedInputStream will be advanced anyway.

java Bug or feature - Why is this not throwing an exception

Consider the following java code which opens a file, reads all of the data, then tries to read one more line.
public static void main ( String[] argv) {
FileInputStream inFile = null;
try {
inFile = new FileInputStream("DemoRead.txt");
}
catch ( FileNotFoundException ex) {
System.out.println("Could not open file "+ ex.getMessage());
System.exit(0);
}
Scanner inputStream = new Scanner( inFile);
while ( inputStream.hasNext()) {
System.out.println( inputStream.nextLine());
}
System.out.println(inputStream.nextLine());
inputStream.close();
}
I would expect that the final inputStream.nextLine() would throw an exception as there is nothing else to read.
Indeed if I change the while loop to:
while ( true) {
System.out.println ( inputStream.nextLine());
}
It does throw an exception as expected.
This is not making any sense to me. Any insight would be appreciated.
hasNext() can return false before the end of the file if there are no more tokens left. This is the case when there are only delimiters left at the end of the file.
Compare this with hasNextLine(). If you're using nextLine() then the condition should be hasNextLine(). hasNext() is used with next().
1stly hasNext()--Returns true if this scanner has another token in its input. This method may block while waiting for input to scan. The scanner does not advance past any input.But in case of while loop we always get true.
2ndly in case of nextLine()--Advances this scanner past the current line and returns the input that was skipped. This method returns the rest of the current line, excluding any line separator at the end. The position is set to the beginning of the next line.
Since this method continues to search through the input looking for a line separator, it may buffer all of the input searching for the line to skip if no line separators are present.
so,in case of while(true) we are getting always true and at certain point the nextLine() method finds no line separator so gives exception, but in case of while(hasNext()) method it returns false when there is no token in the file so loop breaks so no Exception comes..
Hope this may help you out.

Java Scanner hasNextLine returning false

This is probably due more to my lack of familiarity with the code than anything else, but I keep having the following problem:
I have a text file that has empty lines, and a scanner that goes through the file.
When I use the .hasNextLine() method, it returns false even though there are more lines in the file. I must point out that the file begins with an empty line, and that the text inside has more empty lines in between, and finally ends with empty lines.
But shouldn't it return true regardless of whether the lines have text or not?
Yes, it should.
Try this:
public static void main(String[] args){
Test t = new Test();
t.testHNL(new File("test.txt"));
}
public void testHNL(File f){
try {
Scanner s = new Scanner(new FileInputStream(f));
while(s.hasNextLine()){
System.out.println("There is another line! :: "+s.nextLine());
}
System.out.println("There are no more lines :'(");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Make sure the file "text.txt" exists, and just carriage returns in it. Then run this.
use the .hasNext() method instead of using the .hasNextLine() method.
You are having problems because the .hasNextLine() method returns true only if the next line has some content in it. Whereas the .hasNext() method returns true even if there is any token in the next line(here the token being \n for the next line)
Taken from the source for SUNs (oracles?) 1.5 JDK, anything which matches the following regular expression is treated as a "line". This includes empty lines under Windows or linux/unix.
private static final String LINE_SEPARATOR_PATTERN =
"\r\n|[\n\r\u2028\u2029\u0085]"
So it should return true even if lines are empty except for carriage return.

Categories

Resources