Problem
In short, if you try out the following snippet:
Scanner scanner = new Scanner(System.in);
String text = scanner.nextLine(); // enter ₂
System.out.println(text); // 2, not ₂
and enter a subscript number, like ₂, text is actually 2, without subscript.
Tests
Now, I tried to factor out some classic reasons here.
Printing?
You can also compare the string instead of printing it, and it is still incorrect:
Scanner scanner = new Scanner(System.in);
String text = scanner.nextLine(); // enter ₂
System.out.println(text.equals("₂")); // false
System.out.println(text.equals("2")); // true
Scanner?
Scanner is capable of doing it correctly, for example if the input is given as String:
Scanner scanner = new Scanner("₂");
String text = scanner.nextLine();
System.out.println(text); // now prints ₂
System.in?
The issue is still present if factoring out Scanner completely, for example:
byte[] data = System.in.readAllBytes(); // enter ₂
String text = new String(data, StandardCharsets.UTF_8).trim();
System.out.println(text); // 2, not ₂
Encoding?
It does not seem to be a general problem with Unicode/encoding. When entering another character, such as 🤔, it works as expected.
Scanner scanner = new Scanner(System.in);
String text = scanner.nextLine(); // enter 🤔
System.out.println(text); // 🤔
Hypothesis
It seems that the subscript is lost between the console input and System.in, possibly even before reaching Java at all.
Maybe this is a console specific quirk I am not aware of? I tried it with VSC and Windows CMD (Java 18).
Related
I've tried different uses for Scanners (I want it to read in Files but I also tried just Strings), and it just skips over the code as if it doesn't exist. No error messages are shown.
public static void main(String[] args)
throws FileNotFoundException {
Scanner test = new Scanner(System.in);
String testLine = test.next();
Scanner input = new Scanner(new File("data.txt"));
while(input.hasNextLine){
String name = input.nextLine();
String letters = input.nextLine();
System.out.println(name + ": " + letters);
}
}
Your code doesn't compile, because hasNextLine() is a function, not a class member.
You are actually reading from System.in at test.next(); - you have to enter some text, then your code will continue to run. It's just waiting for a user input - thus no exception is thrown.
At this line of code:
String testLine = test.next();
your program is waiting for your input. It cannot proceed to next line till you provide an input.
EDIT:
Taking cue from Charlie's comment below, here is a quote about System.in from docs.
The "standard" input stream. This stream is already open and ready to supply input data. Typically this stream corresponds to keyboard input or another input source specified by the host environment or user.
More here..
I know that by default, the Scanner skips over whitespaces and newlines.
There is something wrong with my code because my Scanner does not ignore "\n".
For example: the input is "this is\na test." and the desired output should be ""this is a test."
this is what I did so far:
Scanner scan = new Scanner(System.in);
String token = scan.nextLine();
String[] output = token.split("\\s+");
for (int i = 0; i < output.length; i++) {
if (hashmap.containsKey(output[i])) {
output[i] = hashmap.get(output[i]);
}
System.out.print(output[i]);
if (i != output.length - 1) {
System.out.print(" ");
}
nextLine() ignores the specified delimiter (as optionally set by useDelimiter()), and reads to the end of the current line.
Since input is two lines:
this is
a test.
only the first line (this is) is returned.
You then split that on whitespace, so output will contain [this, is].
Since you never use the scanner again, the second line (a test.) will never be read.
In essence, your title is right on point: Java Scanner does not ignore new lines (\n)
It specifically processed the newline when you called nextLine().
You don't have to use a Scanner to do this
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String result = in.lines().collect(Collectors.joining(" "));
Or if you really want to use a Scanner this should also work
Scanner scanner = new Scanner(System.in);
Spliterator<String> si = Spliterators.spliteratorUnknownSize(scanner, Spliterator.ORDERED);
String result = StreamSupport.stream(si, false).collect(Collectors.joining(" "));
I am a beginner. Reading from text file in Java using a scanner. This code just to read the first 3 tokens isn't working:
try{
Scanner scFile = new Scanner (new File ("readhere.txt")).useDelimiter("#");
String first = scFile.next();
String second = scFile.next();
int third = scFile.nextInt(); // error here. Why cant I store the integer?
}
catch(FileNotFoundException e){
System.out.println("Error");
}
I am trying to read just the first 3 tokens:
Andrew#Smith#21
John#Morris#55
the problem occurs when reading 21. java.util.InputMismatchException
The scanner is including the carriage return character(s) as part of the next readable token which produces an invalid integer. You could do
Scanner scanner = new Scanner(new File("readhere.txt")).useDelimiter("#|\r\n");
Here a user enters a list of 1's and 0's.... so an input would 10001010. However I want it to read from a text file... my text file input.txt also containes 10001010... need the coverDataArray array to be fed the same string from the console as from a file.
I tried Datainput stream however, it throws me the exception
'
Scanner in = new Scanner (System.in);
String data1="";
...
.....
try{
System.out.println("Enter the binary bits");
data1 = in.next();
for ( int i = 0; i < data1.length(); i++)
{
covertDataArray[i] = Byte.parseByte(data1.substring( i, i+1));
}'
You can pass a File Object instead of System.in to Scanner constructor. Try it as shown below:
String fileName = "input.txt";
File file = new File(fileName);
Scanner scanner = new Scanner(file);
String s = "";
while(scanner.hasNextLine()){
s = scanner.nextLine();
// your code. You can also use scanner.next() to read word by word instead of nextLine()
}
Byte.parseByte(data1.substring( i, i+1));
Your exception is caused by the fact that you're going up to length - 1, then length - 1 + 1, which is length, which is goign to cause your ArrayOutOfBoundsException. This can be seen on this line:
covertDataArray[i] = Byte.parseByte(data1.substring( i, i+1));
At one point, i is equal to length-1, or the last index in your String. You then attempt to access the next element, which doesn't exist.
And as for your file, you can pass a File object into the Scanner.
Example
Either..
File file = new File("yourfile.txt");
Scanner s = new Scanner(file);
You are trying to use Byte.parseByte as a methode of parsing binairy input, this doesn't really work as parseByte will try to take a numerical input and parse it into a number between -128 and 127. You should use a different method.
I have a scanner in my program that reads in parts of the file and formats them for HTML. When I am reading my file, I need to know how to make the scanner know that it is at the end of a line and start writing to the next line.
Here is the relevant part of my code, let me know if I left anything out :
//scanner object to read the input file
Scanner sc = new Scanner(file);
//filewriter object for writing to the output file
FileWriter fWrite = new FileWriter(outFile);
//Reads in the input file 1 word at a time and decides how to
////add it to the output file
while (sc.hasNext() == true)
{
String tempString = sc.next();
if (colorMap.containsKey(tempString) == true)
{
String word = tempString;
String color = colorMap.get(word);
String codeOut = colorize(word, color);
fWrite.write(codeOut + " ");
}
else
{
fWrite.write(tempString + " ");
}
}
//closes the files
reader.close();
fWrite.close();
sc.close();
I found out about sc.nextLine(), but I still don't know how to determine when I am at the end of a line.
If you want to use only Scanner, you need to create a temp string instantiate it to nextLine() of the grid of data (so it returns only the line it skipped) and a new Scanner object scanning the temp string. This way you're only using that line and hasNext() won't return a false positive (It isn't really a false positive because that's what it was meant to do, but in your situation it would technically be). You just keep nextLine()ing the first scanner and changing the temp string and the second scanner to scan each new line etc.
Lines are usually delimitted by \n or \r so if you need to check for it you can try doing it that way, though I'm not sure why you'd want to since you are already using nextLine() to read a whole line.
There is Scanner.hasNextLine() if you are worried about hasNext() not working for your specific case (not sure why it wouldn't though).
you can use the method hasNextLine to iterate the file line by line instead of word by word, then split the line by whitespaces and make your operations on the word
here is the same code using hasNextLine and split
//scanner object to read the input file
Scanner sc = new Scanner(file);
//filewriter object for writing to the output file
FileWriter fWrite = new FileWriter(outFile);
//get the line separator for the current platform
String newLine = System.getProperty("line.separator");
//Reads in the input file 1 word at a time and decides how to
////add it to the output file
while (sc.hasNextLine())
{
// split the line by whitespaces [ \t\n\x0B\f\r]
String[] words = sc.nextLine().split("\\s");
for(String word : words)
{
if (colorMap.containsKey(word))
{
String color = colorMap.get(word);
String codeOut = colorize(word, color);
fWrite.write(codeOut + " ");
}
else
{
fWrite.write(word + " ");
}
}
fWrite.write(newLine);
}
//closes the files
reader.close();
fWrite.close();
sc.close();
Wow I've been using java for 10 years and have never heard of scanner!
It appears to use white space delimiters by default so you can't tell when an end of line occurs.
Looks like you can change the delimiters of the scanner - see the example at Scanner Class:
String input = "1 fish 2 fish red fish blue fish";
Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
System.out.println(s.nextInt());
System.out.println(s.nextInt());
System.out.println(s.next());
System.out.println(s.next());
s.close();