Getting a list from a text file in java - java

I currently have a database access class to pull the data from my list listed like so:
Pique:CBPique.png:41:22:55:91
Ronaldo:STRonaldo.png:89:85:92:91
...
The class is as follows:
class DatabaseAccess {
static DatabaseAccess dataAccessor;
static DatabaseAccess getInstance(String dbPath) {
if (dataAccessor == null) {
dataAccessor = new DatabaseAccess(dbPath);
}
return dataAccessor;
}
private DatabaseAccess(String dbPath) {
dbLocation = dbPath;
}
List<FootballPlayer> getCards() {
return this.getData();
}
private List<FootballPlayer> getData() {
List<FootballPlayer> theData = new ArrayList<FootballPlayer>();
// create a Scanner and grab the data . . .
Scanner scanner = null;
String dataPath = dbLocation + File.separator + "text" + File.separator + "players.db";
String imagePath = dbLocation + File.separator + "images";
try {
scanner = new Scanner(new File(dataPath));
} catch (FileNotFoundException fnf) {
System.out.println(fnf.getMessage());
System.exit(0);
}
// scan players.db file line-by-line
scanner.useDelimiter("\n");
while (scanner.hasNext()) {
String line = scanner.next().trim();
// trim used to trim for new line
String[] bits = line.split(":");
String t = bits[0]; // title
String imgFileName = bits[1]; // image file name
int pa = Integer.parseInt(bits[2]); // pace
int sh = Integer.parseInt(bits[3]); // shooting
int dr = Integer.parseInt(bits[4]); // dribbling
int ph = Integer.parseInt(bits[5]); // physical
// create the image
ImageIcon img = new ImageIcon(imagePath + File.separator + imgFileName);
// Create the business object
FootballPlayer player = new FootballPlayer(t, img, pa, sh, dr, ph);
// add it to the list ... simple as ...
theData.add(player);
}
scanner.close();
return theData;
}
What I want to do is pull the data from this list and display it / use it within another class, for example pulling the image file names for use, or even displaying all the data in a list.
Been struggling with it and any help would be really appreciated.

This could be a way your Scanner may look like: It reads the file and saves line per line into an ArrayList.
ArrayList<String> singleParts = new ArrayList<String>();
try {
int index = 0;
Scanner scanner = new Scanner( new File("files/"+filename+".txt") );
while ( scanner.hasNextLine() ) {
String actualLine = scanner.nextLine();
singleParts.add(actualLine);
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(Throwable te) {
te.printStackTrace();
}
After this, you could iterate through your ArrayList line per line, char per char. To make things easier, you could use your ':' as a seperator.
Example first line, Name:
String name = "";
boolean saved = false;
for(int line = 0; line < singleParts.size(); line++) {
for(int char = 0; char < singleParts.get(line).length(); char++) {
if(char<singleParts.get(line).indexOf(':') {
name += singleParts.get(line).charAt(char);
}
}
}
To get the rest, you have a lot of possibilities. For example, cut away the already used chars and reuse the loop similar to this one.

Does your Player object have attributes/properties that are unique, such as name or ID?
Since you already have the Player object containing all the properties you need, why not put it in a HashMap instead of Arraylist, considering if you have a key to identify the specific Player?
FootballPlayer player = new FootballPlayer(t, img, pa, sh, dr, ph);
yourKey = t // an identifier to you player, in this case i used t for example
playersMap.put(t,player);
This way you can easily retrieve your Player by using
Player myPlayer = playersMap.get(yourKey)
// you can then get the properties of the Player
myPlayer.getImg();
myPlayer.getPa();
Hope this helps

Related

NoSuchElement Exception in Thread in TextFile Program

Hi. I'm having the issue in an error of exception. I don't know what is wrong. But please help me fix this. I'm trying to store data from the file to ArrayList and display the data in the ArrayList. Here, I attached my code and data Code and data source.
the NoSuchElementException appears because you are calling input.nextToken(); while input doesn't have any token.It's due to the last empty line of your file listbook.txt. By deleting this line, the exception shouldn't appear.
A proper manner could be to ensure that you have sufficient tokens to retrieve all your fields for a given line.
public class TextFile
{
public static void main(String[] args)
{
try
{
FileReader read = new FileReader("C:\\Users\\ogawi\\Downloads\\listbook.txt");
BufferedReader bf = new BufferedReader(read);
Book B = new Book();
ArrayList<Book> bookList = new ArrayList<Book>();
String data = null;
StringTokenizer input = null;
while((data = bf.readLine()) != null)
{
input = new StringTokenizer(data,";");
//we ensure that we have enough tokens to retrieve all fields
if(input.countTokens() == 6)
{
String title = input.nextToken();
String author = input.nextToken();
String publisher = input.nextToken();
String genre = input.nextToken();
int year = Integer.parseInt(input.nextToken());
int page = Integer.parseInt(input.nextToken());
B = new Book(title, author, publisher, genre, year, page);
bookList.add(B);
}
}
//This part of code has been moved outside the while loop
//to avoid to print the total content of the array each time
//an element is added
int count=0;
for(int i=0;i<bookList.size();i++)
{
B = (Book)bookList.get(i);
System.out.println(B.toString());
System.out.println("=============================");
count++;
}
System.out.println("Number of Books: " + count);
bf.close();
}
catch(FileNotFoundException fnf)
{ System.out.println(fnf.getMessage());}
catch(EOFException eof)
{ System.out.println(eof.getMessage());}
catch(IOException io)
{ System.out.println(io.getMessage());}
finally
{ System.out.println("System end here..TQ!!");}
}
}
This issue is due to the extra line without book information:
You can see the line 31 and 32 in above figure.
To solve this issue you can add one if condition data.contains(";") . Text file has ; delimiter if we check the condition if given line has ; delimiter then it won't cause an issue.
while ((data = bf.readLine()) != null) {
if (data.contains(";")) {
input = new StringTokenizer(data, ";");
String title = input.nextToken();
String author = input.nextToken();
String publisher = input.nextToken();
String genre = input.nextToken();
int year = Integer.parseInt(input.nextToken());
int page = Integer.parseInt(input.nextToken());
B = new Book(title, author, publisher, genre, year, page);
bookList.add(B);
int count = 0;
for (int i = 0; i < bookList.size(); i++) {
B = (Book) bookList.get(i);
System.out.println(B.toString());
System.out.println("=============================");
count++;
}
System.out.println("Number of Books: " + count);
}
}
Here is the screenshot for successful execution of the code.

How to read a column from a text file in java using scanner?

I have this text that I want to read the first column from in my project named Data.txt.
//column names: productId, name,numInStock,provider,pricePerUnit
private static String records = "231A,Light Bulb,123,Wilco,1.75:"+
"113D,Hairbrush,19,Aamco,3.75:"+
"521W,Shampoo,24,Acme,6.95:"+
"440Q,Dishwashing Detergent,20,Wilco,1.75:"+
"009G,Toothbrush,77,Wilco,0.85:"+
"336C,Comb,34,Wilco,0.99:"+
"523E,Paper Pad Set,109,Congdon and Chrome,2.45:"+
"888A,Fake Diamond Ring,111,Americus Diamond,3.95:"+
"176A,Romance Nove1 1,20,Barnes and Noble,3.50:"+
"176B,Romance Nove1 2,20,Barnes and Noble,3.50:"+
"176C,Romance Nove1 3,20,Barnes and Noble,3.50:"+
"500D,Floss,44,Wilco,1.25:"+
"135B,Ant Farm,5,Wilco,8.00:"+
"211Q,Bicycle,9,Schwinn,75.95:"+
"932V,Pen Set,50,Congdon and Chrome,9.95:"+
"678Q,Pencil 50,123,Congdon and Chrome,9.95:"+
"239A,Colored Pencils,25,Congdon and Chrome,4.75:"+
"975B,Shower Curtain,25,Wilco,6.50:"+
"870K,Dog Bowl,15,Wilco,4.75:"+
"231S,Cat Bowl,15,Wilco,4.75:"+
"562M,Kitty Litter,15,Wilco,3.25:"+
"777X,Dog Bone,15,Wilco,4.15:"+
"933W,Cat Toy,15,Wilco,2.35:"+
"215A,Hair Ball,0,Little Jimmy,0.00:";
I wrote this code to do so but I am not getting the desired output.
My code is
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Scanner input = new Scanner(System.in);
File file = new File("C:\\Users\\student\\Desktop\\workspace\\Welcome\\src\\Data.txt");
input = new Scanner(file);
while (input.hasNextLine()) {
String line = input.nextLine();
String[] words = line.split(",");
System.out.println(words[0]);
input.useDelimiter(",");
}
input.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
I want to get the output in this format
134A
213A
911C
012E
662Z
This is the output I got I want to remove the part that says private static String records = and also the ".
//column names: productId
private static String records = "231A
"113D
"521W
"440Q
"009G
"336C
"231S
You're sort-of on the right track with the delimeters.
Here's how I did it and it can be cleaned up a bit, and you'll have to make a for loop to iterate through the arraylist and get each one, and split each one and print each one's 0'th index ( "str" is the string/text file you provided )
Scanner in = new Scanner(str) ;
in.useDelimiter(":") ;
ArrayList<String> al = new ArrayList<>() ;
while( in.hasNext())
{
al.add(in.next() ) ;
}
for( int i = 0 ; i < al.size(); ++i )
{
String s = al.get(i) ;
String[] s2 = s.split(",") ;
System.out.println( s2[0] );
}

optimising the search time in hashmap

I have a csv file which is hashmapped, whenever the user enter the city name(key) it will display all the details of that city. I have to optimize the search result time, everytime the it is reading the file(instead of only once) and displaying the values.
The CSV files contains data like this :
city,city_ascii,lat,lng,country,iso2,iso3,admin_name,capital,population,id
Malishevë,Malisheve,42.4822,20.7458,Kosovo,XK,XKS,Malishevë,admin,,1901597212
Prizren,Prizren,42.2139,20.7397,Kosovo,XK,XKS,Prizren,admin,,1901360309
Zubin Potok,Zubin Potok,42.9144,20.6897,Kosovo,XK,XKS,Zubin
Potok,admin,,1901608808
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
import java.io.IOException;
public class CSVFileReaders{
public static void main(String[] args) {
String filePath = "C:\\worldcities1.csv";
Scanner in = new Scanner(System.in);
System.out.println(" \n Enter the City name to be Searched : \n _> ");
long start = System.currentTimeMillis();
String searchTerm = in.nextLine();
readAndFindRecordFromCSV(filePath, searchTerm);
long end = System.currentTimeMillis();
System.out.println(" \n It took " + (end - start) + " Milli Seconds to search the result \n");
in.close();
}
public static void readAndFindRecordFromCSV( String filePath, String searchTerm) {
try{
HashMap<String,ArrayList<String>> cityMap = new HashMap<String,ArrayList<String>>();
Scanner x = new Scanner (new File(filePath),"UTF-8");
String city= "";
while(x.hasNextLine()) {
ArrayList<String> values = new ArrayList<String>();
String name = x.nextLine();
//break each line of the csv file to its elements
String[] line = name.split(",");
city = line[1];
for(int i=0;i<line.length;i++){
values.add(line[i]);
}
cityMap.put(city,values);
}
x.close();
//Search the city
if(cityMap.containsKey(searchTerm)) {
System.out.println("City name is : "+searchTerm+"\nCity details are accordingly in the order :"
+ "\n[city , city_ascii , lat , lng , country , iso2 , iso3 , admin_name , capital , population , id] \n"
+cityMap.get(searchTerm)+"");
}
else {
System.out.println("Enter the correct City name");
}
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}`
the time should be optimized and every time i search it is reading the entire file(which should happen)
Currently you mix the map initialization inside the search function.
You don't want that.
First, init the map, then use it in the search function.
To do that, extract a method for statements that instantiate and value the map and then refactor the readAndFindRecordFromCSV() method so that it accepts a Map as additional parameter :
public static void readAndFindRecordFromCSV( String filePath, String searchTerm, HashMap<String,ArrayList<String>> dataByCity) {...}
With refactoring IDE features, it should be simple enough : "extracting method" then "change signature".
Here is a code (not tested at runtime but tested at compile time) that splits the logical in separated tasks and also rely on instance methods :
public class CSVFileReaders {
private final String csvFile;
private HashMap<String, ArrayList<String>> cityMap;
private final Scanner in = new Scanner(System.in);
public static void main(String[] args) {
String filePath = "C:\\worldcities1.csv";
CSVFileReaders csvFileReaders = new CSVFileReaders(filePath);
csvFileReaders.createCitiesMap();
csvFileReaders.processUserFindRequest(); // First search
csvFileReaders.processUserFindRequest(); // Second search
}
public CSVFileReaders(String csvFile) {
this.csvFile = csvFile;
}
public void createCitiesMap() {
cityMap = new HashMap<>();
try (Scanner x = new Scanner(new File(csvFile), "UTF-8")) {
String city = "";
while (x.hasNextLine()) {
ArrayList<String> values = new ArrayList<String>();
String name = x.nextLine();
//break each line of the csv file to its elements
String[] line = name.split(",");
city = line[1];
for (int i = 0; i < line.length; i++) {
values.add(line[i]);
}
cityMap.put(city, values);
}
x.close();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
public void processUserFindRequest() {
System.out.println(" \n Enter the City name to be Searched : \n _> ");
long start = System.currentTimeMillis();
String searchTerm = in.nextLine();
long end = System.currentTimeMillis();
System.out.println(" \n It took " + (end - start) + " Milli Seconds to search the result \n");
//Search the city
if (cityMap.containsKey(searchTerm)) {
System.out.println("City name is : " + searchTerm + "\nCity details are accordingly in the order :"
+ "\n[city , city_ascii , lat , lng , country , iso2 , iso3 , admin_name , capital , population , id] \n"
+ cityMap.get(searchTerm) + "");
} else {
System.out.println("Enter the correct City name");
}
}
}
The interesting part is here :
String filePath = "C:\\worldcities1.csv";
CSVFileReaders csvFileReaders = new CSVFileReaders(filePath);
csvFileReaders.createCitiesMap();
csvFileReaders.processUserFindRequest(); // First search
csvFileReaders.processUserFindRequest(); // Second search
The logical is clearer now.
Why do you create / load the CSV into a HashMap with every search ?
Just create the HashMap only once in the beginning, and then on every search just check whether it exists in the HashMap, eg move the read part into a separate method :
HashMap<String,ArrayList<String>> cityMap = new HashMap<String,ArrayList<String>>();
public static void readCSVIntoHashMap( String filePath) {
try{
Scanner x = new Scanner (new File(filePath),"UTF-8");
String city= "";
while(x.hasNextLine()) {
ArrayList<String> values = new ArrayList<String>();
String name = x.nextLine();
//break each line of the csv file to its elements
String[] line = name.split(",");
city = line[1];
for(int i=0;i<line.length;i++){
values.add(line[i]);
}
cityMap.put(city,values);
}
x.close();
...
}
Then have a separate method for searching :
public static void search(String searchTerm) {
if(cityMap.containsKey(searchTerm)) {
...
}
}

Assign a unique key to repeated Arraylist items. and Keep track of Ordering in java

I have a data like :
in an arraylist of Strings I am collecting names .
example:
souring.add(some word);
later I have something in souring = {a,b,c,d,d,e,e,e,f}
I want to assign each element a key like:
0=a
1=b
2=c
3=d
3=d
4=e
4=e
4=e
5=f
and then I store all ordering keys in an array . like:
array= [0,1,2,3,3,4,4,4,5]
heres my code on which I am working :
public void parseFile(String path){
String myData="";
try {
BufferedReader br = new BufferedReader(new FileReader(path)); {
int remainingLines = 0;
String stringYouAreLookingFor = "";
for(String line1; (line1 = br.readLine()) != null; ) {
myData = myData + line1;
if (line1.contains("relation ") && line1.endsWith(";")) {
remainingLines = 4;//<Number of Lines you want to read after keyword>;
stringYouAreLookingFor += line1;
String everyThingInsideParentheses = stringYouAreLookingFor.replaceFirst(".*\\((.*?)\\).*", "$1");
String[] splitItems = everyThingInsideParentheses.split("\\s*,\\s*");
String[] sourceNode = new String[10];
String[] destNode = new String[15];
int i=0;
int size = splitItems.length;
int no_of_sd=size;
tv.setText(tv.getText()+"size " + size + "\n"+"\n"+"\n");
sourceNode[0]=splitItems[i];
// here I want to check and assign keys and track order...
souring.add(names);
if(size==2){
destNode[0]=splitItems[i+1];
tv.setText(tv.getText()+"dest node = " + destNode[0] +"\n"+"\n"+"\n");
destination.add(destNode[0]);
}
else{
tv.setText(tv.getText()+"dest node = No destination found"+"\n"+"\n"+"\n");
}
} else if (remainingLines > 0) {
remainingLines--;
stringYouAreLookingFor += line1;
}
}
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
How can I do this?
can any one help me in this..?
I would advise you to use ArrayList instead of String[]
So, if you want to add an element you just write
ArrayList<String> list = new ArrayList<String>;
list.add("whatever you want");
Then, if you want to avoid repetitions just use the following concept:
if(!list.contains(someString)){
list.add(someString);
}
And if you want to reach some element you just type:
list.get(index);
Or you can easily find an index of an element
int index=list.indexOf(someString);
Hope it helps!
Why don't you give it a try, its take time to understand what you actually want.
HashMap<Integer,String> storeValueWithKey=new HashMap<>();
// let x=4 be same key and y="x" be new value you want to insert
if(storeValueWithKey.containsKey(x))
storeValueWithKey.get(x)+=","+y;
else
storeValueWithKey.put(z,y); //Here z is new key
//Than for searching ,let key=4 be value and searchValue="a"
ArrayList<String> searchIn=new ArrayList<>(Arrays.asList(storeValueWithKey.get("key").split(",")));
if(searchIn.contains("searchValue"))
If problem still persist than comment

This code keeps formatting the file instead of writing to it. How do i fix it?

I have declared an array and and variables up here. productList array, name, price and number
import java.io.*;
import java.util.*;
public class ReadingAndWritting {
public String name;
public double price;
public int number;
public ReadingAndWritting[] productList = new ReadingAndWritting[3];
public ReadingAndWritting() {
}
public ReadingAndWritting(String name, double price, int number) {
this.name = name;
this.price = price;
this.number = number;
}
public void printContents() {
int i = 0;
try {
FileReader fl = new FileReader("Product List.txt");
Scanner scn = new Scanner(fl);
while (scn.hasNext()) {
String productName = scn.next();
double productPrice = scn.nextDouble();
int productAmount = scn.nextInt();
System.out.println(productName + " is " + productPrice + " pula. There are " + productAmount + " items left in stalk.");
productList[i] = new ReadingAndWritting(productName, productPrice, productAmount);
i = i + 1;
}
scn.close();
} catch (IOException exc) {
exc.printStackTrace();
} catch (Exception exc) {
exc.printStackTrace();
}
}
public void writeContents() {
try {
//FileOutputStream formater = new FileOutputStream("Product List.txt",true);
Formatter writer = new Formatter(new FileOutputStream("Product List.txt", true));
for (int i = 0; i < productList.length; ++i) {
writer.format(name, (price + 100.0), (number - 1), "\n");
}
writer.close();
} catch (IOException exc) {
exc.printStackTrace();
}
}
public static void main(String[] args) {
ReadingAndWritting obj = new ReadingAndWritting();
System.out.println("_____THIS IS THE BEGINNING OF THE PRODUCT LIST_____");
obj.printContents();
System.out.println("_____THIS IS THE END OF THE PRODUCT LIST_____");
System.out.println("_____THIS IS THE BEGINNING OF THE PRODUCT LIST_____");
obj.writeContents();
obj.printContents();
System.out.println("_____THIS IS THE END OF THE PRODUCT LIST_____");
}
}
Every time i run the code it keeps formatting the existing file and then reporting a NullPointerException. I am completely lost as to how to fix this and our lecturer never covered it. Please
the productList[] array has name,price and number value contained in each identifier. I want to wipe the contents of the existing file and then write with the new values to update contents from the array
The constructor you are using truncates the input file, as clearly stated in the Javadoc :
fileName The name of the file to use as the destination of this formatter. If the file exists then it will be truncated to zero size; otherwise, a new file will be created. The output will be written to the file and is buffered.
You can use other constructors, such as Formatter(OutputStream os) to avoid that truncation.
Formatter writer = new Formatter(new FileOutputStream("Product List.txt",true));
As for the NullPointerException, seeing your comment of :
public String name;
name is not initialized, so it is null by default, which leads to the NullPointerException.
P.S. I don't know what productList is, by based on its name and the fact that you are iterating over it, perhaps you should get the price and name from the elements of that list.
EDIT :
Based on the rest of your code, you should take the values from the productList array :
for (int i = 0; i < productList.length; ++i) {
writer.format(productList[i].name, (productList[i].price + 100.0), (productList[i].number - 1), "\n");
}
writer.format(name, (price + 100.0), (number - 1), "\n");
has the incorrect parameters. Due to which its giving the NullPointerException.
Read the Java doc to know about the correct parameters that should be passed.
Do something like this:
public String str=null; //declare class variable str.
In the printContents() method assign the following to the string:
str = "\n"+productName +" "+ (productPrice + 100.0)+" "+ (productAmount - 1)+"\n";
And then finally method, change the parameters being passed to writer.format() method like this:
Formatter writer = new Formatter(new FileOutputStream("Product List.txt", true));
for (int i = 0; i < productList.length; ++i) {
writer.format(str);
}
This is working for me.
The value you want is getting properly appended in the file "ProductList.txt".

Categories

Resources