Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

reading a file using a class  RSS feed

 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm working on a project for university and I'm having some problems when it comes to understand how does a class with a method to read given by our professor works.
We are supposed to be able to use that method to read words in lines from a text file. However, I don't really understand how it works. If anyone could help me, as well as explaining to me how can I use it to read the files, I'd be so grateful.

Here's the class with the method called read() as well as the methods and variables used by it :



I have to use it, as I said, to read lines from a file that looks like this:



I have to check first how the line starts (t1, t2, t3) then I have to read the name, between #n and #d, and then the address, between #d and \n. And I have to use that class above with those methods.

This is what I have so far, but doesn't work:



Please, could someone explain to me how the method works and how can I make it work for reading a file so I can figure out how to use it?

Thanks!
 
Stephan van Hulst
Saloon Keeper
Posts: 7804
142
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Johnny, welcome to CodeRanch!

I'm afraid the code your professor gave to you will do you little good without editing. Honestly, even if you're allowed to edit it, it's pretty much useless.

Normally I would solve this problem by applying so called "regular expressions" to each line you read, but that may be a bit too advanced for now. For now, you can use String.split() to split each line into words, and then process each word individually for the requirements of your program.

If you need more help, tell us what you're stuck on.
 
Campbell Ritchie
Marshal
Posts: 55682
162
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

I am afraid that code looks confused to me. It also doesn't look like Java® code; it looks more like what the C chappies used to write when they were going through the text letter by letter, or even worse, what I find myself writing in Forth. Again going through a String letter by letter. I find it difficult to understand myself; I would suggest you ask whoever wrote it to explain it.

I think you are going through the code letter by letter, putting letters into a char[] if they are not spaces or line end characters, and calling that a word. Not something I would voluntarily do in an object language like Java®.There are all sorts of ways to find a File; you can read a nice way here (though somebody recently said to use the old method with this class because it shows an interface similar to the normal file explorer). The strange version of try‑catch is explained here: Java7+ only.
Now you have a List of Strings, you can take each String, split it, use another Scanner to tokenise it, etc etc. No need to mess around with low‑level code.
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:I'm working on a project for university and I'm having some problems when it comes to understand how does a class with a method to read given by our professor works.

You're not the only one.

We are supposed to be able to use that method to read words in lines from a text file. However, I don't really understand how it works. If anyone could help me, as well as explaining to me how can I use it to read the files, I'd be so grateful.

OK, well my assumption is that this class has been made deliberately difficult to follow. No professor I know of would write something as monstrous as that without a reason; and I suspect his is that he wants you to reason out how to use the horrible methods he's given you correctly.

I'm also presuming that you're not allowed to change anything you've been given, but you might be able to rearrange things a bit.

So, if it was me, the first thing I'd do is
(a) Add space lines between all the methods.
(b) Separate the static variables from the non-static ones. My advice:
1. Move lines 6-8 to just before your first static method (read()).
2. Add at least one space line after line 3 (ie, immediately before 'letters').

That should hopefully spread things out for you and put fields closer to where they're used.

