Java - Reading Text File as an Integer and Split Each Line into Array

Read integers from a text file and store them into an array in Java

You can use java's file nio.file api to read file data into string and then split that string using space to String[] and convert each number from String to an int in this array.

String fileData = new String(Files.readAllBytes(Path.of("file path here")));
int[] data = Stream.of(fileData.split(" ")).mapToInt(Integer::parseInt).toArray();

Reading/splitting different parts from different lines in a text file in Java

Each data record in a text file always has a Start and an End. The easiest records are obviously those that are contained on a single delimited line within the text file, where each file line is in fact a record as you can see within a typical CSV format data file. The harder records to read are the Multi-Line records whereas each data record consists of several sequential text file lines but still, there is a Start and a End to each record.

The Start of a record is usually pretty easy to distinguish. For example, in the file example you provided in your post it is obviously any file line that starts with Student Name:.

The End of a record may not always be so easy to determine since many applications do not save fields which contain no data value in order to help increase access speed and reduce file bloat. The thought is "why have a text file full of empty fields" and to be honest, rightly so. I'm not a big fan of text file records anyways since utilizing a database would make far better sense for larger amounts of data. In any case, there will always be a file line that will indicate the Start of a record so it would make sense to read from Start to Start of the next record or in the case of the last record in file, from Start to End Of File (EOF).

Here is an example (read the comments in code):

// System line separator to use in files.
String ls = System.lineSeparator();
/* Array will hold student data: Student Name, Student ID, College,
Credits Attempted, Credits Earned, and finally Grade Points. */
String[] studentData = new String[6];
// String Array to hold Course Table Header Names.
String[] coursesHeader = {"COURSE NO", "COURSE TITLE", "CREDITS", "GRADE"};
// List Interface to hold all the course Data line Arrays for each record
java.util.List<String[]> cousesList = new java.util.ArrayList<>();
// Underlines to be used for Console display and file records
// Under courses Header
String underline1 = "-------------------------------------------------------------";
// Under all the courses
String underline2 = "------------------------------------------------------------------------------------";

