reading a file with mixed data with java - java

Hello I was wondering if I could get some help. I've been tasked with reading from a file and storing the information into arrays. I have three arrays meant to pick up the data, which for example looks like this:
Smith Jr., Joe
111-22-3333 100 90 80 70 60 88
Jones, Bill
111-11-1111 90 90 87 88 100 66
Brown, Nancy
222-11-1111 100 100 100 100 100 100
My code for reading the data is this so far:
public static void readFile(String[] studentList, String[] idList, int[] scoreList) throws IOException {
String fileName;
System.out.println("Enter file name and location if necessary: ");
fileName = KB.nextLine();
File f1= new File(fileName); // "C:\Users\User\Desktop\final.txt"
Scanner fileIn = new Scanner(f1);
int i = 0 ;
if (f1.length() == 0) {
System.out.println("File is empty");
}
while(fileIn.hasNext() && i < studentList.length){
studentList[i] = fileIn.nextLine();
idList[i] = fileIn.nextLine();
scoreList[i] = fileIn.nextInt();
i++;
}
}
When I go to output the code though, I get this error:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:864)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at managestudent.ManageStudent.readFile(ManageStudent.java:88)
at managestudent.ManageStudent.main(ManageStudent.java:36)
I've tried troubleshooting and what seems to be happening is that my second array stores the entire line and that my integers aren't getting read and stored into my third array.
I tried to set my second array as a long to pick up the numbers like 111-111-111 and differentiate from the integers but that gave me another error which seemed to be that my long array wasn't picking up anything from the second lines at all.
Any suggestions?
Thank you kindly for your time.

You need to make the following changes to your code
studentList[i] = fileIn.nextLine();
String id_score = fileIn.nextLine();
String[] split = id_score.split(" ",2);
idList[i] = split[0];
scoreList[i] = split[1];
.split() will separate the id and score in the second line.

