Reading a customers name in a txt file with File Reader - java

My problem is that I can't figure out how to read the customers name with File Reader.
I am making a reservation system and I need to know of the customer already exist. That's why I have to read my Customers.txt file so I can check if someone is already a customer. If he is not I will make a new one with File writer(I Already have the code).
The meaning of this reservation system is to make reservations with a barber. I have to put the reservations in another txt file called Reservations.txt , and in that file you can see each reservation time and who made the reservation.
Thanks for the help!
This is the code I already have:
(some comments are in Dutch but I will translate them )
package nielbutaye;
import java.io.*;
import java.util.UUID;
/**
* #author Niel
*
*/
public class Klant {
//declaration that represents the text
public static String S;
public static String NEWLINE = System.getProperty("line.separator");
/**
* constructor
*/
public Klant(){}
/**
* #return
* By giving the name of the customer you will get all the data from the customer
*/
public double getCustomer() {
return 0 ;
}
/**
* Make a new customer
*/
public void setNew customer(){
// make a newSimpleInOutDialog
SimpleInOutDialog input = new SimpleInOutDialog("A new customer");
//input
S = "Name customer: " + input.readString("Give in your name:");
WriteToFile();
S = "Adress: " + input.readString("Give your adress");
WriteToFile();
S = "Telephonenummber: " + input.readString("Give your telephonenumber");
WriteToFile();
//making a customerID
UUID idCustomer = UUID.randomUUID();
S = "CustomerID: " + customerID.toString();
WriteToFile();
}
public void WriteToFile(){
try{
FileWriter writer = new FileWriter("L:\\Documents/Informatica/6de jaar/GIP/Customer.txt", true);
BufferedWriter out = new BufferedWriter(writer);
//Wrting away your data
out.write(S + NEWLINE);
//Closing the writer
out.close();
}catch (Exception e){//Catch when there are errors
System.err.println("Error: " + e.getMessage());
}
}
}

A BufferedReader() has a method named readLine(), which you can use to read a line from a file:
BufferedReader br = new BufferedReader(new FileReader("Customers.txt"));
String line;
while ((line = br.readLine()) != null)
{
...
}
br.close();
From your WriteToFile() method it seems a customer's details occupies four lines, with the name of the customer appearing on the first line. When searching for a customer, arrange the while loop to only examine every fourth line read.
Other points:
There appears to be no reason for S to be a member variable, nevermind a static. Just declare a local String instance in setNewCustomer() and pass it as an argument to WriteToFile().
Instead of defining a NEWLINE variable you can use BufferedWriter's newLine() method.

Related

How to read and append text file based on certain conditions

