I have the following code that reads through a line of students and the program should split at each white space then go to the next part of the text but I get arrayindexoutofBound exception.
The text file has several lines like this:
130002 Bob B2123 35 34 B2132 34 54 B2143 23 34
public static void main(String[] args) throws FileNotFoundException {
File f = new File("C:\\Users\\Softey\\Documents\\scores.txt");
Scanner sc = new Scanner(f);
List<MarkProcessing> people = new ArrayList<MarkProcessing>();
while(sc.hasNextLine()){
String line = sc.nextLine();
String[] details = line.split("\\s+");
String regNumber = details[0];
String name = details[1];
String modOne= details[2];
int courseM = Integer.parseInt(details[3]);
int examM = Integer.parseInt(details[4]);
String modTwo = details[5];
int courseM2 = Integer.parseInt(details[6]);
int examM2 = Integer.parseInt(details[7]);
String modThree = details[8];
int courseM3 = Integer.parseInt(details[9]);
int examM3= Integer.parseInt(details[10]);
MarkProcessing p = new MarkProcessing(regNumber, name, modOne,courseM, examM, modTwo,courseM2,examM2, modThree, courseM3, examM3);
people.add(p);
}
}
}
When it goes to details[1] I get the index error.
Without information regarding the input file, I am going to guess this is because of blank lines in your file. If this is the case, you should try something to ensure that you have enough pieces.. For this, your while loop could be something like this.
while(sc.hasNextLine()){
String line = sc.nextLine();
String[] details = line.split("\\s+");
if(details.length < 11) continue; // skip this iteration
...
}
Keep in mind this is only going to work if you are checking at least 11 items per line. If you need a more advanced method of parsing the input, whereas they may have any number of courses. You are better off thinking of another approach than simply storing values directly from indices.
You should try printing the line before parsing it so that you can see what causes it to blow up.
String line = sc.nextLine();
String[] details = line.split("\\s+");
String regNumber = details[0];
String name = details[1];
String modOne= details[2];
You are splitting on chunks of spaces. In the event you encounter a line with no spaces, then there will only be a single element and therefore details[1] will throw an IndexOutOfBoundsException.
My suggestion is to examine your input carefully. Does it have at trailing line feed? If so, that may be interpreted as a blank line
130002 Bob B2123 35 34 B2132 34 54 B2143 23 34
<blank line>
To split by space, you need to use:
String[] details = line.split(" "); // "\\s+" -> does not split by space.
In your case, it is trying to split the line by the regex pattern '//s+' and since this is not found, it considers the whole line to be one string. In this case, the size of the string array is 1. There is no details[1] and hence you get this error.
Related
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);
}
}
}
So I'm having a problem with parsing a text file. Let's say I have a text file with contents like this(all strings are separated by a space and all lines after line 1 only contain 2 strings):
a b c d e
a b
c d
I need to process the first line one string at a time. That is "a"(then use a for a method) then "b"(use b for a method) and so on.
After this, I need to process lines 2 and 3 in a different way. Read line 2, store "a" in a variable as e1, then process "b" and store b in a variable e2. Then I need to use e1 and e2 for a separate method. All lines after line 1 do the same thing as I just described.
My problem is that my code is just reading the whole line and storing that as the variables. Thus, I'm not reading each individual string. Also, I don't understand how to tell when I'm done processing line 1(this is important because I use a different method for all lines after line 1). Here's what I have:
Scanner scan = new Scanner(new File(args[0]));
while(scan.hasNext()){
String input = scan.nextLine();
t.addV(input);
}
while(scan.hasNext()){
String e1 = scan.next();
String e2 = scan.next();
t.addE(e1, e2);
}
I know this is very wrong but I'm just looking to understand how I would know when I'm done reading line 1 and how I would just read each individual string.
You are really close, just a couple things off.
Step 1: getting the first line and calling a method for each individual letter
String firstLine = scan.nextLine();
// splits the line into a letter array
String[] letters = firstLine.split("\\s");
for(String letter: letters){
// do your method
}
Step 2: Getting the two individual letters and calling methods depending on the letter:
while(scan.hasNextLine()){
String line = scan.nextLine();
String[] lets = line.split("\\s");
String e1 = lets[0];
String e2 = lets[1];
// do your methods with the individual letters
}
You could of course use scan.next() to retrieve one letter at a time, but it seems by the way you worded your question that the line that the letters are on is needed knowledge to the method call. Which is why I've also assumed that there are a maximum of two letters per line on subsequent lines.
I recommend you using an BufferedReader, to read a file line by line
try (BufferedReader reader = new BufferedReader(new FileReader(args[0]))) {
String firstLine = reader.readLine();
//Process with the first line
String secondLine = reader.readLine();
//Process with the second line
} catch (Exception ex) {
}
Edit
To get the elements within a line, use the String.split(String delimiter) method.
Like this:
String[] splittedElements = line.Split(" ");
I'm trying to read a data file and save the different variables into an array list.
The format of the data file looks a little like this like this
5003639MATH131410591
5003639CHEM434111644
5003639PSYC230110701
Working around the bad formatting of the data file, I added commas to the different sections to make a split work. The new text file created looks something like this
5,003639,MATH,1314,10591
5,003639,CHEM,4341,11644
5,003639,PSYC,2301,10701
After creating said file, I tried to save the information into an array list.
The following is the snippet of trying to do this.
FileReader reader3 = new FileReader("example.txt");
BufferedReader br3 = new BufferedReader(reader3);
while ((strLine = br3.readLine())!=null){
String[] splitOut = strLine.split(", ");
if (splitOut.length == 5)
list.add(new Class(splitOut[0], splitOut[1], splitOut[2], splitOut[3], splitOut[4]));
}
br3.close();
System.out.println(list.get(0));
The following is the structure it is trying to save into
public static class Class{
public final String recordCode;
public final String institutionCode;
public final String subject;
public final String courseNum;
public final String sectionNum;
public Class(String rc, String ic, String sub, String cn, String sn){
recordCode = rc;
institutionCode = ic;
subject = sub;
courseNum = cn;
sectionNum = sn;
}
}
At the end I wanted to print out one of the variables to see that it's working but it gives me an IndexOutOfBoundsException. I wanted to know if I'm maybe saving the info incorrectly, or am I perhaps trying to get it to print out incorrectly?
You have a space in your split delimiter specification, but no spaces in your data.
String[] splitOut = strLine.split(", "); // <-- notice the space?
This will result in a splitOut array of only length 1, not 5 like you expect.
Since you only add to the list when you see a length of 5, checking the list for the 0th element at the end will result in checking for the first element of an empty list, hence your exception.
If you expect your data to have a comma or a space separating the characters then you would alter the split line to be:
String[] splitOut = strLine.split("[, ]");
The split takes a regular expression as an argument.
Rather than artificially adding commas I would look at String.substring in order to cut the line you have read into pieces. For example:
while ((strLine = br3.readLine())!=null) {
if (strLine.length() != 20)
throw new BadLineException("line length is not valid");
list.add(new Class(strLine.substring(0,1), strLine.substring(1,7), strLine.substring(7,11), strLine.substring(11,15), strLine.substring(15,19)));
}
[ Untested: my numbers might be out because I a bit knacked, but you get the idea ]
I have a serious problem with extracting terms from each string line. To be more specific, I have one csv formatted file which is actually not csv format (it saves all terms into line[0] only)
So, here's just example string line among thousands of string lines;
test.csv
line1 : "31451 CID005319044 15939353 C8H14O3S2 beta-lipoic acid C1CS#S[C##H]1CCCCC(=O)O "
line2 : "12232 COD05374044 23439353 C924O3S2 saponin CCCC(=O)O "
line3 : "9048 CTD042032 23241 C3HO4O3S2 Berberine [C##H]1CCCCC(=O)O "
I want to extract "beta-lipoic acid" ,"saponin" and "Berberine" only which is located in 5th position.
You can see there are big spaces between terms, so that's why I said 5th position.
In this case, how can I extract terms located in 5th position for each line?
one more thing ;
the length of whitespace between each six terms is not always equal.
the length could be one,two,three or four..five... something like that..
Another try:
import java.io.File;
import java.util.Scanner;
public class HelloWorld {
// The amount of columns per row, where each column is seperated by an arbitrary number
// of spaces or tabs
final static int COLS = 7;
public static void main(String[] args) {
System.out.println("Tokens:");
try (Scanner scanner = new Scanner(new File("input.txt")).useDelimiter("\\s+")) {
// Counten the current column-id
int n = 0;
String tmp = "";
StringBuilder item = new StringBuilder();
// Operating of a stream
while (scanner.hasNext()) {
tmp = scanner.next();
n += 1;
// If we have reached the fifth column, take its content and append the
// sixth column too, as the name we want consists of space-separated
// expressions. Feel free to customize of your name-layout varies.
if (n % COLS == 5) {
item.setLength(0);
item.append(tmp);
item.append(" ");
item.append(scanner.next());
n += 1;
System.out.println(item.toString()); // Doing some stuff with that
//expression we got
}
}
}
catch(java.io.IOException e){
System.out.println(e.getMessage());
}
}
}
if your line[]'s type is String
String s = line[0];
String[] split = s.split(" ");
return split[4]; //which is the fifth item
For the delimiter, if you want to go more precisely, you can use regular expression.
How is the column separated? For example, if the columns are separated by tab character, I believe you can use the split method. Try using the below:
String[] parts = str.split("\\t");
Your expected result will be in parts[4].
Just use String.split() using a regex for at least 2 whitespace characters:
String foo = "31451 CID005319044 15939353 C8H14O3S2 beta-lipoic acid C1CS#S[C##H]1CCCCC(=O)O";
String[] bar = foo.split("\\s\\s");
bar[4]; // beta-lipoic acid
I'm doing a programming project and keep getting the error shown below.
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1585)
at ArrayPhoneDirectory.loadData(ArrayPhoneDirectory.java:42)
at ArrayPhoneDirectoryTester.main(ArrayPhoneDirectoryTester.java:18)
I thought this would be because the scanner read.nextLine() is going past the end of the text file. But I've used a while loop with hasNextLine so I'm not sure why this is happening.
Anyone know where I'm going wrong?
public void loadData (String sourceName){
Scanner read = new Scanner(sourceName);
while (read.hasNextLine()) {
String name = read.nextLine();
String telno = read.nextLine(); //ArrayPhoneDirectory Line 42
add(name, telno);
}
}
Associated text file
John
123
Bill
23
Hello
23455
Frank
12345
Dkddd
31231
You are reading two lines while only checking for the existence of one
Here is the second read
String telno = read.nextLine(); //ArrayPhoneDirectory Line 42
hasNextLine checks for only one line. You are trying to read two lines.
String name = read.nextLine();
String telno = read.nextLine();
which in case of odd number of lines can throw NoSuchElementException for second line you want to read.
hasNextLine()
will check only for one new line. you cannot read two lines after checking for just one.
If you have to continuously read records then you could do
public void loadData (String sourceName){
Scanner read = new Scanner(sourceName);
int i = 1;
while (read.hasNextLine()) {
if(i%2 != 0)
String name = read.nextLine();
else
String telno = read.nextLine(); //ArrayPhoneDirectory Line 42
add(name, telno);
i++;
}
}
Once you call nextLine the pointer gets incremented. Since, you have already called it before in this line:
String name = read.nextLine();
So, the next time you try to read it over here:
String telno = read.nextLine();
you get no such element exception. You should use this instead:
String telno = name
What you're doing is reading too many lines when checking for only one. It goes like this:
Problem
If the array on "lines" looks like this:
["This is line 1"]
Then read.hasNextLine() will return true. Then you enter your while loop. You run the first line which is:
String name = read.nextLine();
You retrieved one element from the above array, now it looks like this:
[]
Then you continue through your while loop:
String telno = read.nextLine();
Then the nextLine() method looks for a element in the array to give you, doesn't find any, and throws an exception.