/* Read and Write to files using 'Try With Resources' so to
automatically close the reader an writer objects. */
try (Scanner reader = new Scanner(new java.io.File("StudentData.txt"), "UTF-8");
java.io.Writer writer = new java.io.FileWriter("StudentsGPA.txt")) {
// For console display only! [Anything (except caught errors) to Console can be deleted]
System.out.println("The 'StudentsGPA.txt' file will contain:");
System.out.println("======================================");
System.out.println();

// Will hold each line read from the reader
String line = "";
/* Will hold the name for the next record. This would be the record START
but only AFTER the first record has been read. */
String newName = "";

// Start reading the 'StudentData.txt' file (line by line)...
while (reader.hasNextLine()) {
/* If newName is empty then we're on our first record or
there is only one record in file. */
if (newName.isEmpty()) {
line = reader.nextLine(); // read in a file line...
}
else {
/* newName contains a name so we must have bumped into
the START of a new record during processing of the
previous record. We aleady now have the first line
of this new record (which is the student's name line)
currently held in the 'newName' variable so we just
make 'line' equal what is in the 'newName' variable
and carry on processing the data as normal. in essance,
we simply skipped a read because we've already read it
earlier when processing the previous record. */
line = newName;
// Clear this variable in preparation for another record START.
newName = "";
}
/* Skip comment lines (lines that start with a semicolon (;)
or a hash mark (#). Also skip any blank lines. */
if (line.startsWith(";") || line.startsWith("#") || line.isEmpty()) {
continue;
}
/* Does this file line start with 'Student Name:'? If so then
this is a record START, let's process this record. If not
then just keep reading the file. */
if (line.startsWith("Student Name:")) {
/* Let's put the student name into the studentData array at
index 0. If it is detected that there has been no name
applied for some reason then we place "N/A" as the name.
We use a Ternary Operator for this. So, "N/A" will be a
Default if there is not name. This will be typical for
the other portions of student data. */
studentData[0] = line.isEmpty() ? "N/A" : line.split("\\s*:\\s*")[1].trim();
/* Let's keep reading the file from this point on and retrieve
the other bits of student data to fill the studentData[]
Array... */
for (int i = 1; i < 6; i++) {
line = reader.nextLine().trim();
/* If we encounter a comment line or a blank line then let's
just skip past it. We don't want these. */
if (line.startsWith(";") || line.startsWith("#") || line.isEmpty()) {
i--;
continue;
}
/* Store the other portions of student data into the
studentData Array using "N/A" as a default should
any student data field contain nothing. */
studentData[i] = line.isEmpty() ? "N/A" : line.split("\\s*:\\s*")[1].trim();
}
// The current Student's Courses...
/* Clear the List Interface object in preparation for new
Courses from this particular record. */
cousesList.clear();
// Read past the courses header line...We don't want it.
reader.nextLine();
// Get the courses data (line by line)...
while (reader.hasNextLine()) {
line = reader.nextLine().trim();
/* Again, if we encounter a comment line or a blank line
in this section then let's just skip past it. We don't
want these. */
if (line.startsWith(";") || line.startsWith("#") || line.isEmpty()) {
continue;
}
/* At this point, if we have read in a line that starts
with 'Student Name:' then we just hit the START of a
NEW Record! This then means that the record we're
currently working on is now finished. Let's store this
file line into the 'newRecord' variable and then break
out of this current record read. */
if (line.startsWith("Student Name:")) {
newName = line;
break;
}
/* Well, we haven't reached the START of a New Record yet
so let's keep creating the courses list (line by line).
Break the read in course line into a String[] array.
We use the String#split() method for this with a small
Regular Expression (regex) to split each line based on
comma delimiters no matter how the delimiter spacing
might be (ex: "," " ," " , " or even " , "). */
String[] coursesData = line.split("\\s*,\\s*");
/* Add this above newly created coursesData string array
to the list. */
cousesList.add(coursesData);
}
/* Write (append) this current record to new file. The String#format()
method is used here to save the desired data into the 'StudentGPA.txt'
file in a table style format. */
// Student Data...
writer.append(String.format("%-12s: %-25s", "ID", studentData[1])).append(ls);
writer.append(String.format("%-12s: %-25s", "Name", studentData[0])).append(ls);
writer.append(String.format("%-12s: %-25s", "College", studentData[2])).append(ls);
// Student Courses...
// The Header line
writer.append(String.format("%-13s %-30s %-10s %-4s", coursesHeader[0],
coursesHeader[1], coursesHeader[2], coursesHeader[3])).append(ls);
// Apply an Underline (underline1) under the header.
writer.append(underline1).append(ls);
// Write the Courses data in a table style format to make the Header format.
for (String[] cData : cousesList) {
writer.append(String.format("%-13s %-33s %-9s %-4s",
cData[0], cData[1], cData[2], cData[3])).append(ls);
}
// Apply an Underline (underline2) under the Courses table.
writer.append(underline2).append(ls);

// Display In Console Window (you can delete this if you want)...
System.out.println(String.format("%-12s: %-25s", "ID", studentData[1]));
System.out.println(String.format("%-12s: %-25s", "Name", studentData[0]));
System.out.println(String.format("%-12s: %-25s", "College", studentData[2]));
System.out.println(String.format("%-13s %-30s %-10s %-4s", coursesHeader[0],
coursesHeader[1], coursesHeader[2], coursesHeader[3]));
System.out.println(underline1);
for (String[] cData : cousesList) {
System.out.println(String.format("%-13s %-33s %-9s %-4s",
cData[0], cData[1], cData[2], cData[3]));
}
System.out.println(underline2);

// The LAST line of each record, the Credits...
// YOU DO THE CALCULATIONS FOR: totalAttemped, semGPA, and cumGPA
String creditsAttempted = studentData[3];
String creditsEarned = studentData[4];
int credAttempted = 0;
int credEarned = 0;
int totalAttempted = 0;
double semGPA = 0.0d;
double cumGPA = 0.0d;
/* Make sure the 'credits attemted' numerical value is in fact
a string representaion of an integer value. if it is then
convert that string numerical value to integer. */
if (creditsAttempted.matches("\\d+")) {
credAttempted = Integer.valueOf(creditsAttempted);
}
/* Make sure the 'credits earned' numerical value is in fact
a string representaion of an integer value. if it is then
convert that string numerical value to integer. */
if (creditsEarned.matches("\\d+")) {
credEarned = Integer.valueOf(creditsEarned);
}
// Build the last record line (the Credits string) with the acquired data.
String creditsString = new StringBuilder("CREDITS: TOTAL.ATTEMPTED ")
.append(totalAttempted).append("? EARNED ").append(credEarned)
.append(" ATTEMPTED ").append(credAttempted).append(" SEM GPA ")
.append(semGPA).append("? CUM GPA ").append(cumGPA).append("?")
.toString();
// Display it to the console Window (you can delete this).
System.out.println(creditsString);
System.out.println();

// Write the built 'credit string' to file which finishes this record.
writer.append(creditsString).append(ls);
writer.append(ls); // Blank Line in preparation for next record.
writer.flush(); // Flush the data buffer - write record to disk NOW.
}
}
}
// Trap Errors...Do whatever you want with these.
catch (FileNotFoundException ex) {
System.err.println("File Not Found!\n" + ex.getMessage());
}
catch (IOException ex) {
System.err.println("IO Error Encountered!\n" + ex.getMessage());
}

