I'm doing a java project where one of it's parts is to add college courses to an arraylist. This college courses has their class code like ccom 3001, how many credits does that class have and the complete name of the course, like Programming I etc.

The only thing I want to know is how to read a complete line and store it in variables. For example, I want the ccom part in one variable, the number 3001 in one variable, the credits in another variable and the name of the course in another variable. I'm pretty sure I can do the other part of the project but this is where I'm stuck. Any tips?

My file has it's courses like this (just an example):

ccom 3001 3 Programming I
ccom 3002 3 Programming II
ccom 4005 3 Data Structures

Recommended Answers

All 28 Replies

You can read a line to a variable and using tokenizer class take each part you need to other variables. Or you can use String methods like .split(" ") to get each word.

So for example...I can read ccom in a string using hasNext() like...

String name = in.hasNext(); or in.Next();? If so, what can I do about the complete name of the course like "Data Structures" so that it can catch everything including the space?

try nextline, or inside for loops use a byte stream and parse into your data if there are special delimiters

If the course name is the last thing on the file, then nextline() will do you nicely. If it weren't you'd have to look for some clever trick for recognizing the end of the course name - but luckily, it looks like someone's made it easy for you. :)

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.ArrayList;

public class TextFileReading 
{
	public static void main(String[] args) throws FileNotFoundException
	{
		
		File inputFile = new File("pathname of the file");
		ArrayList<Cursos> core = new ArrayList<Cursos>(); //crea nuevo array list

		Scanner in = new Scanner(inputFile);
		in.useDelimiter(" ");
		
		while(in.hasNextLine())
		{
			String line = in.next();
			String line2 = in.next();
			String line3 = in.nextLine();
			//System.out.println(line + " " + line2 + " " + line3 );
			core.add(new Cursos(line,line2,line3));
		}
		
in.close();
	
	for (int j = 0; j < core.size() ; j++)
	{
		System.out.println(core.get(j).getNombre()+ " " + core.get(j).getCreditos() + " " + core.get(j).getDescripcion());
	}

	}
}

I have created a Class Curso (I speak spanish) so that I create an ArrayList of this class. But if I have a file and I want to add other classes that don't belong to the core to other ArrayList...for example...if I have a text like this: (CCOM being of the core)

CCOM
CCOM
CCOM
MATH
MATH
MATH
PSIC

Is there something I can do to stop reading when MATH appears so that I can save Math courses in other ArrayList?

Sure, that's not hard. When you're doing the input, look at the variable that'll be getting that value, and use as your trigger for some new thing to do.

There are actually a few ways to deal with this which might be slicker than just hardcoding values. One way would be to store the previous value in a placeholder and read lines until the input differs from the placeholder, then switch to another destination. For your destinations, you might make a HashMap of ArrayLists, each one keyed to the course code. That way if someone adds a new course code, you never even have to know - when they read the files into the machine, it'll make a correct place to put them.
So you end up with a HashMap:
"CCOM", ArrayList of CCOM courses
"MATH", ArrayList of MATH courses
and so forth.

If someone adds a "BIOL" department, no problem. The HashMap has a new entry, and you can sit around drinking coffee, no problem.

I figured that I can create separate text files with different courses. Like for example, create a text file for the CORE Courses and another file for the General Courses. My question now ...is there a way to open both files? I'm trying but the program just explodes.

What's the error it's reporting?

Ok, my bad, I just figured out that I wasn't accessing the right fields in the ArrayList.

This program consists in three parts. The first part is the administration part in which I have to enter what my core courses are, general course, elective courses etc. I think I can do pretty much the rest of that part because I already did the core and general courses.