The other thing I noticed is that while 'phrase' is null (which is what it's initialized to), readCharKeyB() will ALWAYS return '.', which is probably not what you want - so you'll have to think about what you want to set it to.

I have to pop out for a while, but if I think of anything else when I get back, I'll post.

Good luck.

Winston
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello everyone and thank you for you answers!!

Some of you suggest that I should split the String into words, but the problem is that it's obligatory to use that class or a similar one.

What I understand about it, or at least I think I do, is that a Word is a char array and with you put characters into that char array and form a single Word. Am i right?

My biggest question, however, is how do I call it from my program to make it read a line. I've been trying different ways, but they seem to be wrong.

Should I create a new Word object for every new word that it's supposed to be in the line??
And when I want to read the line how do I do it? ??

Thanks!!
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:What I understand about it, or at least I think I do, is that a Word is a char array and with you put characters into that char array and form a single Word. Am i right?

No. Word is an object containing a char array, and read() attempts to "read" characters with readCharKeyB() and transfer them into its own array (letters).

The important thing is that read() returns a Word object, NOT a char[].

My biggest question, however, is how do I call it from my program to make it read a line. I've been trying different ways, but they seem to be wrong.

Because you're trying to assign the result to a char[]. Read what I said above.

However, even when you get that right, your troubles aren't over, because you actually have to get characters into word.letters in order to look at them - at least I presume that's the idea.

If I've got it right, the whole point of this exercise is that it should be confusing; and it's up to you to think it through.

Tip: Take each method one at a time and read through it carefully, making notes for yourself on exactly what it does; then try to put it all together.

HIH

Winston
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What do you mean when you say Word is an object containing a char array? I don't see the difference

For example if I do should read() read the line and create Word objects for every word in the line or not?

And I think I understand read(), but readCharKeyB()?? What's phrase? A sequence of objects Word??
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:What do you mean when you say Word is an object containing a char array? I don't see the difference
For example if I do should read() read the line and create Word objects for every word in the line or not?

No, you should not. The problem is that you CANNOT say
  line = Word.read();
because you cannot assign the result to line, because line is a String, and read() returns a Word.

And I think I understand read(), but readCharKeyB()?? What's phrase? A sequence of objects Word??

I hate to say, but I suspect you may not be ready for this quite yet. You have to read every single line of the class you've been given in detail. There IS a phrase variable, you just have to find it and work out where and how it's used.
Spend three hours on it if you have to, but try to work out what each method you've been given does before you start writing anything in main().

This problem is NOT simple, so don't expect to be able to just bash out code to solve it.

Winston
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've been reading the class again and again and I have these doubts at this moment:

First of all: read() reads from a sequence that I think it's phrase, or not? I mean, phrase is a char array and returns its chars, then each char returned form readCharKeyB() goes to variable letter, then letter goes into the char array of the new Word object. Is this correct? Or I'm totally wrong?

Second: how do I tell read() what is the sequence from which it has to read??

For example I have a char array called "x" that contains this: "hello how are you" (imagine that it's a char array) I want "x" to be my sequence, so read() will read from it. Then how do write this in code??


Please tell me if I'm understanding how it works properly or not hahaha

Thanks
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:First of all: read() reads from a sequence that I think it's phrase, or not? I mean, phrase is a char array and returns its chars, then each char returned form readCharKeyB() goes to variable letter, then letter goes into the char array of the new Word object. Is this correct? Or I'm totally wrong?

No, you're on the right track, but you really do have to write down every single step that each method does in a form you can understand.

For example:
read()
1. Creates a new Word and assigns it to local variable 'wd'.   (that's pretty important wouldn't you say?)
2. Runs jumpblanks().

jumpblanks()
1. Cheks if variable 'letter' is equal to the constant 'blank' (' ').
If it is:
2. Runs readCharKeyB() and assigns the result to 'letter'
3. Go back to step 1.
Otherwise it terminates.

readCharKeyB()
1. Sets local variable 'res' to '.'.
2. ...

Do you see what I mean? YOU have to understand exactly what every single step of every method is doing, and you may have to write some tables and and run through them, noting what the value of each variable is at each step.

Like I said, this is not a simple problem; and the most important ingredient to solving it is that you must not guess.

So be warned: you have a few hours of work ahead of you.

HIH

Winston
 
Knute Snortum
Sheriff
Posts: 4073
112
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have to ask: have you posted the entire code of class Word? If not, please do.
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There's one method missing, but I understand how it works and how to use it in my main().



 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:There's one method missing, but I understand how it works and how to use it in my main().

Erm ... that doesn't look right.

Shouldn't line 4 be:
  iguals = letters[idx] == b.letters[idx];
?

Winston
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh yes you're right. I deleted "b." while translating.

Take a look at this:



This is just a test to check if I understood what the method does, etc .
So I declare three objects Word, I figured out this way to do it and I assume it's the right one, I compare two of them and if they are equal I print the other one "x".

Then I tried this:



But the output is a blank space and I expected the words to appear one per line.
How can I select the text from which I want to read??
Maybe making phrase public and calling it from Main() like Word.phrase=x; ??

I did it and worked, but I can only print the first Word, if I write System.out.println(first + second); it reports an error with band operators. Also how can I do it if I don't know how many words has my text??



It prints "My", but as I wrote above, how can I do it to print the second or obviously to print them all?

Thanks again!

(I edited several times so you see how my reasoning works and you can now if I'm on the right track and help me better)
 
Dave Tolls
Rancher
Posts: 2913
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What do you get returned with a second call to read()?
That is, what happens if you repeat this call?
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What do you get returned with a second call to read()?
That is, what happens if you repeat this call?


It reads the next one so it prints "My" "name" , but if I continue doing this it just prints until "is" and reports a "java.lang.ArrayIndexOutOfBoundsException: 17"
And I don't think it's the best way to do it, because when reading a file I don't know how many words does it have.
 
Dave Tolls
Rancher
Posts: 2913
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So, what you need is a mechanism for running a piece of code until some event happens.
That tends to mean a loop.

For the loop to work you need to identify the end point. Does the read() method provide a Word object that you can use to identify that it has reached the end?

ETA: Oh yes, and then we can look into why that exception is occurring,.
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think read() doesn't provide a Word object to identify the end.
I did it like this:



It prints the whole "whatever" but gives an extra 4 or 5 blank lines and I don't know why.

And now how do I save each Word object to use it later??

For example, in my file the first line looks like this:


I wrote this:



And prints:



So "Palma " is not printed. Why??
And how do I read the next line and print it? And again how do I save each Word object? Because later I'll need to write in another file the name( between #n and #d) and the address (between #d and '\n') and also check if the beginning of the line is "t1" or "t2" or "t3", because the lines are names and addresses of people, and I have to write a letter (new file) for each, depending on the beginning of the line one letter will be one or another. The new files will have the name of the person who will receive it, so that's why I need the name too.
 
Dave Tolls
Rancher
Posts: 2913
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That exception should give a stack trace showing the line causing the problem.

For the general issue of reading the file, you are looking at a loop within a loop.

However, I would recommend breaking out your Word code into a separate method, and concentrating on getting that working.
This assumes you have been taught about writing your own methods.
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

However, I would recommend breaking out your Word code into a separate method, and concentrating on getting that working.
This assumes you have been taught about writing your own methods.


Do you mean creating a method that gets the type (t1, etc), another one that gets the name and another one that gets the address?
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:I think read() doesn't provide a Word object to identify the end.
I wrote this:

Three things:

1. That piece of code is in Spanish, which makes me think that the class you originally showed us was a "translation".
If I'm right, it was a nice thought, but we've lost things in the process (like the esIgualA() method).

Could you provide us with a copy of the entire "Word" class exactly as it was given to you by your professor please; and also show us your main() method exactly as you've written it.
If we have problems with any of the Spanish names, we'll let you know

2. There are two "index" variables ('index' and 'length' in the copy you gave us) which are updated by the static methods but never reset, so I suspect you may have to do that yourself.

3. read() is looking for a '\n' (endOfSequence) as one of the conditions for when to stop, but BufferedReader.readLine() does NOT include a line terminator in the String it returns.

HIH

Winston
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The file is in spanish, yes. But the class is in catalan



And actually I should be reading the file with these methods. I don't think we were supposed to create new ones, but maybe it's the only way.
 
Dave Tolls
Rancher
Posts: 2913
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:
Do you mean creating a method that gets the type (t1, etc), another one that gets the name and another one that gets the address?


I would simply write one that takes a String (in your case a line) and does the while loop.
So you can then write code that loops over the file and passes in each line it reads to this new method.

That will allow you to break the problem down, so you can test it a bit easier. It'll also be easier to read.

Also, note what Winston says about how the Word code detects the end of a line. That might effect what the String you pass into this new method needs to look like.
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I would simply write one that takes a String (in your case a line) and does the while loop.


In a separate class? Like in class Word? Or in my main program?
And I don't understand what while loop you mean, while(line!=null)??
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
and also show us your main() method exactly as you've written it.


Sorry, I forgot this part.



My intention with this is just to print each Word in the file, that looks like this:

t1 0001 #n Miguel Amengual Garrido #d Calle Company, 2 - Palma
t1 0002 #n Ana Bosch Pulido #d Plaza Madrid, 12 - Palma
t3 0003 #n Javier Mir Penalva #d Calle Mateu, 18 - Sa Pobla
t2 0004 #n Isabel Campins Mas #d Calle Mallorca, 23 - Palma
t3 0005 #n Juan Ortega Pons #d Calle España, 79 - Palma

But with that code it prints:
t1
0001
#n
Miguel
Amengual

It cuts the line, and moreover it seems that it only reads ONE line.

2. There are two "index" variables ('index' and 'length' in the copy you gave us) which are updated by the static methods but never reset, so I suspect you may have to do that yourself.

And I don't understand this. What do you mean resetting by myself?

3. read() is looking for a '\n' (endOfSequence) as one of the conditions for when to stop, but BufferedReader.readLine() does NOT include a line terminator in the String it returns.


I guess this is why it doesn't read properly, but how do I change it or improve it?



}
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:In a separate class? Like in class Word? Or in my main program?

No, just write a static method that processes ONE line, and one line ONLY. And call that from your main() for every line returned by your
  while ((line = br.readLine()) != null) { ...
loop.

Anyway, now that we're finally dealing with the real code, let me explain what I meant about "re-arranging" things.

I'm now convinced that this class has been deliberately written to make life difficult. So, sort a few things out in it without changing what it does, viz:Do you see what I mean?

Now all the static methods that were given to you - along with all the fields they use - are in one place , and instance methods are in another, so you should be able to read the logic more easily. I've also spaced things out a bit and made the indentation and declarations consistent.

But I haven't changed anything that the class DOES; it's all simply to make it easier to read.

Now I don't know if you're adding your code to this class or not, but if you do, then it should all go at the end.

HIH

Winston
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, just write a static method that processes ONE line


When you say process you mean reading it with Word.read()? or what?

Or maybe you mean divide the string into name, address, etc.
 
Dave Tolls
Rancher
Posts: 2913
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:

In a separate class? Like in class Word? Or in my main program?
And I don't understand what while loop you mean, while(line!=null)??


I mean this bit, in a static method (as Winston says):

or at least a version that works.
The "My name is Johnny." would be your method parameter.
Something like:


Once you've isolated that then you can work on what Winston is talking about, to actually handle using the class you've been given.
Yes, the above doesn't work, but by sticking it as its own method you isolate the problem area.

Also note that I have no idea exactly what the output should be (and at the moment it's not actually the main problem), so the above method signature may need changing to return something.
As I say, that's simply not relevant at the moment.
The whole point is to break it down into little self contained bits. Trying to look at the whole problem is likely to cause an overload...I know it does for me.
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:When you say process you mean reading it with Word.read()? or what?
Or maybe you mean divide the string into name, address, etc.

That's up to you, but if it was me, I'd tackle those things one at a time.

FIRST make sure you can read a line - ANY line, including blank ones - and then tackle the business of searching it separately. Because you aren't going to be able to do the second bit UNTIL you have the first one working.

I'd also suggest that you forget about reading your file for the moment, and just provide some test strings to your method, and concentrate on getting that correct.

When, and ONLY when, you know you can read a line, then deal with pulling out the name, and when you know you you can do THAT, add your while loop back in.

Programming and solving problems is all about breaking them up into small pieces; and your first one is to work out how to use those horrible methods correctly.

HIH

Winston
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I wrote this:



I don't really know if this is what you mean, but anyway, there's something wrong , because it says the source code is uncompliable
 
Dave Tolls
Rancher
Posts: 2913
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It should tell you what exactly the compilation issue is.

But yes, that's a start point.
You now can call that parseLine method from main() directly, passing in some rest strings.

Note, you need to know what your expected output should be.
And remember Winston pointed out that the Word class expects a line to end with a '\n' character.
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Johnny Januan wrote:I wrote this:
I don't really know if this is what you mean, but anyway, there's something wrong , because it says the source code is uncompliable

Presumably because you now don't have a main() method. Why did you rename it to 'line()'?

THIS is what we're suggesting:
And keep doing that until it works. EVERY TIME.

Winston
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have this now:



But parseLine() just works if it's called one single time. If I called five times, like above, it runs parseLine(test) and ignores the others
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Now I have this:



It reads and parses one single line, that works fine. However, it reports this:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 64
at práctica_final.Paraula.leerCarTeclado(Paraula.java:108)
at práctica_final.Paraula.botarBlancs(Paraula.java:90)
at práctica_final.Paraula.llegir(Paraula.java:41)

The source seems to be at this line of leerCarTeclado() :


You said something about the index before, but I don't understand what the problem is and therefore how to solve it

 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Now I have this:



It reads and parses one single line, that works fine. However, it reports this:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 64
at práctica_final.Paraula.leerCarTeclado(Paraula.java:108)
at práctica_final.Paraula.botarBlancs(Paraula.java:90)
at práctica_final.Paraula.llegir(Paraula.java:41)

The source seems to be at this line of leerCarTeclado() :


You said something about the index before, but I don't understand what the problem is and therefore how to solve it
 
Knute Snortum
Sheriff
Posts: 4073
112
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the stack trace on the error, but you have a habit of not posting the entire class, so we don't know the class names or the correct line numbers.
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
 
Campbell Ritchie
Marshal
Posts: 55682
162
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
After you have called the leerCarTeclado method, your indice will be 20. Niext time you use that method, you will be attempting to access the 21st element of a 20‑element array. You will get there very quickly if you don't have .s and spaces in your array.

There is something not quite right about using char[]s instead of Strings. It doesn't fit with my ideas of an object‑oriented language.
 
Johnny Januan
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

After you have called the leerCarTeclado method, your indice will be 20. Niext time you use that method, you will be attempting to access the 21st element of a 20‑element array.

So what do I have to change ? Set indice to 0?
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!