PDA

View Full Version : Java - Reading from an external file


Yakisoba
07-25-2006, 09:27 AM
I have a working background in PHP and JavaScript, now I am venturing into the world of Java...Well, actually I learned a little a long time ago but forgot a lot so I decided to start from the ground up...

Anyway, with that said, I have just created a simple class that can "draw" integers on 20x20 2d array. (some of you may be familiar with the Turtle.java assignment, well, I'm just making a really simple version of that right now).

Currently I issue commands through the main method as follows:

Turtle Leonardo = new Turtle();
Leonardo.setStage();
Leonardo.moveEast(5);
Leonardo.moveNorth(5);
Leonardo.setPenState("u");
Leonardo.moveWest(5);
Leonardo.setPenState("d");
Leonardo.moveSouth(5);
System.out.println(Leonardo.getArray());


this would output somthing like a 20x20 array of 0's with a square in the middle drawn with 1's (excluding the top part of the square because the "pen" is lifted during that part).

The output appears as expected. Perfect.

Now, I would like to issue those commands through an external file.
The commands would be as follows:

u = pen up
d = pen down
n10 = move up 10 spaces
e100 = move right 100 spaces
...
...
etc.

I can read from the external file, but I am not sure how to handle the data. Currentley I wrote this bit of code that breaks the file down by line:


try {
/**Read the specified file to give the turtle Directions*/
BufferedReader turtleBrain = new BufferedReader(new FileReader("C:\\iTurtle.txt"));

/**Seperate the file by line*/
String thought;
while ((thought = turtleBrain.readLine()) != null){
//just for testing
System.out.println(thought);
}

} catch (FileNotFoundException ex) {
System.out.println("File not found");
} catch (IOException ex){
System.out.println("IO ERROR");
}


Now, in that while loop I will check each line (i was thinking of using a switch/case) to call a certain method.

i.e. case "u" will call setPenState with the parameter "u".

the above is pretty straight forward, I don't have any trouble with that... What I would like some guidance on are the movements:

for example:
the line read = n8

I will have: case "n" that calls moveNorth and sends it the parameter "8".

Any suggestions on how to approach this?

Right now I a messing around with grabbing the line as a string, remove and check the first charater using RegEx, and if the first char is n, s, e, or w (North, South, East, West) parseInt the following number and send it to the appropriate method.
I have a feeling there is a better way to do this.

Thanks

Yakisoba


Note:

The iTurtle.txt file would contain somthing like:
u
d
n13
s10
e3
w9
u
e3
n5
d
s7
u
q

TheShaner
07-25-2006, 03:14 PM
Why not put a character or space in between the command and parameter? That way you can utilize Java's Split function and do something like the below.

iTurtle.txt
U
D
N-13
S-10
E-3
W-9
Sample Java code
enum Commands {U, D, N, S, E, W};
String thought;
while ((thought = turtleBrain.readLine()) != null){
String[] instructions = thought.split("-");
Commands com = instructions[0];
switch (com) {
case U: Leonardo.setPenState("u"); break;
case D: Leonardo.setPenState("d"); break;
case N: Leonardo.moveNorth(instructions[1]); break;
case S: Leonardo.moveSouth(instructions[1]); break;
case E: Leonardo.moveEast(instructions[1]); break;
case W: Leonardo.moveWest(instructions[1]); break;
default: System.out.println("Invalid Command"); break;
}
}
-Shane

Aradon
07-25-2006, 11:01 PM
And if you wanted to do something that didn't 1.5 you could always just take the first character, call a subsequent method, and then if it's either N S E W you could substring it from the second character on, that way you'll get all of the numer.

So something like... (excuse any errors, writing this on the fly ;) )



try {
/**Read the specified file to give the turtle Directions*/
BufferedReader turtleBrain = new BufferedReader(new FileReader("C:\\iTurtle.txt"));

/**Seperate the file by line*/
String thought = turtleBrain.readLine();
while (thought != null){
char f = thought.charAt(0);
if(f == 'u')
Leonardo.setPenState("u");
if(f == 'd')
Leonardo.setPenState("d");
if(f == 'n')
Leonardo.moveNorth(Integer.parseInt(thought.substring(1,through.length()-1)));
if(f == 's')
Leonardo.moveSouth(Integer.parseInt(thought.substring(1,through.length()-1)));
if(f == 'e')
Leonardo.moveEast(Integer.parseInt(thought.substring(1,through.length()-1)));
if(f == 'w')
Leonardo.moveWest(Integer.parseInt(thought.substring(1,through.length()-1)));

thought = turtleBrain.readLine();
}

} catch (FileNotFoundException ex) {
System.out.println("File not found");
} catch (IOException ex){
System.out.println("IO ERROR");
}



Or something like that. I like the above guy's example cause this way looks messy, but this one you can use in 1.4 environment (there are more of those out there then you people realize :P )