What the program does: A user loads a file and it saves the file name, creation date and a file number to a text file. I want the program to check the file to see if the filename is already stored. If it is, to then check the creation date to see if it matches the one the user is currently trying to save. If it differs, to save over the currently saved creation date with the new one.
An example of Info.txt:
CreationDate: 140319, FileName: example1.txt, FileNumber: 1
CreationDate: 110219, FileName: example2.txt, FileNumber: 6
CreationDate: 100319, FileName: example3.txt, FileNumber: 14
How I create and write to the file:
public void fileCreation() throws IOException {
String fileinformation = File.creationdate + ", " + File.name + ", " + "Number: " + File.Number;
FileWriter wr = new FileWriter("Info.txt", true);
PrintWriter output = new PrintWriter(wr);
output.println(fileinformation);
output.close();
}
How I'm currently checking the file, at the moment it only prints the file contents, so if a User goes to save example2.txt with a different creation date, then the new one should overwrite the current one
public void scanFile() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("Info.txt"));
String readfile;
while ((readfile = br.readLine()) != null) {
System.out.println(readfile);
}
System.out.println("file not found");
}
Creation date is a long number and File.creationdate is a string such as "CreationDate: 140319", it would also be good to put a check to see if the FileNumber matches, but this is not necessary.
You should use split on your line with ',' as a separator.
Then you can go through every line and for each line check if first the name is the same as the file name, if it is, go and check the date and then finally check the FileNumber.
But why do you need to check it one by one ? Better to write it in with &&, like this
public boolean scanFile() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("Info.txt"));
String readfile;
Boolean isAlreadyIn = false;
while ((readfile = br.readLine()) != null) {
String[] parts = readFile.split(',');
if(parts[1].replace("FileName: ","").equals(File.name) &&parts[0].replace("CreationDate: ","").equals(File.creationdate) &&parts[2].replace("FileNumber: ","").equals(File.number){
isAlreadyIn = true; // you can also write directly in this fonction
}
return isAlreadyIn;
}
}
if you really need to check it one by one, just make a if(if( if()) with the condition in it

Unable to Read a Text File via BufferedReader

I am unable to read a text file via a BufferedReader Object. However I can successfully write to the same text file via a BufferedWriter Object.
The intent of my program is to read a text file called queryCountFile.txt which will then able to figure out how many Query Objects (my custom object) have been previously created. From there, I will then be able to create as many Query Objects as a want while being able to keep track of the number of said Queries.
The function that tries (and fails) to read from the text file is called findNumberOfQueries(). It is located in my file called Query.java
Can anyone understand why I am unable to read from the text file?
QuickControllerApplication.java
#SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class QuickControllerApplication {
public static void main(String[] args) {
SpringApplication.run(QuickControllerApplication.class, args);
//everthing below this line is for testing purposes
Query littleQuery = new Query(101L);
//littleQuery.testPrint();
littleQuery.generateQueryID();
System.out.println(littleQuery.findNumberOfQueries());
}
}
Query.java
/**************************************************************
* queryIDNumber - a long that holds the individual data of an
* individual query. Each query will have a unique number
* associated with it.
**************************************************************/
public class Query {
final Long MIN_ID_NUMBER = 1L; //minimum ID Number that can be ever generated by the program
final String QUERY_COUNT_FILE = "queryCountFile.txt"; //this file will simply hold a number that states how many queries have been created
final int SKIP_NUM_LINES_IN_FILE = 2; //the first X number of lines that will skipped in QUERY_COUNT_FILE
//final Long MAX_ID_NUMBER = 9223372036854775807L; //maximum ID Number that can be ever generated by the program
private Long queryID; //each query must have a unique ID Number which will go in the URL when the user is viewing the result of the query search.
private static Long totalQueryIDs = 0L; //holds the value of how many queries have been created over the life of the program
public Query(Long previouslyGeneratedIDNumber)
{
generateQueryID();
//totalQueryIDs++;
//OTHER FUNCTION CALLS
//WILL PROBABLY GO
//HERE LATER...
}
/**************************************************************
* generateQueryID - Generate a ID Number for a query. ID
* Number must be unique, and then is assigned to queryID
**************************************************************/
public void generateQueryID(){
Long generatedNumber;
//Finds the totalQueryIDs stored in QUERY_COUNT_FILE
generatedNumber = findNumberOfQueries();
if (generatedNumber <= MIN_ID_NUMBER){
totalQueryIDs = MIN_ID_NUMBER;
}
else {
totalQueryIDs = generatedNumber + 1L;
}
queryID = totalQueryIDs;
}
/**************************************************************
* findNumberOfQueries - This function finds out how many
* queries have been generated so far. This function will check
* a text file that will contain the past number of queries
* that have been generated.
**************************************************************/
public Long findNumberOfQueries(){
//Check a file. If queryCountFile.txt is not found then numberOfQueries is considered 0 and becomes 1?
try {
Date date = new Date();
//Assume default encoding.
FileWriter fileWriter = new FileWriter(QUERY_COUNT_FILE);
FileReader fileReader = new FileReader(QUERY_COUNT_FILE);
//Always wrap FileWriter in BufferedWriter.
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
//Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader = new BufferedReader(fileReader);
bufferedWriter.write("FILE LAST WRITTEN TO ON: " + date + "\n");
bufferedWriter.write("totalQueryIDs:\n");
bufferedWriter.write("5");
//reading from QUERY_COUNT_FILE
try{
System.out.println("got here\n"); //debug statement
String line; //temp var
//skip first SKIP_NUM_LINES_IN_FILE lines in QUERY_COUNT_FILE
for (int count = 0; count < SKIP_NUM_LINES_IN_FILE; count++) {
bufferedReader.readLine();
}
line = bufferedReader.readLine();
while (line != null) {
System.out.println("stuff bufferedReader got: " + line);
}
}
catch(IOException ex) {
System.out.println("Error reading to file '" + QUERY_COUNT_FILE + "'");
}
//Close the file.
bufferedWriter.close();
bufferedReader.close();
}
catch(IOException ex) {
System.out.println("Error writing to file '" + QUERY_COUNT_FILE + "'");
}
return totalQueryIDs;
}
}
Let me suggest you another way of reading your lines using most recent APIs method which make it easier to read and maintain (at least in my opinion) :
try(final Stream<String> fileStream = Files.lines(Paths.get("queryCountFile.txt")){
fileStream.skip(SKIP_NUM_LINES_IN_FILE)
.forEach(line -> processMyLine(line));
}
For completeness, the problem in your example is that you never re-assign line variable in your loop :
while(line != null)
should be :
while((line = bufferedReader.readLine()) != null)

Load Text file into array

Im writing a hotel console program, the problem i have at the moment is to load the saved file back to a String[], when the user presses option to load from file.
The text file includes the guest names saved earlier.
Here is the file data
tom
mo
jo
john
meg
bob
jack
veronica
jessica
angelica
And here is all the code I have
Yes thank you i know arrays are 0 index. for loops are starting from 1 because
i want to have
Room1 instead Room0 as first
THANK YOU PROBLEM SOLVED
public class FileLoad {
public String[] readLines(String filename) throws IOException {
FileReader fileReader = new FileReader(filename);
BufferedReader bufferedReader = new BufferedReader(fileReader);
List<String> lines = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
lines.add(line);
}
bufferedReader.close();
return lines.toArray(new String[lines.size()]);
}
public class Hotel_array {
if (Menu.equalsIgnoreCase("S")) {
save(hotel);
}
if (Menu.equalsIgnoreCase("L")) {
load(hotel);
}
}
}
private static void save(String hotel[]) {
try {
PrintWriter pr = new PrintWriter("data.txt");
for (int i = 1; i < 11; i++) {
pr.println(hotel[i]);
}
pr.close();
} catch (Exception e) {
e.printStackTrace();
System.out.println("No such file exists.");
}
}
public static void load(String[] args) {
FileLoad rf = new FileLoad();
String file = "data.txt";
try {
String[] hotel = rf.readLines(file);
for (String line : hotel) {
System.out.println(line); // IT PRINTS FILE NOT LOADS TO ARRAY
}
} catch (IOException e) {
System.out.println("Unable to create " + file + ": " + e.getMessage());
}
}
}
You could change your FileLoad class and add another method to write the array to the file, just to keep all the file IO in one class.
public class FileLoad {
public static String[] readHotelArray(String filename) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader(filename));
List<String> lines = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
lines.add(line);
}
bufferedReader.close();
return lines.toArray(new String[lines.size()]);
}
public static void writeHotelArray(String filename, String[] hotel) throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filename, false));
//Write each string from the array to the file as a new line
for (String s : hotel)
bufferedWriter.write(s + "\n");
bufferedWriter.flush();
bufferedWriter.close();
}
}
Note: Both methods are static so you don't have to instantiate a new object since there will always be only one method call on that object
Now you have to change the way you save and load the array in your Hotel_array class. You could use something like this:
//...
private static void save(String[] hotel) {
try {
FileLoad.writeHotelArray("data.txt", hotel);
} catch (Exception e) {
e.printStackTrace();
System.out.println("No such file exists.");
}
}
public static String[] load() {
String file = "data.txt";
String[] hotelArray = null;
try {
hotelArray = FileLoad.readHotelArray(file);
} catch (IOException e) {
System.out.println("Unable to create " + file + ": " + e.getMessage());
}
return hotelArray;
}
//...
and since parameters in java are always pass-by-value (more about that here) you need to return the String array in your load() method. And therefore you also have to change a tiny bit of code in the main method.
From:
//...
if (Menu.equalsIgnoreCase("L")) {
load(hotel);
}
//...
To:
//...
if (Menu.equalsIgnoreCase("L")) {
hotel = load();
}
//...
Hope that helps a bit (:
tomaszsvd, I will leave this here for your review... I thought it might help your Java learning curve. I encourage you to compare the load() method below with your original code. Also study the example output to see what is different.
fwiw, I like scsere's answer, it is a clean design. You should pursue that and mark it as the answer.
Let's focus on the code for Hotel_array.load( String[] args ).
Once Hotel_array.load() calls rf.readLines() you have 2 arrays in memory.
1st array: Hotel_array's main()'s local variable "hotel".
2nd array: load()'s local variable "hotel", which is a temporary variable.
Inside Hotel_array.load() remember that the args parameter ties back to main()'s "hotel" variable.
So load()'s local variable "hotel" has nothing to do with main()'s "hotel" variable.
Just to make this a little more clear I'm going to tweak your load() method:
Sample Output
$ javac *.java
$ cat data.txt
alpha
beta
gamma
delta
$ java Hotel_array
WELCOME TO THE HOTEL BOOKING
Hotel Booking Options
A: To Add customer to a room
V: To View all rooms
E: To Display empty rooms
D: To Delete customer from a room
F: Find room from customer name
O: View rooms alphabetically by name
S: Save to file
L: Load from file
L
Loaded 4 lines from filedata.txt
args[1]=empty, will assign line=alpha
args[2]=empty, will assign line=beta
args[3]=empty, will assign line=gamma
args[4]=empty, will assign line=delta
Hotel Booking Options
A: To Add customer to a room
V: To View all rooms
E: To Display empty rooms
D: To Delete customer from a room
F: Find room from customer name
O: View rooms alphabetically by name
S: Save to file
L: Load from file
V
room 1 is occupied by alpha
room 2 is occupied by beta
room 3 is occupied by gamma
room 4 is occupied by delta
room 5 is empty
room 6 is empty
room 7 is empty
room 8 is empty
room 9 is empty
room 10 is empty
Hotel Booking Options
A: To Add customer to a room
V: To View all rooms
E: To Display empty rooms
D: To Delete customer from a room
F: Find room from customer name
O: View rooms alphabetically by name
S: Save to file
L: Load from file
^C$
Modified Hotel_array.load() method
public static void load(String[] args) {
FileLoad rf = new FileLoad();
String file = "data.txt";
try {
// ORIGINAL String[] hotel = rf.readLines(file);
String[] tempHotelData = rf.readLines(file); // Note the different var name.
System.out.println("Loaded "+tempHotelData.length+" lines from file"+file);
int i = 1; // Following your convetion of staring from index #1.
for (String line : tempHotelData ) {
// ORIGINAL: System.out.println(line); // IT PRINTS FILE NOT LOADS TO ARRAY
// NEW...
// Let's print out what is oging on...
// So let's assign "line" to the "args" array.
// Remember that "args" ties back to main()'s "hotel" variable.
System.out.println("args["+i+"]="+args[i]+", will assign line="+line);
args[i] = line;
i = i + 1;
}
} catch (IOException e) {
// probably should say "Unable to LOAD" vs "Unable to CREATE"...
System.out.println("Unable to create " + file + ": " + e.getMessage());
}
}
Some additional things for you to think about...
1) Do you want to assign a line from a file if somebody is already in a room?
(e.g. it isn't empty).
2) What happens if "data.txt" has more lines than you have rooms?

