Using a scanner to extract data with delimiters by line - java

I am extracting data from a file. I am having trouble with using the delimiters while reading through the file.
My file is ordered like so:
0 Name 0
1 Name1 1
The structure is an integer, a tab (\t), a string, a tab (\t), another integer, and then a newline (\n).
I have tried to use a compound delimiter as referenced in this question:
Java - Using multiple delimiters in a scanner
However, I am still getting an InputMismatch Exception when I run the following code:
while(readStations.hasNextLine()) {
327 tempSID = readStations.nextInt();
328 tempName = readStations.next();
329 tempLine = readStations.nextInt();
//More code here
}
It calls this error on line two of the above code...
I am not sure why, and help would be appreciated, Thanks.
The current output runs as such for the code:
Exception in thread "main" java.util.InputMismatchException
...stuff...
at Metro.declarations(Metro.java:329)

Newline is most likely causing you issues. Try this
public class TestScanner {
public static void main(String[] args) throws IOException {
try {
Scanner scanner = new Scanner(new File("data.txt"));
scanner.useDelimiter(System.getProperty("line.separator"));
while (scanner.hasNext()) {
String[] tokens = scanner.next().split("\t");
for(String token : tokens) {
System.out.print("[" + token + "]");
}
System.out.print("\n");
}
scanner.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}

i think when the scanner separates input like this you can only use input.next() not next int: or keep the same type.

Related

What am I missing? NumberFormatException error

I want to read from a txt file which contains just numbers. Such file is in UTF-8, and the numbers are separated only by new lines (no spaces or any other things) just that. Whenever i call Integer.valueOf(myString), i get the exception.
This exception is really strange, because if i create a predefined string, such as "56\n", and use .trim(), it works perfectly. But in my code, not only that is not the case, but the exception texts says that what it couldn't convert was "54856". I have tried to introduce a new line there, and then the error text says it couldn't convert "54856
"
With that out of the question, what am I missing?
File ficheroEntrada = new File("C:\\in.txt");
FileReader entrada =new FileReader(ficheroEntrada);
BufferedReader input = new BufferedReader(entrada);
String s = input.readLine();
System.out.println(s);
Integer in;
in = Integer.valueOf(s.trim());
System.out.println(in);
The exception text reads as follows:
Exception in thread "main" java.lang.NumberFormatException: For input string: "54856"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Integer.parseInt(Integer.java:658)
at java.base/java.lang.Integer.valueOf(Integer.java:989)
at Quicksort.main(Quicksort.java:170)
The file in.txt consists of:
54856
896
54
53
2
5634
Well, aparently it had to do with Windows and those \r that it uses... I just tried executing it on a Linux VM and it worked. Thanks to everyone that answered!!
Try reading the file with Scanner class has use it's hasNextInt() method to identify what you are reading is Integer or not. This will help you find out what String/character is causing the issue
public static void main(String[] args) throws Exception {
File ficheroEntrada = new File(
"C:\\in.txt");
Scanner scan = new Scanner(ficheroEntrada);
while (scan.hasNext()) {
if (scan.hasNextInt()) {
System.out.println("found integer" + scan.nextInt());
} else {
System.out.println("not integer" + scan.next());
}
}
}
If you want to ensure parsability of a string, you could use a Pattern and Regex that.
Pattern intPattern = Pattern.compile("\\-?\\d+");
Matcher matcher = intPattern.matcher(input);
if (matcher.find()) {
int value = Integer.parseInt(matcher.group(0));
// ... do something with the result.
} else {
// ... handle unparsable line.
}
This pattern allows any numbers and optionally a minus before (without whitespace). It should definetly parse, unless it is too long. I don't know how it handles that, but your example seems to contain mostly short integers, so this should not matter.
Most probably you have a leading/trailing whitespaces in your input, something like:
String s = " 5436";
System.out.println(s);
Integer in;
in = Integer.valueOf(s.trim());
System.out.println(in);
Use trim() on string to get rid of it.
UPDATE 2:
If your file contains something like:
54856\n
896
54\n
53
2\n
5634
then use following code for it:
....your code
FileReader enter = new FileReader(file);
BufferedReader input = new BufferedReader(enter);
String currentLine;
while ((currentLine = input.readLine()) != null) {
Integer in;
//get rid of non-numbers
in = Integer.valueOf(currentLine.replaceAll("\\D+",""));
System.out.println(in);
...your code

Double string output from while loop

I am trying to make simple one-Class code to copy some definite files (photos) from one folder to another according to a list. The list is kept in separate txt file.
Finally I've got file not found error, so I divided entire code into parts and tested each of them with console output.
And that what I found in scanner while loop:
So the code:
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class Sandy2 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
File f = new File("D:\\\\Javasorter\\List.txt");
Scanner in;
in = new Scanner(f).useDelimiter("[?! .,;:\t\r\n\f\'\"]");
String word, pathbuf1, pathbuf2;
while (in.hasNext()) {
word = in.next().toLowerCase();
System.out.println(word);
Thread.sleep(1000);
pathbuf1 = "\\IMG_" + word + ".CR2";
pathbuf2 = "\\IMG_" + word + ".CR2";
System.out.println(pathbuf1);
System.out.println(pathbuf2);
}
}
}
Expected output:
9452
\IMG_9452.CR2
\IMG_9452.CR2
9475
\IMG_9475.CR2
\IMG_9475.CR2
and so on until list has next, but
Output:
9452
\IMG_9452.CR2
\IMG_9452.CR2
\IMG_.CR2
\IMG_.CR2
9475 \IMG_9475.CR2
\IMG_9475.CR2
\IMG_.CR2
\IMG_.CR2
and so on///
Copying command is added in the same loop in full version program, where "\IMG_9452.CR2" is attached to path srting
So, after the first file copied I got error, because of course there is no "IMG_.CR2" file.
Does anybody know why \IMG_.CR2 doubles in each loop iteration?
Many thanks!
Your problem is in the .useDelimiter("[?! .,;:\t\r\n\f\'\"]"), because Scanner will read spaces between lines as string object, so you have to remove it or change it if you still need to use Delimiter.
Also, You can write the file path with forward slashes / then it will be more readable and OS independent, and try to use try-with-resource to prevent source leak.
Consider this code:
public static void main(String[] args) throws Exception {
try (Scanner in = new Scanner(new File("D:/Javasorter/List.txt"))) {
// in.useDelimiter("[?! .,;:\t\r\n\f\'\"]");
String word, pathbuf1, pathbuf2;
while (in.hasNext()) {
word = in.next().toLowerCase();
System.out.println(word);
Thread.sleep(1000);
pathbuf1 = "\\IMG_" + word + ".CR2";
pathbuf2 = "\\IMG_" + word + ".CR2";
System.out.println(pathbuf1);
System.out.println(pathbuf2);
}
}
}
If you want to use Delimiter for some cases, you can use string trim and then check if string is empty, like:
public static void main(String[] args) throws Exception {
try (Scanner in = new Scanner(new File("D:/Javasorter/List.txt"))) {
in.useDelimiter("[?! .,;:\t\r\n\f\'\"]");
String word, pathbuf1, pathbuf2;
while (in.hasNext()) {
word = in.next().trim().toLowerCase();
if (!word.isEmpty()) {
System.out.println(word);
Thread.sleep(1000);
pathbuf1 = "\\IMG_" + word + ".CR2";
pathbuf2 = "\\IMG_" + word + ".CR2";
System.out.println(pathbuf1);
System.out.println(pathbuf2);
}
}
}
}
remove the variable pathbuf2 completely and you will not have any more of the duplicates

Java scanner error without finishing the file

I am trying to read a paragraph in java via Scanner class and printout the line. However, I encoutner a very strange issue. I get the following error:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Unknown Source)
at Test.main(Test.java:10)
and the print before that is not the end of the file. The print stops at the first word on a specific line every time and there are 5-6 lines more in the file.
My code:
try {
Scanner scanner = new Scanner(new File(filename));
for (int i = 1; i < 3801; i++){
System.out.println(scanner.nextLine());
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Use the following to determine the end of file instead of hardcoded integer.
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
Your scanner.nextLine() is in a for-loop.
It is recommended that you use a while-loop instead.
The condition of the while-loop should be scanner.hasNextLine() which basically translates to "While the scanner has another line ahead in the file, run the code inside the while-loop, otherwise stop the while-loop"
That way, if the scanner doesn't have any more lines to read, it simply stops the loop and continues with the rest of the code.
In your for-loop, you are forcing the scanner to keep reading the file even though it has no other lines to read.
The code should be:
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("read.txt"));
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
scanner.close();
}
Apparently java was confused by the encoding of the file and that is why it was crashing. After adding "UTF-8" in the scanner class now it read everything fine.