Look at this code:
studentList[i] = fileIn.nextLine();
idList[i] = fileIn.nextLine();
scoreList[i] = fileIn.nextInt();
You are reading line by line.
But 111-22-3333 100 90 80 70 60 88 is a single line (which is read into idList[i]).
You need to change your code in a way, that you read 111-22-3333 100 90 80 70 60 88 as a line, and then split the line into two (or more, that's up to you) segments, that you process further to get ID and scores.

As an alternate to Moritz Petersens answer, for minimal changes to your code, you can use the next() method instead of nextLine() method to get the idList() by changing your while loop as follows;
studentList[i] = fileIn.nextLine();
idList[i] = fileIn.next();
scoreList[i] = fileIn.nextLine();
i++;
This will store the first token (Your ID) into the idList array and the remaining part of that line into the scoreList array. Which I assume you are expecting to happen here.
Refer: https://www.tutorialspoint.com/java/util/scanner_next.htm
Hope this helps!
UPDATE
I just observed that your scoreList array is of type int[].
Based on that, above fix will not work.
You will need to create a temporary string which takes all scores and then split it to put the appropriate integers into the score array.
Also, create a new integer for tracking index of the scoreList array.
Something like;
int scoreIndex = 0;
while(fileIn.hasNext() && i < studentList.length){
studentList[i] = fileIn.nextLine();
idList[i] = fileIn.next();
String scores = fileIn.nextLine();
String[] splitScores = scores.trim.split(" ");
for (String a : splitScores) {
scoreList[scoreIndex] = Integer.parseInt(a);
scoreIndex++;
}
i++;
}
Also, since you are using a primitive array dataType for scoreList array, make sure that the size of the array is number_of_subjects*number_of_students.
In your example, 6*3.

Related

How to print line until the first letter of the line is different (with scanner or bufferedreader)?

What I am trying to do is make a MATCH. I have an array with a list of numbers like this:
171142229
171142232
171142250
171142254
177073637
but there are a lot more, this is just an example and I have to find each number in all of my files, the content of the files is something like this (can't change this either and there are a lot more also each line begins either with the letter H or the I)
H ZPDV 171 MO ME 8500015847 8500015847 8500015847 8500015847 171142229 20160112 20160112 MXN 0000002978
I 20 6CB 1 10.07 0 16 C2 9019999999171610099277 9019999999171610099277
I 10 61 1 189.93 0 16 C2 9019999999171610099277 9019999999171610099277
H ZPDV 169 MO ME 2000169 2000169 2000169 2000169 169068348 20160112 20160112 MXN 0000012213
I 20 6CB 1 12.00 0 16 C2 7019999999169610019193 7019999999169610019193
I 10 61 1 154.38 0 16 C2 7019999999169610019193 7019999999169610019193
if you notice, the first number 171142229 is found in the the first line which has an H at the beginning.
I want to print al the lines that have an I on the beginning that are below the one with the H and stop until the next H.
The program prints all the lines below, no matter what until the end of the file, then looks the next number in the list of files and do the same and so on.
public static void main(String[] args) throws IOException {
String[] lista = CreaPVF.creaListaPendientes(); //this method creates my list of nubers
String[] rutas = CreaPVF.recorreCarpeta();//this method has a list with the routes to my files
for (int i = 0; i < lista.length; i++) {
int x = 0;
while (x < rutas.length) {
try{
String[] tmp;
FileInputStream fis = new FileInputStream(rutas[x]);
Scanner scanner = new Scanner(fis);
String line=scanner.nextLine();
do{
tmp=scanner.nextLine().split("\t");
if (lista[i].equals(tmp[9])) {
while(scanner.hasNextLine()){
do{
System.out.println(scanner.nextLine());
}while(tmp[0].equals("I"));
}
}
}while(scanner.hasNext() ) ;
scanner.close();
} catch (Exception e) {
} finally {
}
x++;
}
}
}
The variable line is unused, and is taking up a Scanner.nextLine(), you are effectively ignoring the first line of the file with this.
Next, in order to get your loop working correctly, you're gonna want to move the initialization of tmp outside of the loop. This ensures that no lines are skipped.
Finally, you need to update tmp inside the loop, and check it for starting character before displaying the line.
// extract the next line from the stream
tmp=scanner.nextLine().split("\t");
do{
// check if our number is in that line
if (lista[i].equals(tmp[9])) {
while(scanner.hasNextLine()){
do{
tmp=scanner.nextLine();
if(tmp[0].equals("I")) {
System.out.println(Arrays.toString(tmp));
}
}while(tmp[0].equals("I"));
}
}
}while(scanner.hasNext() ) ;
I've used Arrays.toString(tmp); here because it's the quickest way to show the result. You might want to consider reading every line into a string, and splitting it into another variable. That way you retain the string for display later.

How to use delimiters to ignore floats greater than 1?

So I'm reading in a two column data txt file of the following from:
20 0.15
30 0.10
40 0.05
50 0.20
60 0.10
70 0.10
80 0.30
and I want to put the second column into an array( {0.15,0.10,0.05,0.2,0.1,0.1,0.3}) but I don't know how to parse the floats that are greater than 1. I've tried to read the file in as scanner and use delimiters but I don't know how to get ride of the integer that proceeds the token. Please help me.
here is my code for reference:
import java.io.PrintWriter;
import java.util.Scanner;
import java.io.*;
class OneStandard {
public static void main(String[] args) throws IOException {
Scanner input1 = new Scanner(new File("ClaimProportion.txt"));//reads in claim dataset txt file
Scanner input2 = new Scanner(new File("ClaimProportion.txt"));
Scanner input3 = new Scanner(new File("ClaimProportion.txt"));
//this while loop counts the number of lines in the file
while (input1.hasNextLine()) {
NumClaim++;
input1.nextLine();
}
System.out.println("There are "+NumClaim+" different claim sizes in this dataset.");
int[] ClaimSize = new int[NumClaim];
System.out.println(" ");
System.out.println("The different Claim sizes are:");
//This for loop put the first column into an array
for (int i=0; i<NumClaim;i++){
ClaimSize[i] = input2.nextInt();
System.out.println(ClaimSize[i]);
input2.nextLine();
}
double[] ProportionSize = new double[NumClaim];
//this for loop is trying to put the second column into an array
for(int j=0; j<NumClaim; j++){
input3.skip("20");
ProportionSize[j] = input3.nextDouble();
System.out.println(ProportionSize[j]);
input3.nextLine();
}
}
}
You can use "YourString".split("regex");
Example:
String input = "20 0.15";
String[] items = input.split(" "); // split the string whose delimiter is a " "
float floatNum = Float.parseFloat(items[1]); // get the float column and parse
if (floatNum > 1){
// number is greater than 1
} else {
// number is less than 1
}
Hope this helps.
You only need one Scanner. If you know that each line always contains one int and one double, you can read the numbers directly instead of reading lines.
You also don't need to read the file once to get the number of lines, again to get the numbers etc. - you can do it in one go. If you use ArrayList instead of array, you won't have to specify the size - it will grow as needed.
List<Integer> claimSizes = new ArrayList<>();
List<Double> proportionSizes = new ArrayList<>();
while (scanner.hasNext()) {
claimSizes.add(scanner.nextInt());
proportionSizes.add(scanner.nextDouble());
}
Now number of lines is claimSizes.size() (also proportionSizes.size()). The elements are accessed by claimSizes.get(i) etc.

Turning a string into multiple arrays?

I'm a student who is learning java (just started this year. I just graduated so I can't ask my high school teacher for help, either), and I need some help on how to turn a string into multiple arrays(?).
However, after this I get stuck (because I can't find a way to break down the string for my purposes).
The file is read like this
Input: The first line will be the number of cases. For each case the
first line will be Susan’s work schedule, and the second line will be
Jurgen’s work schedule. The work schedules will be the date of the
month (1-30) which they work. The third line will be the size of the
initial TV.
The file in question:
3
2 5 10
2 4 10
60
2 4 10
2 5 10
60
1 2 3 4 7 8 10 12 14 16 18 20 24 26 28 30
1 2 3 6 9 10 17 19 20 21 22 23 25 27 28 29
20
I'm not sure how to go about this. I've tried .split(), but that only seems to work on the first row in the string. Any help/tips you might have would be greatly appreciated!
you may read your input by lines and then apply regex on them to separate numbers from string like:
String numbers = "1 2 3 4 7 8 10 12 14 16 18 20 24 26 28 30";
String[] singleNumbers = numbers.split(" ");
then you will have these numbers separated by space in singleNumbers array
Depending on how you are reading the file, you are probably using something like the following:
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
Then, to read the file line by line:
String theLine = in.readLine();
Now you have the string corresponding to the line (in this case the first line, but you can call readLine() over and over to read them all), but note you do not read the 'whole' file at once to get all the Strings, as I think you are suggesting, rather the reader takes a line at a time.
Therefore, if you want all the lines held in an array, all you need to do is declare the array, and then read each line into it. Something like:
// Declare an array to put the lines into
int numberOfLines = 10;
String[] arrayOfStrings = new String[numberOfLines];
// Read the first line
String aLine = in.readLine();
int i = 0;
// If the line that has been read is null, it's reached the end of the file
// so stop reading
while(aLine != null){
arrayOfStrings[i] = aLine;
i++;
aLine = in.readLine();
}
// arrayOfStrings elements are now each line as a single String!
Of course, you may not know how many lines are in the file to be read in the first case, so declaring the size of the array is difficult. You could then look into a dynamically-scaling data structure such as ArrayList, but that is a separate matter.
Hey I got a great solution for you.
Just make a class to store each student's data like
import java.util.List;
public class Student {
private int noOfCases;
private List<String> workSchedule;
private List<String> initialTV;
//getter setters
}
Then this...
public static void main(String[] args) {
//3 students for reading 9 lines
//Susan, Jurgen and You ;)
Student[] students = new Student[3];
int linesRead = 0;
String aLine = null;
// read each line through aLine
for (Student student : students) {
//use buffered/scanner classes for reading input(each line) in aLine
while (aLine != null) {
++linesRead;
if (linesRead == 1) {
student.setNoOfCases(Integer.valueOf(aLine));
++linesRead;
} else if (linesRead == 2) {
student.setWorkSchedule(Arrays.asList(aLine.split(" ")));
++linesRead;
} else if (linesRead == 3) {
student.setInitialTV(Arrays.asList(aLine.split(" ")));
} else {
linesRead = 0;
}
}
}
}
}
If you need to read more lines/more student's records, just resize the Student Array!!
Given you already have your BufferedReader, you could try something like this to give you a multi dimensional array of your rows and columns:
BufferedReader reader = ...;
List<String[]> lines = new ArrayList<String[]>();
String input;
while((input = reader.readLine()) != null){
if (!input.trim().isEmpty()){
lines.add(input.split(" "));
}
}
String[][] data = lines.toArray(new String[lines.size()][]);

JAVA My two-dimensional array scanned from a text file prints without the first column

I am working on a lab for school so any help would be appreciated, but I do not want this solved for me. I am working in NetBeans and my main goal is to create a "two-dimensional" array by scanning in integers from a text file. So far, my program runs with no errors, but I am missing the first column of my array. My input looks like:
6
3
0 0 45
1 1 9
2 2 569
3 2 17
2 3 -17
5 3 9999
-1
where 6 is the number of rows, 3 is the number of columns, and -1 is the sentinel. My output looks like:
0 45
1 9
2 569
2 17
3 -17
3 9999
End of file detected.
BUILD SUCCESSFUL (total time: 0 seconds)
As you can see, everything prints correctly except for the missing first column.
Here is my program:
import java.io.*;
import java.util.Scanner;
public class Lab3
{
public static void main(String[] arg) throws IOException
{
File inputFile = new File("C:\\Users\\weebaby\\Documents\\NetBeansProjects\\Lab3\\src\\input.txt");
Scanner scan = new Scanner (inputFile);
final int SENT = -1;
int R=0, C=0;
int [][] rcArray;
//Reads in two values R and C, providing dimensions for the rows and columns.
R = scan.nextInt();
C = scan.nextInt();
//Creates two-dimensional array of size R and C.
rcArray = new int [R][C];
while (scan.nextInt() != SENT)
{
String line = scan.nextLine();
String[] numbers = line.split(" ");
int newArray[] = new int[numbers.length];
for (int i = 1; i < numbers.length; i++)
{
newArray[i] = Integer.parseInt(numbers[i]);
System.out.print(newArray[i]+" ");
}
System.out.println();
}
System.out.println("End of file detected.");
}
}
Clearly, there is a logical error here. Could someone please explain why the first column is invisible? Is there a way I can only use my rcArray or do I have to keep both my rcArray and newArray? Also, how I can get my file path to just read "input.txt" so that my file path isn't so long? The file "input.txt" is located in my Lab3 src folder (same folder as my program), so I thought I could just use File inputFile = new File("input.txt"); to locate the file, but I can't.
//Edit
Okay I have changed this part of my code:
for (int i = 0; i < numbers[0].length(); i++)
{
newArray[i] = Integer.parseInt(numbers[i]);
if (newArray[i]==SENT)
break;
System.out.print(newArray[i]+" ");
}
System.out.println();
Running the program (starting at 0 instead of 1) now gives the output:
0
1
2
3
2
5
which happens to be the first column. :) I'm getting somewhere!
//Edit 2
In case anyone cares, I figured everything out. :) Thanks for all of your help and feedback.
Since you do not want this solved for you, I will leave you with a hint:
Arrays in Java are 0 based, not 1 based.
As well as Jeffrey's point around the 0-based nature of arrays, look at this:
while (scan.nextInt() != SENT)
{
String line = scan.nextLine();
...
You're consuming an integer (using nextInt()) but all you're doing with that value is checking that it's not SENT. You probably want something like:
int firstNumber;
while ((firstNumber = scan.nextInt()) != SENT)
{
String line = scan.nextLine();
...
// Use line *and* firstNumber here
Or alternatively (and more cleanly IMO):
while (scan.hasNextLine())
{
String line = scan.nextLine();
// Now split the line... and use a break statement if the parsed first
// value is SENT.

Writing a file in Java

Good day!
I have a project (game) that needs to be presented tomorrow morning. But I discovered a bug when writing in the high scores. I am trying to create a text file and write the SCORE NAME in descending order using score as the basis.
FOR EXAMPLE:
SCORE NAME RANK
230 God
111 Galaxian
10 Gorilla
5 Monkey
5 Monkey
5 Monkey
NOTE THERE'S ALSO A RANK
My code is as follows:
public void addHighScore() throws IOException{
boolean inserted=false;
File fScores=new File("highscores.txt");
fScores.createNewFile();
BufferedReader brScores=new BufferedReader(new FileReader(fScores));
ArrayList vScores=new ArrayList();
String sScores=brScores.readLine();
while (sScores!=null){
if (Integer.parseInt(sScores.substring(0, 2).trim()) < score && inserted==false){
vScores.add(score+"\t"+player+"\t"+rank);
inserted=true;
}
vScores.add(sScores);
sScores=brScores.readLine();
}
if (inserted==false){
vScores.add(score+"\t"+player+"\t"+rank);
inserted=true;
}
brScores.close();
BufferedWriter bwScores=new BufferedWriter(new FileWriter(fScores));
for (int i=0; i<vScores.size(); i++){
bwScores.write((String)vScores.get(i), 0, ((String)vScores.get(i)).length());
bwScores.newLine();
}
bwScores.flush();
bwScores.close();
}
But if i input three numbers: 60 Manny, the file would be like this:
60 Manny
230 God
111 Galaxian
10 Gorilla
5 Monkey
5 Monkey
5 Monkey
The problem is it can only read 2 numbers because I use sScores.substring(0, 2).trim()).
I tried changing it to sScores.substring(0, 3).trim()). but becomes an error because it read upto the character part. Can anyone help me in revising my code so that I can read upto 4 numbers? Your help will be highly appreciated.
What you should use is:
String[] parts = sScrores.trim().split("\\s+", 2);
Then you will have an array with the number at index 0, and the name in index 1.
int theNumber = Integer.parseInt(parts[0].trim();
String theName = parts[1].trim();
You could re-write the while-loop like so:
String sScores=brScores.readLine().trim();
while (sScores!=null){
String[] parts = sScrores.trim().split(" +");
int theNumber = Integer.parseInt(parts[0].trim();
if (theNumber < score && inserted==false){
vScores.add(score+"\t"+player+"\t"+rank);
inserted=true;
}
vScores.add(sScores);
sScores=brScores.readLine();
}
Personally, I would add a new HighScore class to aid in parsing the file.
class HighScore {
public final int score;
public final String name;
private HighScore(int scoreP, int nameP) {
score = scoreP;
name = nameP;
}
public String toString() {
return score + " " + name;
}
public static HighScore fromLine(String line) {
String[] parts = line.split(" +");
return new HighScore(Integer.parseInt(parts[0].trim()), parts[1].trim());
}
}
The format of each line is always the same : an integer, followed by a tab, followed by the player name.
Just find the index of the the tab character in each line, and substring from 0 (inclusive) to this index (exclusive), before parsing the score.
The player name can be obtained by taking the substring from the tab index +1 (inclusive) up the the length of the line (exclusive).
if above mentioned table is a file.
for first two score it will be fine but for 5 it start reading character. Might be that is causing problem.

Categories