Load Text file into array - java

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?

Related

Want to seperate string every 2 new lines and add it to array

I have .txt file which I convert to string. I want to store every 2 new lines starting from the 1 all the way to the last number.
name.txt file:
imported/names/A
1/name=Arwin
2/Age=22
3/name=AJ
4/Age = 27
5/name=Anna
6/Age = 21
7/name=Avon
8/Age = 25
9/name=Atman
10/Age = 19
I want to store these contents in a array list seperating every 2 new lines:
ArrayList = ["1/name=Arwin2/Age=22","3/name=AJ4/Age = 27","5/name=Anna
6/Age = 21","7/name=Avon8/Age = 25"9/name=Atman10/Age = 19"]
So fair I have this code but the last line splitting doesnt really work because for this file I have to skip the very first line and then split the rest 2 lines at a time which makes it not work:
File file = new File(classLoader.getResource("name.txt").getFile());
String data = FileUtils.readFileToString(file, "UTF-8");
List<String> items = Arrays.asList(data.split("\\n\\n));
There are several ways to do this. Here is one using the Scanner class to read the file line by line. The strategy used in this example is to discard the first line and then use a while loop to iterate over the rest of the file.
This example assumes the file exists in the resources since the OP appears to be loading a resource file.
public List<String> extractPeople(String fileName) throws IOException, URISyntaxException {
List<String> people = new ArrayList<>();
URL url = getClass().getClassLoader().getResource(fileName);
if (Objects.isNull(url)) throw new IOException("Unable to load URL for file: " + fileName);
// try with resources and use scanner to read file one line a time
try (Scanner scanner = new Scanner(new FileReader(new File(url.toURI())))) {
// move cursor to the second line
if(scanner.hasNextLine()) scanner.nextLine();
// loop through the file
while(scanner.hasNextLine()) {
// extract the line with name
String name = scanner.nextLine();
// extract the line with the age
String age = scanner.nextLine();
// concatenate name and age and add to list of results.
people.add(name.concat(age));
}
}
return people;
}
And a simple test using a text file named "people.txt" based of the question.
#Test
void shouldLoadPeople() throws IOException, URISyntaxException {
List<String> people = extractPeople("people.txt");
assertEquals(5, people.size());
}
Just another way. As it does indeed appear that the file to read is located within a resources directory, the following runnable code will read the file in both the IDE or the distributive JAR file. The resources directory is assumed to be located within the following hierarchy:
ProjectFolder
src
resources
Users.txt
Read the comments in code:
public class ExtractDataDemo {
private final String LS = System.lineSeparator();
// Class global List to hold read in Users.
private final java.util.List<String> usersList = new java.util.ArrayList<>();
private final String resourceFile = "/resources/Users.txt";
public static void main(String[] args) {
// Started this way to avoid the need for statics.
new ExtractDataDemo().startApp(args);
}
private void startApp(String[] args) {
try {
// Read the Users.txt file
readUsers(resourceFile);
}
catch (java.io.IOException ex) {
// Display IO exceptions (if any) in Console.
System.err.println(ex);
return;
}
// Make sure the Users List contains something.
if (usersList.isEmpty()) {
System.out.println("No Users To List!");
return
}
// Display the people List contents in Console Window:
System.out.println(LS + "Users List (as List):");
System.out.println("=====================");
for (String elements : usersList) {
System.out.println(elements);
}
System.out.println();
// Display a table style formated people List in Console:
// Header...
System.out.println("Users List (as Table):");
System.out.println("======================");
System.out.printf("%-8s %-11s %-3s%n", "Import", "Name", "Age");
System.out.println("------------------------");
// Iterate through the people List so to format contents...
for (String peeps : usersList) {
// Split list element into parts for formatting.
String[] peepParts = peeps.split("/");
System.out.printf(" %-6s %-11s %-3s%n",
peepParts[0], // Import Number
peepParts[1].split("\\s*=\\s*")[1], // Name
peepParts[2].split("\\s*=\\s*")[1]); // Age
}
System.out.println("------------------------");
System.out.println(LS + "< DONE >" + LS);
// DONE
}
public void readUsers(String fileName) throws IOException {
/* Clear the usersList in case it has something
already in it from a previous operation: */
usersList.clear();
/* Read from resources directory. This will work in
both the IDE and a distributive JAR file. 'Try With
Resources' is used here to auto-close file and free
resources. */
try (java.io.InputStream in = getClass().getResourceAsStream(fileName)) {
if (in == null) {
throw new IOException("Unable To Locate Resource! (" + fileName + ")");
}
try (java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(in))) {
String line;
//Skip header line in file (don't want it this time).
line = reader.readLine();
while ((line = reader.readLine()) != null) {
// Get Import # from line (ex: "1"/name=Arwin)
String imprt = line.split("/")[0];
// Get Name from line (ex: 1/"name=Arwin")
String name = line.split("/")[1];
/* Read in the line with the age (omit the line number)
[Ex: "2/Age=22"] */
line = reader.readLine();
// Get the age from line (ex: 2/"Age=22")
String age = line.split("/")[1];
// Concatenate import number, name, and age then add to usersList.
usersList.add(imprt.concat("/").concat(name).concat("/").concat(age));
}
}
}
}
}
When the code above is run, the following is what should be displayed within the Console Window providing the Users.txt file can be found:
Users List (as List):
=====================
1/name=Arwin/Age=22
3/name=AJ/Age = 27
5/name=Anna/Age = 21
7/name=Avon/Age = 25
9/name=Atman/Age = 19
Users List (as Table):
======================
Import Name Age
------------------------
1 Arwin 22
3 AJ 27
5 Anna 21
7 Avon 25
9 Atman 19
------------------------
< DONE >

Delete specific line from text file

I want to have a method that will take the file path and then delete a specific line from a text file and this is the code I came up with.
Method.java
public class Method {
static void deletefileline(String file, Integer line) throws IOException {
ArrayList<String> filecontent = new ArrayList<String>();
try {
File myObj = new File(file);
Scanner myReader = new Scanner(myObj);
while (myReader.hasNextLine()) {
String data = myReader.nextLine();
filecontent.add(data);
}
myReader.close();
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
File f = new File(file);
f.delete();
filecontent.remove(line);
try {
File newfile = new File(file);
newfile.createNewFile();
} catch (IOException e) {
System.out.println("An Error Occured");
}
for (Integer i = 0; i < filecontent.size(); i++) {
String textToAppend = "\r\n" + filecontent.get(i);
Path path = Paths.get(file);
Files.write(path, textToAppend.getBytes(), StandardOpenOption.APPEND);
}
}
public static void main(String[] args) {
deletefileline("src/test.txt", 1);
}
}
This is the text file
test.txt
hi
hello
hii
helloo
This is the text file after i ran Methods.java
Output:
hi
hello
hii
helloo
It won't show it but at the first "hi" before that there is a space so it only added a space at line 1.
So the problem is that when it is running it only adds an extra line at line 1.
Why is not the line removed?
https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html
E remove(int index) Removes the element at the specified position in this list.
boolean remove(Object o) Removes the first occurrence of the specified element from this list, if it is present.
Since Integer line is Object and not a primitive data type int, this call
filecontent.remove(line);
tries to remove the line with a content equal to new Integer(1).
Change the method argument to int line or add type cast to the call filecontent.remove((int) line).
Why is an empty line added?
The extra space is added by this statement:
String textToAppend = "\r\n" + filecontent.get(i);
Change it like this:
String textToAppend = filecontent.get(i) + "\r\n";
This is a small snippet to perform same function as mentioned in question (kotlin version, however same can be done in java)
import java.io.File
class RemoveFileContent {
fun deleteContentAtIndex(filePath: String, indexPos: Int) {
val bufferedWriter = File("/SampleOutputFile.txt").bufferedWriter()
File(filePath).readLines().filterIndexed { i, _ -> i != indexPos }.forEach {
bufferedWriter.appendLine(it)
}
bufferedWriter.flush()
}
}
fun main(args : Array<String>) {
RemoveFileContent().deleteContentAtIndex("/SampleFile.txt",2)
}
Input : Output:
hi hi
hello hello
hii helloo
helloo
Disclaimer : Note that if your file content are huge, this can lead to high memory consumption, as stated here - How to remove first line of a text file in java

How do you allow a user to retrieve values from a list in Java?

I created a list in a FlightBookingSystem Java Class, as you can see below:
public List<Flight> getFlights() {
List<Flight> out = new ArrayList<>(flights.values());
return Collections.unmodifiableList(out);
}
Which I imported from a text file show below:
1::LX2500::Birmingham::Munich::2020-11-25::
2::LX2500::Denmark::London::2021-07-01::
3::LY2380::London::France::2021-06-28::
It's a basic text file which holds the information for each flight
Here is the code I wish to adjust:
public Flight execute(FlightBookingSystem flightBookingSystem, int id)
throws FlightBookingSystemException {
List<Flight> flights = flightBookingSystem.getFlights();
for (Flight Flight : flights) {
if (Flight.getFlightNumber() == flightNumber) {
System.out.println(Flight.getFlightNumber() + " flight(s)");
return flights.get(id);
}
System.out.println(((Flight) flights).getFlightNumber() + " flight(s)");
}
return flights.get(id);
}
How do I change that code so that it allows the user to retrieve one single record from the text file?
Why not to retrieve all and get the one you want by key or id using HashMap ?
If you still want the other option, you can read the text file line by line, and check if it startsWith(...) and the to retrieve this line.
Code example:
try (BufferedReader br = new BufferedReader(new FileReader(file)))
{
String line;
while ((line = br.readLine()) != null)
{
// Add here 'if' condition and parse your line
}
}
Your question is a bit confusing. Your title states:
How do you allow a user to retrieve values from a list in Java?
and the very last line of your post states:
How do I change that code so that it allows the user to retrieve
one single record from the text file?
Which is it, from a List or from a text file?
If it's from a List because you already have the mechanism available then is could be something similar to this:
public String getFlightInfo(String flightNumber) {
List<Flight> flights = FlightBookingSystem.getFlights();
for (Flight flite : flights) {
if(flite.getFlightNumber().equalsIgnoreCase(flightNumber)){
return flite.toString();
}
}
JOptionPane.showMessageDialog(null, "<html>Flight number <font color=red><b>"
+ flightNumber + "</b></font> could not be found!</html>", "Flight Not "
+ "Found", JOptionPane.INFORMATION_MESSAGE);
return null;
}
The code above assumes you have an overriden toString() method applied to the Flight class. If you don't then create one.
If it's actually from file then it could be something like this:
public String getFlightInfo(String flightNumber) {
// 'Try With Resouces' to auto-close reader.
try (BufferedReader reader = new BufferedReader(new FileReader("Flights.txt"))) {
String fileLine = "";
while ((fileLine = reader.readLine()) != null) {
fileLine = fileLine.trim();
// If by chance the file line read in is blank then skip it.
if (fileLine.isEmpty()) {
continue;
}
// First, remove the double colons at the end of line (if any).
if (fileLine.endsWith("::")) {
fileLine = fileLine.substring(0, fileLine.lastIndexOf("::")).trim();
}
/* Split each read in file line based on a double colon delimiter.
The "\\s*" within the regex for the split method handles any
cases where the might be one or more whitespaces before or after
the double-colon delimiter. */
String[] lineParts = fileLine.split("\\s*\\:\\:\\s*");
if(lineParts[1].equalsIgnoreCase(flightNumber)){
// At this point you could just return the line, for example:
// return fileLine;
// or you can return a string with a little more structure:
return new StringBuilder("Flight ID: ").append(lineParts[0])
.append(", Flight #: ").append(lineParts[1]).append(", From: ")
.append(lineParts[2]).append(", To: ").append(lineParts[3])
.append(", Date: ").append(lineParts[4]).toString();
}
}
}
catch (FileNotFoundException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
}
catch (IOException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
}
JOptionPane.showMessageDialog(null, "<html>Flight number <font color=red><b>"
+ flightNumber + "</b></font> could not be found!</html>", "Flight Not "
+ "Found", JOptionPane.INFORMATION_MESSAGE);
return null;
}

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.

Java, problems with string array of (string) array (maybe dynamic)

To speed-up a lookup search into a multi-record file I wish to store its elements into a String array of array so that I can just search a string like "AF" into similar strings only ("AA", "AB, ... , "AZ") and not into the whole file.
The original file is like this:
AA
ABC
AF
(...)
AP
BE
BEND
(...)
BZ
(...)
SHORT
VERYLONGRECORD
ZX
which I want to translate into
AA ABC AF (...) AP
BE BEND (...) BZ
(...)
SHORT
VERYLONGRECORD
ZX
I don't know how much records there are and how many "elements" each "row" will have as the source file can change in the time (even if, after being read into memory, the array is only read).
I tried whis solution:
in a class I defined the string array of (string) arrays, without defining its dimensions
public static String[][] tldTabData;
then, in another class, I read the file:
public static void tldLoadTable() {
String rec = null;
int previdx = 0;
int rowidx = 0;
// this will hold each row
ArrayList<String> mVector = new ArrayList<String>();
FileInputStream fStream;
BufferedReader bufRead = null;
try {
fStream = new FileInputStream(eVal.appPath+eVal.tldTabDataFilename);
// Use DataInputStream to read binary NOT text.
bufRead = new BufferedReader(new InputStreamReader(fStream));
} catch (Exception er1) {
/* if we fail the 1.st try maybe we're working into some "package" (e.g. debugging)
* so we'll try a second time with a modified path (e.g. adding "bin\") instead of
* raising an error and exiting.
*/
try {
fStream = new FileInputStream(eVal.appPath +
"bin"+ File.separatorChar + eVal.tldTabDataFilename);
// Use DataInputStream to read binary NOT text.
bufRead = new BufferedReader(new InputStreamReader(fStream));
} catch (FileNotFoundException er2) {
System.err.println("Error: " + er2.getMessage());
er2.printStackTrace();
System.exit(1);
}
}
try {
while((rec = bufRead.readLine()) != null) {
// strip comments and short (empty) rows
if(!rec.startsWith("#") && rec.length() > 1) {
// work with uppercase only (maybe unuseful)
//rec.toUpperCase();
// use the 1st char as a row index
rowidx = rec.charAt(0);
// if row changes (e.g. A->B and is not the 1.st line we read)
if(previdx != rowidx && previdx != 0)
{
// store the (completed) collection into the Array
eVal.tldTabData[previdx] = mVector.toArray(new String[mVector.size()]);
// clear the collection itself
mVector.clear();
// and restart to fill it from scratch
mVector.add(rec);
} else
{
// continue filling the collection
mVector.add(rec);
}
// and sync the indexes
previdx = rowidx;
}
}
streamIn.close();
// globally flag the table as loaded
eVal.tldTabLoaded = true;
} catch (Exception er2) {
System.err.println("Error: " + er2.getMessage());
er2.printStackTrace();
System.exit(1);
}
}
When executing the program, it correctly accumulates the strings into mVector but, when trying to copy them into the eVal.tldTabData I get a NullPointerException.
I bet I have to create/initialize the array at some point but having problems to figure where and how.
First time I'm coding in Java... helloworld apart. :-)
you can use a Map to store your strings per row;
here something that you'll need :
//Assuming that mVector already holds all you input strings
Map<String,List<String>> map = new HashMap<String,List<String>>();
for (String str : mVector){
List<String> storedList;
if (map.containsKey(str.substring(0, 1))){
storedList = map.get(str.substring(0, 1));
}else{
storedList = new ArrayList<String>();
map.put(str.substring(0, 1), storedList);
}
storedList.add(str);
}
Set<String> unOrdered = map.keySet();
List<String> orderedIndexes = new ArrayList<String>(unOrdered);
Collections.sort(orderedIndexes);
for (String key : orderedIndexes){//get strings for every row
List<String> values = map.get(key);
for (String value : values){//writing strings on the same row
System.out.print(value + "\t"); // change this to writing to some file
}
System.out.println(); // add new line at the end of the row
}

Categories