Java Scanner Delimeter not working as I expected

I have got a question about a code I have written
package salescities;
import java.io.File;
import java.util.Scanner;
public class SalesCities {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
double totalSales = 0;
int count = 0;
int missingCount = 0;
String line;
File file;
Scanner input;
try {
file = new File("sales.txt");
input = new Scanner(file);
input.useDelimiter(":");
while (input.hasNextLine()) {
input.next();
line = input.nextLine();
try{
totalSales += Double.parseDouble(line);
count++;
}
catch(IllegalArgumentException e){
missingCount++;
}
}
input.close();
} catch (Exception ex) {
ex.printStackTrace();
}
System.out.println(totalSales + " " +missingCount);
}
}
And the file im trying to read is like this
New York: 23.5678
New Jersey: no reports
Rio de Janeiro: 12.3654
When i run the program however it prints out 0.0 3 like all is missing.
The problem is when i run the debugger to see whats happening to line so parseDouble isn't functioning and i saw that line is a string that has this
: 23.5678
and I don't understand why if I'm using ":" as delimeter. I expected only the number without the colon. Can someone answer me?
ps: this is an exercise from a book that's quite simple but the book uses a class TextIO that is implemented by them. just wanted to try scanner instead of their code.
Scanner#nextLine grabs the rest of the line, regardless of the delimiter.
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. — Scanner#nextLine