Yes, it looks long but if you get rid of all the comments you can see that it really isn't. Don't be afraid to experiment with the code. Make it do what you want.


EDIT: (as per comments)

To place the student info portion of each record into an ArrayList so that you can parse it the way you want:

Where the forloop is located within the example code above for gathering the student info, just change this loop to this code and parse the data the way you want:

// Place this ArrayList declaration underneath the 'underline2' variable declaration:
java.util.ArrayList<String> studentInfo = new java.util.ArrayList<>();

then:

if (line.startsWith("Student Name:")) {
studentInfo.clear();
studentInfo.add(line);
/* Let's keep reading the file from this point on and retrieve
the other bits of student data to fill the studentData[]
Array... */
for (int i = 1; i < 6; i++) {
line = reader.nextLine().trim();
/* If we encounter a comment line or a blank line then let's
just skip past it. We don't want these. */
if (line.startsWith(";") || line.startsWith("#") || line.isEmpty()) {
i--;
continue;
}
studentInfo.add(line);
}

// .................................................
// .... The rest of the code for this `if` block ...
// .................................................
}

You will of course need to change the code after this loop to properly represent this ArrayList.

How to read from text file, split strings from integers and then pass integers into an arraylist?

You can use your snippet and extend it to read the second .txt file aswell.

Your while loop now has to loop over lines.

fileScan.nextLine(); // skip first line
while (fileScan.hasNextLine())
{
marksArray.add(Integer.valueOf(fileScan.nextLine().split(" ")[1]));
}

So what happens here is that first you get the nextLine, split it by " " and get the second part where the Integer sits. But since nextLine returns a String which is split in two Strings you have to cast it to Integer or use the static method Integer.valueOf.

How to read from txt file line and print arrays of strings and integers

Whilst this isn't the greatest solution, here is a potential solution that you could build upon/tidy up.

Basically, read in your file, loop through each line, if the line contains the user input, split each string on that line, check if text or numeric, and add to the relevant array.

public static void main(String[] args) throws FileNotFoundException {
List<String> nameArr = new ArrayList<>();
List<Double> intArr = new ArrayList<>();
System.out.print("Enter the State name: ");
Scanner in = new Scanner(System.in);
String inputFileName = in.next();

Scanner sc = new Scanner(new File("pplnames17.txt"));

while (sc.hasNextLine()) {
String nameLine = sc.nextLine();
if (nameLine.contains(inputFileName)) {
String[] inputs = nameLine.split(" ");
for (String input : inputs) {
if (isNumeric(input)) {
intArr.add(Double.parseDouble(input));
} else {
nameArr.add(input);
}
}
}
}
if (!nameArr.isEmpty()) {
System.out.println(nameArr);
} else {
System.out.println("No names found");
}
if (!intArr.isEmpty()) {
System.out.println(intArr);
} else {
System.out.println("No numbers found");
}
}

public static boolean isNumeric(String str) {
try {
double d = Double.parseDouble(str);
} catch (NumberFormatException e) {
return false;
}
return true;
}

I tested it and my text file was like this:

abc def ghi 12 55 jkl mno pqr

joe jack mary 1 2 james 4

paul jim kim bob 45 othername

bill yu will gill 455 Paulo

User input of mary gave an output of:

[joe, jack, mary, james]

[1.0, 2.0, 4.0]

Read file using delimiter and add to array

There are multiple issues with your current code.

  • myFile.equals("sl") compares your Scanner object with a String. You would actually want to compare your read string line, not your Scanner object. So line.equals("sl").
  • nextLine() will read the whole line. So line will never be equal to "sl". You should split the line using your specified delimiter, then use the split parts to build your object. This way, you will not have to worry about newline in combination with next().
  • Currently, your evaluation of the read input is outside of the while loop, so you will read all the content of the file, but only evaluate the last line (currently). You should move the evaluation of the input and creation of your landing objects inside the while loop.