The second part consists of another text file in which I have a student number, pin number and the courses that the student has taken with its grades and the semester that the student took the course. I think I have to prompt the user (in the console) to enter his student number and pin to see if it exists in the file. How can I catch the first two things in a line in the file (student # and pin) and discard the rest of the line and start in the other line until I find it or until I get to the bottom of the text?

How can I catch the first two things in a line in the file (student # and pin) and discard the rest of the line and start in the other line until I find it or until I get to the bottom of the text?

Depends on the file format, I'd say. If it's XML, you load up some XML library and let it do the work. More likely it's CSV, less likely it's a fixed-width field. That last is something that's still in use, and it works in some applications: each field of data gets some fixed number of characters, and you just bite off that many characters at a go to break up your line into data. I've even seen some pretty convoluted arrangements where the "fixed" width is variable, specified at the head of the file: that way, you set the fixed width to the longest field you'll need and you're never truncating. Clever, at least half-way.
Most likely, though, you'll be seeing something like this:

LastName, FirstName, Student#, PIN, yadda, yadda

The separator doesn't have to be a comma - CSV used to mean "comma-separated values" but now it seems to have been reverse-engineered to mean "character-separated values", as in "some particular character is the flag that means new value". That can be comma, tab, or anything you like.

To read that, the easiest thing to do is to get the whole line as a String and then use the split() method of the String class to break it up into an array of Strings. From there you should have no problems. If you want to be more of an independent cuss, you can step through the file character by character, putting each character into a StringBuffer until you hit your flag character, then put the resulting String into an appropriate place, lather, rinse, repeat.

If you're using this in actual fact, you would probably load the whole data file into memory, on the assumption that you're going to be accessing it more than once, and reading from the disk is slow relative to reading from memory. However, for a classroom assignment, you might want to just read the data file until you get what you came for, and then only save those values (and quit reading the data at that point).
Your call.

I chose to do a Student class that has studentnumber and pin as its attributes and add attributes like grade and term to the Course class so that I can add the course, grade and terms to that student. I still am having problems because I don't know what to do with files like this:

studentnumber pin course grade term

3827132832 3813 prog3000 A a81 prog3001 B a82 prog3002 C a91 math3000 A a92
3283281271 3091 math3000 F a81 prog3021 C a82
3281921127 3000 math3928 C a81

I'm a noob and our professor didn't get through the whole process of explaining how to do the reading...she just gave us the code I posted earlier in the topic so that I can read files, but this one is different because it has different quantity of courses...so I don't know how to add those courses and then go to the next ilne and add those courses and so on.

So a file is
StudentNumber PIN Course-And-Grade*

where StudentNumber is a 10-digit String of ints, PIN, is a 4-digit String of ints, and a Course-And-Grade is a courseNumber followed by a single-char grade and an alphanumeric code I don't recognize? (the * after Course-And-Grade indicates that there may be zero, one, or many of these)

That's not difficult to parse, is it? Since no spaces seem to be allowed in the data items, you can take a chance and split on " ". If you want Student# and PIN, take the first and second (zeroth and first, that is) elements of the resulting array. To be safe you should verify that these each consist of only integers, and the correct number of them. Validating your data is good policy.

Then, to get at a student's record, you can step through the rest of the array (from 2 to array.length) to get each triplet making up a course record. I would step through this three at a time, making sure that there's the correct number of records remaining. Taking the array three at a time means that you can handle one course record with each iteration of the loop, which obviously simplifies things.

Simple, no? :)

I really really am trying to understand you but I don't haha, maybe it's because my primary language is Spanish. Anyways, you're suggesting that I read normally the student number and pin with the in.next() and then how would I read the course grade term sequence? You're telling me to declare a normal array and input the data there? But if so how would I do that? My problem is that sequence of course-grade-term that it's always different.

After reviewing I was thinking...what if I store the student number in a variable, the pin number in other and then the rest of the text(that will be course-grade-term) in one variable...and then use some kind of method to separate the course, grade and term from the string? The only problem would be how I would search for the other course grades and terms that will be in that same string.

Depends, as always, on what you need to do in the long run with this.

What I was saying in my previous post was, simply this: it looks like your input format is one that's not hard to read. It's a single line with data fields separated by spaces. The easiest way to break this up is to use the split() method of the String class: look for it here, if you're not familiar with it. This method returns an array of Strings, so that's where the array comes from. Based on the lines you've given, this array will have student number in the [0] place and PIN in the [1] place, and then [2]-[4], [5]-[7], and so forth will hold the data for the classes.

[0]:3827132832
[1]:3813

[2]:prog3000
[3]: A
[4]:a81

[5]:prog3001
[6]:B
[7]:a82

and so forth.

Are you with me so far?

So you're saying that I should read the whole line in a variable, and then use the split method...then save it in a array of strings, the 0 and 1 would be account number and pin number and then every three spaces would be course-grade-term? The end of the array would be the null character right?

You'd get an array of Strings from the split method. You have to decide what you want to do with them, but saving them as an array doesn't seem good to me.

Is there a data object for all of this? A Student class, maybe?

I have a Student Class but it only has studentnumber and pin as its attributes...I really don't know how to make an arraylist for each individual students courses and grades (this is another problem). And how would I manipulate the split method without equaling it to an array?

I really don't know how to make an arraylist for each individual students courses and grades (this is another problem)

Maybe you need another class to represent this? It'll seem like classes are multiplying here, but they are a good organizing principle. If you collect these into a class, then you have an arraylist of that class, and you're set.

And how would I manipulate the split method without equaling it to an array?

It will give you an array, but you don't have to keep the array. Arrays are a good mechanism for dealing with a set of data while you figure out what you want to do with it.

Here, I'll do it in pseudocode, it'll be easier.
Begin by declaring an ArrayList of Students. Then

while (file has more lines)
{
  make a new student, call it newStudent
  read a line and split it to an array
  from the resulting array, set newStudent.studentNumber and newStudent.PIN to array[0] and array[1]
  for (i = 2; i <array.length; i+=3)
  {
    make a new CourseCredit, cc
    set cc's coursenumber to array[i]
    set cc's coursenumber to array[i+i]
    set cc's other field to array[i+2]
    add cc to newStudent's list of courseCredits
  }
  add newStudent to list of students
}

This leaves out a lot, but maybe the idea is clear.

Ok, I understand the pseudocode, but I would have a Student class with student number and pin number and a CourseCredit class with course name , grade and term?

Exactly. You don't need to put it in a list, either. If you just want to read the one student, you would just loop through the file and split each line. Look at the first entry: is it the number you're looking for? If so, extract that line, otherwise move along. Construct your Student as before.

If you're going to be looking up multiple students, it's best to read them all into memory. Memory access is much faster than disk access. However, if you're just reading one student with each run of the program, don't worry about setting up the list.

Oh, I understand. The problem is that my professor told us to save it into an ArrayList and that's why I'm doing this. A last question for today so that I can spend the night with this project (is due next tuesday)...I would have to pass the CourseCredit arraylist as a parameter of the Student class constructor?

No, not necessarily. I pictured it as a setter in the Student method. newStudent.addCourseCredit(cc); //it might look like this in your code That method would just use the add method of the ArrayList class: list.add(cc); //this is within the Student class - this is what does the work This makes more sense to me: create a Student with the minimal data, and then give it the mechanism to add more data.
However, you could do it in the constructor. In that case, you'd have to build the list of CourseCredits in the loop, and then make the Student object after the loop terminates. Both ways are viable.


Buenas noches, y mucho suerte con la programmación.

Haha! Good one =D...the pseudocode you gave me worked perfectly. I have other things this program should do but I'll try that on my own.

Another question though...I have to make this program in such way that I can run it by the console and by a Graphical Interface...my question is, is it hard to create this interface? Our professor didn't teach us anything about graphical interfaces and I would like to know if I'm gonna spend a lot of time in the interface? And other question...does the code that I use for the console work too for the GUI or I would have to do a completely different coding?

May sound like a noob but that's what I'm practically am =P

"Noob" ain't no bad thing. Nothing wrong with learning new things.

Building a GUI can be a real pain, though some people find it's not so bad. If you haven't done anything with Swing before, Sun has a lot of tutorials. Go play with those and see what you can learn.

Setting up an application to run as GUI or console is a good design trick. It forces you to separate the business logic from the presentation layer. It's harder to do once you've already written a program that integrates the two, but it's not impossible. It's probably easiest to explain if you spend some time learning your way around Swing first, but essentially you want to have your input methods separate from the calculations.

A simple example: Suppose I want to make a program for calculating the square of a number. (ooh, tricky)
Simple enough:

main
{
  while (not done)
  {
    get a number
    display number * number
    done?
  }
}

Well, if I wrote this as you'd expect, it would look like this:

public static void main(String[] args)
{
  boolean done = false;
  Scanner scanner = new Scanner(in);
  while (!done) 
  { 
    S.o.println("Give me a number");
    int i = scanner.nextInt();
    S.o.println(i +" squared is "+ i*i+"\nAnother?");
    String s = scanner.nextLine();
    if (s.charAt(0)!='y'&& s.charAt(0)!='Y')
      done = true;
  }
}

Breaking that out to a gui would not be easy - you'd end up rewriting the whole thing. However, if I were to make the code more modular, it's easier:

public static void main(String[] args)
{
  PresentationLayer p = getPresentationLayer();
  while (!done)
  {
    int i = p.getANumber();
    p.display(square(i));
    done = p.checkIfDone()
  }
}

Okay, now I have to write those methods. I'd start by definining an interface "PresentationLayer" which can do getANumber(), display(int i), and checkIfDone() among other things - I'd probably think a little more about those methods in a more serious example.
I can then make a ConsoleUI and a GraphicUI that implement that interface: one of them writes to the screen and reads from stdin, the other uses Swing to make pretty boxes on the screen.
GetPresentationLayer would return me one of those PresentationLayers, Console or GUI, based on some decision procedure that I don't care about right now- maybe it picks one at random, maybe it depends on the phase of the moon, it doesn't matter. To the main program, it doesn't make a difference. When the main program asks for a number, it gets a number, and when it sends a number off to be displayed, it assumes that number is going to be displayed.

That's one way to do this, there are probably others, and some of the others may well be better. I don't think you necessarily need to use this structure, there are probably a few other ways to get at it, but it's a way of thinking about the problem of separating the presentation from the business logic, which is what you need to do if you want to use the same business logic for both console and GUI interface.

I did some research and found information about GUI Builders like JFormDesigner as a plugin for Eclipse...it's easier with this or not?

I don't know, I've always built them by hand. People say it's easier that way.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.