Reading a string with new lines from console java

I want to read this string (from console not file) for example:
one two three
four five six
seven eight nine
So I want to read it per line and put every line in an array.
How can I read it? Because if I use scanner, I can only read one line or one word (nextline or next).
what I mean is to read for example : one two trhee \n four five six \n seven eight nine...
You should do by yourself!
There is a similer example:
public class ReadString {
public static void main (String[] args) {
// prompt the user to enter their name
System.out.print("Enter your name: ");
// open up standard input
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String userName = null;
// read the username from the command-line; need to use try/catch with the
// readLine() method
try {
userName = br.readLine();
} catch (IOException ioe) {
System.out.println("IO error trying to read your name!");
System.exit(1);
}
System.out.println("Thanks for the name, " + userName);
}
} // end of ReadString class
To answer the question as clarified in the comment on the first answer:
You must call Scanner's nextLine() method once for each line you wish to read. This can be accomplished with a loop. The problem you will inevitably encounter is "How do I know big my result array should be?" The answer is that you cannot know if you do not specify it in the input itself. You can modify your programs input specification to require the number of lines to read like so:
3
One Two Three
Four Five
Six Seven Eight
And then you can read the input with this:
Scanner s = new Scanner(System.in);
int numberOfLinesToRead = new Integer(s.nextLine());
String[] result = new String[numberOfLinesToRead];
String line = "";
for(int i = 0; i < numberOfLinesToRead; i++) { // this loop will be run 3 times, as specified in the first line of input
result[i] = s.nextLine(); // each line of the input will be placed into the array.
}
Alternatively you can use a more advanced data structure called an ArrayList. An ArrayList does not have a set length when you create it; you can simply add information to it as needed, making it perfect for reading input when you don't know how much input there is to read. For example, if we used your original example input of:
one two trhee
four five six
seven eight nine
You can read the input with the following code:
Scanner s = new Scanner(System.in);
ArrayList<String> result = new ArrayList<String>();
String line = "";
while((line = s.nextLine()) != null) {
result.add(line);
}
So, rather than creating an array of a fixed length, we can simply .add() each line to the ArrayList as we encounter it in the input. I recommend you read more about ArrayLists before attempting to use them.
tl;dr: You call next() or nextLine() for each line you want to read using a loop.
More information on loops: Java Loops
Look at this code:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class SearchInputText {
public static void main(String[] args) {
SearchInputText sit = new SearchInputText();
try {
System.out.println("test");
sit.searchFromRecord("input.txt");
System.out.println("test2");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void searchFromRecord(String recordName) throws IOException {
File file = new File(recordName);
Scanner scanner = new Scanner(file);
StringBuilder textFromFile = new StringBuilder();
while (scanner.hasNext()) {
textFromFile.append(scanner.next());
}
scanner.close();
// read input from console, compare the strings and print the result
String word = "";
Scanner scanner2 = new Scanner(System.in);
while (((word = scanner2.nextLine()) != null)
&& !word.equalsIgnoreCase("quit")) {
if (textFromFile.toString().contains(word)) {
System.out.println("The word is on the text file");
} else {
System.out.println("The word " + word
+ " is not on the text file");
}
}
scanner2.close();
}
}

Categories