How to detect end of line with Scanner from text file - java

So I'm reading an input text file that is 4 lines of single-space separated numbers. The text file is just:
5
9 6
4 6 8
0 7 1 5
I'd like to input these numbers into a 2D array called rows. So for example, rows[1][0] should be 9, the first number in the second row.
My problem is when I use the Scanner for in.next() or in.nextInt(), it ignores the end of the line and just keeps on going, so rows[0][1] ends up being 9 instead of 0. I'd like for the array to finish populating with 0's if there is no number for that slot. So since the first row is only 1 number, 5, I'd like for the array rows[0][0] to be 5, but rows[0][1] to rows[0][3] to be 0.
I've tried using a try/catch for NoSuchElementException and an if in.hasNextLine() but neither of those seemed to work.
Any ideas or help would be greatly appreciated.

You can use a Scanner to read individual tokens, and you can use a Scanner to read an entire line, but you cannot use a Scanner to do both.
What you want to do is first read the line into a String, then use a Scanner on that String to parse that line, e.g.:
BufferedReader lineReader = new BufferedReader(...);
String line;
while ((line = lineReader.readLine()) != null) {
Scanner scanner = new Scanner(line);
// use scanner here
}
You can also use a Scanner to read lines instead of a BufferedReader, but unless you have a specific requirement (e.g. you're trying to drop this into code that already uses a Scanner), it doesn't really matter how you read the lines.
Hope that helps.

Use more than one Scanner. One Scanner gets each line with nextLine(), and then you feed the line obtained to the next Scanner analyzes each line's tokens. Just be sure to close() of the inner Scanner (and the outer one too) when done using it.
Pseudocode:
create fileScanner with file
while fileScanner has more lines
get next line from fileScanner
create new Scanner with next line, lineScanner
while lineScanner has next,
get next token.
do what you want with token.
close of lineScanner
close fileScanner

You should probably use a BufferedReader and split. The advantage of this is that you know how big to make your arrays in the second dimension as the split method will return an array and you can check its length:
public static void main(String[] args) throws Exception {
final String s = "5\n"
+ "9 6\n"
+ "4 6 8\n"
+ "0 7 1 5";
final InputStream is = new ByteArrayInputStream(s.getBytes());
final int[][] array = new int[4][];
try (final BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
String line;
for (int i = 0; (line = br.readLine()) != null; ++i) {
final String[] tokens = line.split("\\s");
final int[] parsed = new int[tokens.length];
for (int j = 0; j < tokens.length; ++j) {
parsed[j] = Integer.parseInt(tokens[j]);
}
array[i] = parsed;
}
}
System.out.println(Arrays.deepToString(array));
}
Output:
[[5], [9, 6], [4, 6, 8], [0, 7, 1, 5]]
As arrays don't expand it's not easy to use them in while loops that you don't know the size of. Using split allows you to simply do final int[] parsed = new int[tokens.length]; which with a Scanner over whitespace you could not do.
The first dimension size is hard coded however as said your file always has 4 lines.

At the end of each line, there is '\n' ,and at the first of each line(except first line), there is '\r'. You can control your file by them.

Scanner scanner = new Scanner(
"5\n9 6\n4 6 8\n0 7 1 5");
while (scanner.hasNextLine())
{
String currentline = scanner.nextLine();
String[] items = currentline.split(" ");
int[] intitems = new int[items.length];
for (int i = 0; i < items.length; i++)
{
intitem[i] = Integer.parseInt(items[i]);
}
}

Related

Using Scanner and Arrays's to add BigInts

This is a project from school, but i'm only asking for help in the logic on one small part of it. I got most of it figured out.
I'm being given a file with lines of string integers, for example:
1234 123
12 153 23
1234
I am to read each line, compute the sum, and then go to the next one to produce this:
1357
188
1234
I'm stuck on the scanner part.
public static void doTheThing(Scanner input) {
int[] result = new int[MAX_DIGITS];
while(input.hasNextLine()) {
String line = input.nextLine();
Scanner linesc = new Scanner(line);
while(linesc.hasNext()) {
String currentLine = linesc.next();
int[] currentArray = convertArray(stringToArray(currentLine));
result = addInt(result, currentArray);
}
result = new int[MAX_DIGITS];
}
}
In a nutshell, I want to grab each big integer, put it an array of numbers, add them, and then i'll do the rest later.
What this is doing it's basically reading all the lines and adding everything and putting it into a single array.
What i'm stuck on is how do I read each line, add, reset the value to 0, and then read the next line? I've been at this for hours and i'm mind stumped.
Edit 01: I realize now that I should be using another scanner to read each line, but now i'm getting an error that looks like an infinite loop?
Edit 02: Ok, so after more hints and advice, I'm past that error, but now it's doing exactly what the original problem is.
Final Edit: Heh....fixed it. I was forgetting to reset the value to "0" before printing each value. So it makes sense that it was adding all of the values.
Yay....coding is fun....
hasNext method of the Scanner class can be used to check if there is any data available in stream or not. Accordingly, next method used to retrieve next continuous sequence of characters without white space characters. Here use of the hasNext method as condition of if doesn't make any sense as what you want is to check if the there are any numerical data left in the current line. You can use next(String pattern).
In addition, you can try this solution even though it is not optimal solution...
// In a loop
String line = input.nextLine(); //return entire line & descard newline character.
String naw[] = line.split(" "); //split line into sub strings.
/*naw contains numbers of the current line in form of string array.
Now you can perfom your logic after converting string to int.*/
I would also like to mention that it can easily & efficiently be done using java-8 streams.
An easier approach would be to abandon the Scanner altogether, let java.nio.io.Files to the reading for you and then just handle each line:
Files.lines(Paths.get("/path/to/my/file.txt"))
.map(s -> Arrays.stream(s.split("\\s+")).mapToInt(Integer::parseInt).sum())
.forEach(System.out::println);
If i were you i would be using the BufferedReader insted of the Scanner like this:
BufferedReader br = new BufferedReader(new FileReader("path"));
String line = "";
while((line = br.readLine()) != null)
{
int sum = 0;
String[] arr = line.split(" ");
for(String num : arr)
{
sum += Integer.parseInt(num);
}
System.out.println(sum);
}
Considering the level you're on, I think you should consider this solution. By using only the scanner, you can split the lines into an array of tokens, then iterate and sum the tokens by parsing them and validating that they're not empty.
import java.util.*;
class SumLines {
public static void main(String[] args) {
Scanner S = new Scanner(System.in);
while(S.hasNext()) {
String[] tokens = S.nextLine().split(" ");
int sum = 0;
for(int i = 0; i < tokens.length; i++) {
if(!tokens[i].equals("")) sum += Integer.parseInt(tokens[i]);
}
System.out.println(sum);
}
}
}

Is there a way around not advancing a line with Scanner (Java)

Okay so I'm having a slight problem with scanner advancing an extra line. I have a file that has many lines containing integers each separated by one space. Somewhere in the file there is a line with no integers and just the word "done".
When done is found we exit the loop and print out the largest prime integer that is less than each given integer in each line(if integer is already prime do nothing to it). We do this all the way up until the line with "done".
My problem: lets say the file contains 6 lines and on the 6th line is the word done. My output would skip lines 1, 3 and 5. It would only return the correct values for line 2 and 4.
Here's a snippet of code where I read the values in:
Scanner in = new Scanner(
new InputStreamReader(socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
while(in.nextLine() != "done"){
String[] arr = in.nextLine().split(" ");
Now I sense the problem is that the nextLine call in my loop advances the line and then the nextline.split call also advances the line. Thus, all odd number lines will be lost. Would there be another way to check for "done" without advancing a line or is there a possible command I could call to somehow reset the scanner back to the start of the loop?
The problem is you have 2 calls to nextLine() try something like this
String line = in.nextLine();
while (!"done".equals(line)) {
String[] arr = line.split(" ");
// Process the line
if (!in.hasNextLine()) {
// Error reached end of file without finding done
}
line = in.nextLine();
}
Also note I fixed the check for "done" you should be using equals().
I think you are looking for this
while(in.hasNextLine()){
String str = in.nextLine();
if(str.trim().equals("done"){
break;
}else{
String[] arr = str.split("\\s+");
//then do whatever you want to do
}
}

Scanner problems in Java

I have a method that returns a scanner to a text file that has lines of input (I can't get this to display properly, but like - Hi (new line) This (\n) Is (\n) Me (\n)). Then in main, I used the scanner to count the number of lines of input there are, and then resetted the scanner. I later used the scanner to put the lines of input into an array (I don't want an ArrayList), but Java says "java.util.NoSuchElementException: No line found"...
while(scanner.hasNextLine()){
numOfStrings++;
scanner.nextLine();
}
scanner.reset();
String[] stringsOfInput = new String[numOfStrings];
for(int i = 0; i < numOfStrings; i++){
String s = scanner.nextLine(); //returns "No line found" error message
stringsOfInput[i] = s;
}
Does anyone know how to fix this so it does what it should?
The most versatile way to do this would be to add the lines into an ArrayList<String> then make that into an Array(String[] stringsOfInput = myArrayList.toArray(new String[myArrayList.size()]);)
You may want to try putting the content of the for loop within the while. That way you can get the number of strings and each string in one loop through the file.
EDIT:
Sample with ArrayList
ArrayList<String> stringsOfInput = new ArrayList<String>();
while(scanner.hasNextLine())
{
stringsOfInput.add(scanner.nextLine());
numOfStrings++;
}

My output is assuming the whole file is one line

public static void main(String args[]) throws FileNotFoundException
{
String inputFileName = "textfile.txt";
printFileStats(inputFileName);
}
public static void printFileStats(String fileName) throws FileNotFoundException
{
String outputFileName = "outputtextfile.txt";
File inputFile = new File(fileName);
Scanner in = new Scanner(inputFile);
PrintWriter out = new PrintWriter(outputFileName);
int lines = 0;
int words = 0;
int characters = 0;
while(in.hasNextLine())
{
lines++;
while(in.hasNext())
{
in.next();
words++;
}
}
out.println("Lines: " + lines);
out.println("Words: " + words);
out.println("Characters: " + characters);
in.close();
out.close();
}
I have a text file containing five lines
this is
a text
file
full of stuff
and lines
The code creates an output file
Lines: 1
Words: 10
Characters: 0
However, if I remove the capability for reading the number of words in the file, it correctly states the number of lines (5). Why is this happening?
Your inner while loop is gobbling up the whole file. You want to count the number of words in each line, right? Try this instead:
while (in.hasNextLine())
{
lines++;
String line = in.nextLine();
for (String word : line.split("\\s"))
{
words++;
}
}
Note that splitting on spaces is a very naive approach to tokenization (word-splitting) and will only work for simple examples like the one you have here.
Of course, you could also do words += line.split("\\s").length; instead of that inner loop.
in.hasNext() and in.next() treat all whitespace characters as word separators, including newline characters. Your inner loop is eating all the newlines as it's counting all the words.
This reads next Token, not the line :
in.next();
So it just read next and next and next and dont care about line ending. Space or \n is considered as white space usually, so methods like this one does not make any difference between them.
The reason is, that hasNext() does not care about line breaks.
So, you are entering the while(in.hasNextLine()) loop, but then you are consuming the whole file with the while(in.hasNext()) loop, resulting in 1 line and 10 words.
-> Check the token consumed by hasNext() for EOL-Characters, then increase line count.
OR:
Use String line = scanner.nextLine() to obtain exactly ONE line, and then use a second scanner to fetch all tokens of that line: scanner2 = new Scanner(line); while(scanner2.hasNext())

Reading each Integer from a line from a Text file

I am new to Java. How can i read each integer from a line in a text file. I know the reader class has the read and readline functions for it. But in my case i not only want to read the integers in the file but want to know when the line changes. Because the first element of every line denotes an array index and all the corresponding elements are the linked list values attached to that index.
For example, see the 4 line below. In this case i not only want to read each integer but the first integer of every line would be an array index so i will have an a 4 element array with each array element correspoding to a list where A[1]-> 4, A[2]-> 1,3,4 and soo on.
1 4
2 1 3 4
3 2 5
4 2
After retrieving the integers properly i am planning to populate them via
ArrayList<Integer>[] aList = (ArrayList<Integer>[]) new ArrayList[numLines];
EDITED : I had been asked in one the comments that what i have thinked soo far and where exctly i am stucken so below is what i am thinking (in terms of original and pseoudo code mixed)..
while (lr.readLine() != null) {
while ( // loop through each character)
if ( first charcter)
aList[index] = first character;
else
aList[index]->add(second char.... last char of the line);
}
Thanks
Thanks for the scanner hint, Andrew Thompson.
This is how i have achieved it
Scanner sc =new Scanner(new File("FileName.txt"));
ArrayList<Integer>[] aList = (ArrayList<Integer>[]) new ArrayList[200];
String line;
sc.useDelimiter("\\n");
int vertex = 0;
while (sc.hasNextLine()) {
int edge = 0;
line = sc.nextLine();
Scanner lineSc = new Scanner(line);
lineSc.useDelimiter("\\s");
vertex = lineSc.nextInt() - 1;
aList[vertex] = new ArrayList<Integer>();
int tmp = 0;
System.out.println(vertex);
while (lineSc.hasNextInt()) {
edge = lineSc.nextInt();
aList[vertex].add(edge);
System.out.print(aList[vertex].get(tmp) + " ");
++tmp;
}
System.out.println ();
}

Categories

Resources