Problems writing to and reading from a file

I am new to programming (Sorry if I ask an easy question) and I have a problem with my program dealing with writing to and reading from a file. To start off I ask the user what they want their username and password to be. Then to simply check if what I was doing was correct, I tried to read the file and then print out the same information. Here is my code:
public void createAccount()
{
try
{
FileWriter doc = new FileWriter("Username.ctxt", true);
System.out.print("Enter your desired Username: ");
myUsername = keyboard.next();
System.out.println();
System.out.print("Enter your desired Password: ");
myPassword = keyboard.next();
System.out.println();
String doc2 = myUsername + " " + myPassword + "\n";
doc.write(doc2, 0, doc2.length());
doc.close();
}
catch(IOException e)
{
System.out.println("Error: " + e.getMessage());
}
retrieveAccount();
}
public void retrieveAccount()
{
try
{
BufferedReader reader = new BufferedReader(new FileReader("Username.ctxt"));//
String user = new String("");//username
String pass = new String("");//password
int stop;
String line = null;
System.out.print("Enter your username: ");//allows computer to search through file and find username
username = keyboard.next();
while ((line = reader.readLine()) != null)
{
scan = reader.readLine();
stop = scan.indexOf(" ");
user = scan.substring(0, stop);
System.out.println(user);
pass = scan.substring(stop + 1);
System.out.println(pass);
if(user.equals(myUsername))
{
System.out.println("Your password is: " + pass);
break;
}
}
}
catch(IOException a)
{
System.out.println("Error: " + a.getMessage());
}
}
So what I want to happen is:
Enter desired username: jake101
Enter desired password: coolKid
Enter your username: jake101
your password is: coolKid
But what actually happens is, is and out of bounds exception(-1)
This is happening because when I use indexOf(" "); it searches for a space. And when it returns negative 1 it means there is no space. What i believe is happening is that i am not writing to the same document i am trying to read from. If anybody can help me figure out what i am doing wrong this would help!
You're double readling the contents of the file...
You first read a line from the file using...
while ((line = reader.readLine()) != null) {
The, straight after that, you read another line using...
String scan = reader.readLine();
Get rid of the second line read...
The issue is that you are calling readline twice in same loop
while ((line = reader.readLine()) != null)
{
scan = reader.readLine();
Change the above to following and it will work
while ((line = reader.readLine()) != null)
{
String scan = line;
The problem seems to be in your retrieveAccount() method, try closing ur reader object. U have opened the file in retrieveAccount() and never closed (so its stil under locked state for other applns/mthds/threads to access).
Try adding reader.close() before end of try block
I would suggest you to create seperate methods for createAccount,retrieveAccount,writeToFile and readToFile. A method should always be responsible to handle single modules. Is the actual responsibillity of createAccount method to read from a file? I would totally say no. Firstly, because low coupling - high cohesion principles are not followed and secondly, because reusabillity does not exist in this way. There are other issues that occur with your currect approach but since you are still in the beginning is expected.
I will provide you with some parts of the things you could do, however, there will be some parts that you should work on your own, like creating the User Class ( it shouldn't be difficult and it will help you learn)
So let's see.
public void createAccount(User user, ListInterface<User> userList)
throws AuthenticationException {
if (!userList.exists(user)) {
userList.append(user);
} else {
throw new AuthenticationException(
"You cannot add this user. User already exists!");
}
}
public boolean authenticate(User user, ListInterface<User> userList)
throws AuthenticationException {
for (int i = 1; i <= userList.size(); i++) {
if (user.equals(userList.get(i))
&& user.getPassword().equals(
userList.get(i).getPassword())) {
return true;
}
}
return false;
}
public void readFromFile(String fileName, ListInterface<User> userList) {
String oneLine, oneLine2;
User user;
try {
/*
* Create a FileWriter object that handles the low-level details of
* reading
*/
FileReader theFile = new FileReader(fileName);
/*
* Create a BufferedReader object to wrap around the FileWriter
* object
*/
/* This allows the use of high-level methods like readline */
BufferedReader fileIn = new BufferedReader(theFile);
/* Read the first line of the file */
oneLine = fileIn.readLine();
/*
* Read the rest of the lines of the file and output them on the
* screen
*/
while (oneLine != null) /* A null string indicates the end of file */
{
oneLine2 = fileIn.readLine();
user = new User(oneLine, oneLine2);
oneLine = fileIn.readLine();
userList.append(user);
}
/* Close the file so that it is no longer accessible to the program */
fileIn.close();
}
/*
* Handle the exception thrown by the FileReader constructor if file is
* not found
*/
catch (FileNotFoundException e) {
System.out.println("Unable to locate the file: " + fileName);
}
/* Handle the exception thrown by the FileReader methods */
catch (IOException e) {
System.out.println("There was a problem reading the file: "
+ fileName);
}
} /* End of method readFromFile */
public void writeToFile(String fileName, ListInterface<User> userList) {
try {
/*
* Create a FileWriter object that handles the low-level details of
* writing
*/
FileWriter theFile = new FileWriter(fileName);
/* Create a PrintWriter object to wrap around the FileWriter object */
/* This allows the use of high-level methods like println */
PrintWriter fileOut = new PrintWriter(theFile);
/* Print some lines to the file using the println method */
for (int i = 1; i <= userList.size(); i++) {
fileOut.println(userList.get(i).getUsername());
fileOut.println(userList.get(i).getPassword());
}
/* Close the file so that it is no longer accessible to the program */
fileOut.close();
}
/* Handle the exception thrown by the FileWriter methods */
catch (IOException e) {
System.out.println("Problem writing to the file");
}
} /* End of method writeToFile */
Useful Information:
The userList is a dynamic linked list that uses generics (ListInterface<User>)
if you dont want to use generics you could just say ListInterface userList, whereever it appears.
Your User class should implement the comparable and include the methods stated below:
public int compareTo(User user) {
}
public boolean equals(Object user) {
}
Always try to create "plug-an-play" methods(not hardcoded), that's the reason I pass as a parameter the userList.
Note that, in case that you dont use generics, typecast might be needed. Otherwise, you will get compilation errors.
If you have any questions let me know.

take in different files

Hi I am writing a program that takes in a textfile and goes through it and if it finds the message #GetFile "filename.txt" goes and gets that and stores it in the same arraylist as the first textfile but I am not able to think through the problem because if a file calls another file which calls another file and that file might be able to call another file. And I am wondering if I can call a method that contains a scanner class over and over again.
This is file one
#GetFile "fileSecond.txt"
----------
this is file two
#GetFile "fileThird.txt"
----------
this is text file three
#GetFile "fileOne.txt"
this is how different text file have it the --- <- is different textfile not same page sorry I didn't know how to show it here
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class Project3
{
public static void main(String[] args)
{
ArrayList<String> text = new ArrayList<String>();
File dictionaryFile = null; // set default value
File dictionaryFileTwo = null;
Scanner inputFile = null; // set default value
Scanner inputFileTwo = null;
// use a try-catch block to handle situations when the file is not present
keyboard = new Scanner(System.in);
// fileName = keyboard.next();
String fileName = "test1.txt";
try {
dictionaryFile = new File(fileName); // declare the file
inputFile = new Scanner(dictionaryFile);
} catch (Exception e) {
// if File object creation failed (such as when file is not there)
// then this code gets executed.
// print the directory where this program expects to find dictionary
System.out.println(System.getProperty("user.dir"));
// ensure file exists and is in the correct directory
if (!dictionaryFile.exists()) {
System.out.println("*** Error *** \n"
+ "Your text file has the wrong name or is "
+ "in the wrong directory. \n"
+ "Aborting program...\n\n");
System.exit(-1); // Terminate the program
}
}// end catch
// while there are words in the input file, add them to the dictionary
while (inputFile.hasNext()) {
if(inputFile.next().startsWith("#GetFile")){
String filing = inputFile.next();
System.out.println("HEY THIS IS THE FILE THAT I FOUND "+ filing);
String fileNameSecond = filing;
try {
dictionaryFileTwo = new File(filing); // declare the file
inputFile = new Scanner(dictionaryFile);
}catch (Exception e) {
// if File object creation failed (such as when file is not there)
// then this code gets executed.
// print the directory where this program expects to find dictionary
System.out.println(System.getProperty("user.dir"));
// ensure file exists and is in the correct directory
if (!dictionaryFile.exists()) {
System.out.println("*** Error *** \n"
+ "Your text file has the wrong name or is "
+ "in the wrong directory. \n"
+ "Aborting program...\n\n");
System.exit(-1); // Terminate the program
}
}// end catch
} else {
text.add(inputFile.nextLine());
}
}
for(int i =0; i < text.size(); i++){
System.out.println(text.get(i));
}
}
}
The basic algorithm would be:
open the output-file
ExpandIncudes(input-file, output-file) {
open input-file
while (read line from input)
if (line is-a #include) then
ExpandIncudes(input-file)
else
write line to output-file
endif
next line
}
And no, I don't think you could keep reusing the same scanner for reading different files.
Cheers. Keith.
Your question is a little muddled but it seems you need to investigate how to use some recursion here.
You'd just need a method that upon finding the "#GetFile" directive would then grab the file name to get and call the method again with this name.
public void parseFile(String filename) {
//readline while not end of file...
//is line a #GetFile directive?
//parseFile(newFilename)
}
... or something like that
Sibghatuk,
I'm going to presume that your homework's been handed in, so it's "safe" to just hand you "the answer".
I'd do it something like this:
package forums;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
public class HashInclude
{
private static final String[] INCLUDE_PATH =
System.getenv("INCLUDE_PATH").split(File.pathSeparator);
public static void main(String... args) {
try {
for ( String filename : filenames ) {
hashInclude(filename);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void hashInclude(String filename)
throws FileNotFoundException, IOException
{
BufferedReader reader = new BufferedReader(new FileReader(filename));
try {
String line = null;
int lineCount = 0;
while ( (line=reader.readLine()) != null ) {
++lineCount;
if ( line.startsWith("#include ") ) {
String targetFilename = line.replaceFirst("^#include[ \t]*", "").trim();
if ( !targetFilename.matches("^[<\"][A-z0-9_]+\\.h[\">]$") )
// not a <valid.h> or a "valid.h"
throw new IncludeException(targetFilename, lineCount, filename);
// <valid.h> --> valid.h
targetFilename = targetFilename.substring(1, targetFilename.length()-1);
// search directories in the INCLUDE_PATH for targetFilename
for ( String dir : INCLUDE_PATH ) {
File targetFile = new File(dir, targetFilename); // c:/path/to/valid.h
if ( targetFile.exists() ) {
hashInclude( targetFile.getAbsolutePath() ); // <<-- recursive call
return;
}
} // next dir
throw new FileNotFoundException("File " + targetFilename
+ " not found in INCLUDE_PATH="+ System.getenv("INCLUDE_PATH"));
} else {
System.out.println(line);
}
} // next line
} finally {
reader.close();
}
}
}
class IncludeException extends RuntimeException {
private static final long serialVersionUID = 0L;
public IncludeException(String targetFilename, int lineCount, String filename) {
super("Invalid #include: " + targetFilename + " at " + lineCount + " " + filename);
}
}
I think that the above is a "reasaonbly elegant" solution to the problem... even if I do say so myself ;-)
Note that the hashInclude method recursively calls itself... recursion lends itself naturally to following an "arbitrary tree structure"... i.e. a tree whose precise structure is unknowable when you're writing the software... and therefore "recursion" is about the first thing pops into many programmers minds when they here the word "tree".
Please note that the above code implements a greatly-simplified version of the C preprocessor #include mechanism... but could (reasonably easily) be extended into a "proper preprocessor"... one that even (recursively) expands #defines.
Cheers. Keith.

Categories