All suggestions implemented:

...
Scanner myFile = new Scanner(fr);
// no need to specify a delimiter, since you want to read line by line
String line;
String[] splitLine;
while (myFile.hasNextLine()) {
line = myFile.nextLine();
splitLine = line.split(","); // split the line by ","
if (splitLine[0].equals("sl")) {
StrongLanding sl = new StrongLanding();
sl.setLandingId(Integer.parseInt(splitLine[1]));
sl.setLandingDesc(splitLine[2]);
sl.setNumLandings(Integer.parseInt(splitLine[3]));
sl.setCost(Double.parseDouble(splitLine[4]));
landings.add(sl);
} else if (splitLine[0].equals("ul")) {
UltimateLanding ul = new UltimateLanding();
ul.setLandingId(Integer.parseInt(splitLine[1]));
ul.setLandingDesc(splitLine[2]);
ul.setNumLandings(Integer.parseInt(splitLine[3]));
ul.setCost(Double.parseDouble(splitLine[4]));
landings.add(ul);
}
}
...

However, if you don't want to read the contents line by line (due to whatever requirement you have), you can keep reading it via next(), but you have to specify the delimiter correctly:

...
Scanner myFile = new Scanner(fr);
String line; // variable naming could be improved, since it's not the line
myFile.useDelimiter(",|\\n"); // comma and newline as delimiters
while (myFile.hasNext()) {
line = myFile.next();
if (line.equals("sl")) {
StrongLanding sl = new StrongLanding();
sl.setLandingId(Integer.parseInt(myFile.next()));
sl.setLandingDesc(myFile.next());
sl.setNumLandings(Integer.parseInt(myFile.next()));
sl.setCost(Double.parseDouble(myFile.next()));
landings.add(sl);
} else if (line.equals("ul")) {
UltimateLanding ul = new UltimateLanding();
ul.setLandingId(Integer.parseInt(myFile.next()));
ul.setLandingDesc(myFile.next());
ul.setNumLandings(Integer.parseInt(myFile.next()));
ul.setCost(Double.parseDouble(myFile.next()));
landings.add(ul);
}
}
...

Read text file and convert rows to Integer arrays

Modify the while as shown below

Scanner s = new Scanner("file path");
while (s.hasNextLine()) {
//read each line in the file and split the line content on the basis of space
String[] eachLine = s.nextLine().split("\\s+");
}

Once you have the eachLine String array - use it to initialize the Integer vector. Also, following this approach you can avoid the -1 which you are putting explicitly to tell the Scanner the end of line/ file/ input.

Use eachLine.lenght to define the length of each Vector.

For example,

28 1 9 5 4 0 3

90 3 6 4 7

Scanner s = new Scanner("file path");
while (s.hasNextLine()) {
String[] eachLine = s.nextLine().split("\\s+");
//import java.util.Arrays;
System.out.println(Arrays.toString(eachLine));
}

split a text file into arrays

Let me try to give you a little direction.

List<Person> list = new ArrayList<Person>();
String line;
try (
// open an input stream
InputStream fileInputStream = new FileInputStream("".../testing"");

// read file as UTF-8
InputStreamReader reader = new InputStreamReader(fileInputStream, Charset.forName("UTF-8"));

// open a BufferedReader to read line-by-line
BufferedReader br = new BufferedReader(reader);
) {
while ((line = br.readLine()) != null) {
// split the `line` on ";"
// [0] - ID
// [1] - FName
// [2] - LName
// [3] - City
// [4] - Age
String[] objects = line.split(";");
int ID = Integer.parseInt(objects[0]);
String fName = objects[1];
String lName = objects[2];
String city = objects[3];
int age = Integer.parseInt(objects[4]);
list.add( new Person(ID, fName, lName, city, age) );
}
}

System.out.println(list);

An idea about what a Person object can look like.

class Person {
int ID;
String fName;
String lName;
String city;
int age;

public Person(int ID, String fName, String lName, String city, int age) {
this.ID = ID;
this.fName = fName;
this.lName = lName;
this.city = city;
this.age = age;
}

@Override
public String toString() {
return ID + ";" + fName + ";" + lName + ";" + city ";" + age;
}
}

The opened file is read in lin-by-line. It would be a good idea to create an object, called Person of something, that would have ID, FName, LName, City and Age as fields. Then you could create a new List<Person> entry for each line in the file.

Does that help?



Related Topics



Leave a reply



Submit