If this were perl you could split it on the empty string and just grab each character...but this isn't so I don't know if java's split can do that :O

daniel_g
07-26-2006, 04:21 AM
He, you guys all missed case "q" :p

Yakisoba
07-26-2006, 09:33 AM
In attempting TheShaners suggestion I have come accross an error I'm sure is due my lack of understanding of "enum".

I understand that enumerated type values consist of a fixed set of constants...this would seem to be the most appropriate way to store my commands as they will always remain the same.

The error that I'm getting is:
"Type not compatible" (this is roughly what it says, I had to translate the message from Japanese)

the line it points to is:

Commands com = instructions[0];


Commands com, does not seem to like the format/type of instruction[0].

However, if i write the line like this:

Commands com = Commands.e;


everything is gravy...

(except in the above case it will execute case "e" and do nothing)

Currently reading up on enums and how to use them with switch.

Any suggestions?

Here is a chunk of code:
(NOTE: I have hardcoded all of the parameters for the directions...my main concern is getting the first character of the line to execute the proper case)

try {
/**Read the specified file to give the turtle Directions*/
BufferedReader turtleBrain = new BufferedReader(new FileReader("C:\\iTurtle.txt"));

/**Seperate the file by line*/
String thought;
while ((thought = turtleBrain.readLine()) != null){
//System.out.println(line);

String[] instructions = thought.split("|");
//String test = instructions[1];
//Commands com = Commands.p;

Commands com = instructions[0];

//int distance = parseInt(instructions[1]);

switch (com){
case u:
Leonardo.setPenState("u");
break;
case d:
Leonardo.setPenState("d");
break;
case n:
Leonardo.moveNorth(5);
break;
case s:
Leonardo.moveSouth(5);
break;
case e:
Leonardo.moveEast(5);
break;
case w:
Leonardo.moveWest(5);
break;
case p:
Leonardo.getArray();
break;
default:
System.out.println("not happinin', command is bunk");
break;
}

}

} catch (FileNotFoundException ex) {
System.out.println("File not found");
} catch (IOException ex){
System.out.println("IO ERROR");
}



Thanks

Yakisoba

Yakisoba
07-26-2006, 10:45 AM
I resolved the issue shortly after I posted the question...

This is what I ended up with:

try {
/**Read the specified file to give the turtle Directions*/
BufferedReader turtleBrain = new BufferedReader(new FileReader("C:\\iTurtle.txt"));

/**Seperate the file by line*/
String thought;
while ((thought = turtleBrain.readLine()) != null){
//System.out.println(line);

String[] instructions = thought.split("\\|");

Commands com = Commands.valueOf(instructions[0]);

switch (com){
case u:
Leonardo.setPenState("u");
break;
case d:
Leonardo.setPenState("d");
break;
case n:
Leonardo.moveNorth(Integer.parseInt(instructions[1]));
break;
case s:
Leonardo.moveSouth(Integer.parseInt(instructions[1]));
break;
case e:
Leonardo.moveEast(Integer.parseInt(instructions[1]));
break;
case w:
Leonardo.moveWest(Integer.parseInt(instructions[1]));
break;
case p:
//Leonardo.getArray();
System.out.println(Leonardo.getArray());
break;
default:
System.out.println("Invalid Command");
break;
}

}

} catch (FileNotFoundException ex) {
System.out.println("File not found");
} catch (IOException ex){
System.out.println("IO ERROR");
}


Thank you "TheShaner" and "Aradon" for your suggestions...I ended up leaning more toward TheSaner's solution because I think a switch was a "cleaner" solution.

Thanks

Yak

TheShaner
07-26-2006, 02:55 PM
Glad you got it to work! I forgot that you had to assign the data types for the file input, i.e. Commands.valueOf and Integer.parseInt. It's been a while since i have done some real programming, haha.

In response to Aradon, I did forget to mention that you have to have the 1.5 environment or higher for using the Split function. My initial suggestion was going to be to use the String Tokenizer class. It's a legacy class now that it's deprecated, but it's still supported in all environments for backwards compatibility. So if the Split method could not be used, the Tokenizer class would have been my next suggestion.

-Shane

Aradon
07-26-2006, 05:28 PM
I resolved the issue shortly after I posted the question...
Thank you "TheShaner" and "Aradon" for your suggestions...I ended up leaning more toward TheSaner's solution because I think a switch was a "cleaner" solution.

Thanks

Yak

You're right, it's a much cleaner solution then what I showed you. Enums are a powerful new feature in java and if you're not concerened with the particular environment then I'd say use all that you have available to you.

I'm glad it works, good luck on the rest of your projects. And if you're into the webdesign stuff (since you work with PHP and javascript), then I suggest looking at JSP and servlets while you're in java's neck of the woods :D