Writing to Text File from Comma Delimited ArrayList - java

I have created a Song class that includes data members for a Song (Title, artist, album,length). I already have a .txt file that contains different songs which is stored into an array list. After the user finishes adding or deleting songs the program should write to the text file in the original format of the text file (comma separated).
My problem is that the program writes to the file without the commas and it is causing my program to crash when I re-run it by getting an ArrayIndexOutOfBoundsException. I have attempted to use nested for-loops and the printf function but have had no success. How can i write to the file with its original formatting and avoid crashing after i write to it and attempt to run it again?
This is the format of the .txt File
Rock Lobster,The B-52's,The B-52's,4:37
Walk Like An Egyptian,The Bangles,Different Light,3:24
This is my Song Class with toString() method
public class Song {
//Declaring all data members.
private String title;
private String artist;
private String album;
private String length;
private static int songCounter = 0;
//Constructors for Song class.
public Song(String title, String artist, String album, String length){
this.title = title;
this.artist = artist;
this.album = album;
this.length = length;
songCounter++;
}
//Get and Set methods
public String getTitle(){
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist(){
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getAlbum(){
return album;
}
public void setAlbum(String album){
this.album = album;
}
public String getLength(){
return length;
}
public void setLength(String length){
this.length = length;
}
public static int getSongCounter(){
return songCounter;
}
public int compareArtist(Song o){
return artist.compareTo(o.artist);
}
public int compareTitle(Song o){
return title.compareTo(o.title);
}
//Overriding the toString() function.
#Override
public String toString(){
return title +","+artist+","+album+","+length;
}
}
This is my Main Class that reads from the file and contains a write method
public class Library {
public static void main(String[] args) {
ArrayList <Song> songList = new ArrayList <Song> ();
boolean repeat = true;
try{
Scanner read = new Scanner (new File("SongList.txt"));
do{
String line = read.nextLine();
String [] tokens = line.split(",");
songList.add(new Song(tokens[0], tokens[1], tokens[2], tokens[3]));
}while(read.hasNext());
read.close();
}catch (FileNotFoundException e){
System.out.println("File not found.");
}
while ( repeat ){
System.out.println("\nSelect a Function");
System.out.println("1. Search Song");
System.out.println("2. Add Song");
System.out.println("3. Delete Song");
System.out.println("4. Display Songs");
System.out.println("5. Quit");
switch (MenuInputCheck(1, 5)){
case 1: searchSong(songList);
break;
case 2: addSong(songList);
break;
case 3: deleteSong(songList);
break;
case 4: displaySorted(songList);
break;
case 5: saveFile(songList);
repeat = false;
break;
}
}
}
public static void saveFile(ArrayList <Song> songList){
try{
PrintWriter writer = new PrintWriter("SongList.txt");
for (int i = 0; i < songList.size();i++){
writer.println(i);
}
writer.close();
} catch (FileNotFoundException e){
System.out.println("File not found.");
}
}

presently the code is simply writing an integer
for (int i = 0; i < songList.size();i++){
writer.println(i);
}
I suggest you create a method in Song which will write its fields sperated by commas
e.g.
public String writeMe () {
StringBuffer buf = new StringBuffer ();
buf.append (name).append(",").append(artist).....;
return buf.toString ();
}
and then in your loop call
writer.write (singList.get(i).writeMe ();
Update
Using you updated code you can get the output using
writer.println(song.toString());

You're writing the value of i to the file?? You should be writing the song information. In the absents of your Song class, I'm just making up fields and methods
If you're using Java 8 you can use the StringJoiner API...
public static void saveFile(ArrayList <Song> songList){
try{
PrintWriter writer = new PrintWriter("SongList.txt");
for (Song song : songList){
StringJoiner sj = new StringJoiner(",");
sj.add(song.getTitle());
sj.add(song.getArtiest());
sj.add(song.getAlbum());
sj.add(song.getDuration());
writer.println(sj.toString());
}
writer.close();
} catch (FileNotFoundException e){
System.out.println("File not found.");
}
}
Otherwise you will need to use something like a String#format or a StringBuilder to generate the output...
Now might be the time to introduce you to JAXB...
Updated
So, based on your updated code, including the Song class, you should be able to do something as simple as...
public static void saveFile(ArrayList <Song> songList){
try{
PrintWriter writer = new PrintWriter("SongList.txt");
for (Song song : songList){
writer.println(song.toString());
}
writer.close();
} catch (FileNotFoundException e){
System.out.println("File not found.");
}
}

Related

Java - parsing a 2nd csv file to override a value

I have two csv files. One shows all crime data including City, State, Population etc. The other shows State and Abbreviation. I want to have the state set as the abbreviation, currently I have some very long code and I'm thinking there is definitely a better way at setting it based on the abbreviation csv file.
My main class:
public class StartApp {
public static ArrayList<CityCrime> crimes = new ArrayList<CityCrime>();
public static ArrayList<String> cities = new ArrayList<String>();
/**
* Start point for app. Directs the reads from file and shows the menu
* #param args
*/
public static void main(String[] args) {
try {
readCrimeData("crimeUSA.csv");
System.out.println("Total cities read: " + getTotalCities());
showMenu();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Reads the crime data for each city from entered file
* Adds the CityCrime objects to the crimes ArrayList
*/
public static void readCrimeData(String fromFile) {
File file = new File(fromFile);
FileReader fileReader;
BufferedReader bufferedReader;
String crimeInfo;
String[] stats;
try {
fileReader = new FileReader(file);
bufferedReader = new BufferedReader(fileReader);
crimeInfo = bufferedReader.readLine();
crimeInfo = bufferedReader.readLine();
do {
CityCrime crime = new CityCrime(); // Default constructor
stats = crimeInfo.split(",");
{
if (stats[0] != null) {
crime.setCity(stats[0]);
}
if (stats[1] != null) {
crime.setState(stats[1]);
}
if (stats[2] != null) {
if (Integer.parseInt(stats[2]) >= 0) {
crime.setPopulation(Integer.parseInt(stats[2]));
}
}
if (stats[3] != null) {
if (Integer.parseInt(stats[3]) >= 0) {
crime.setMurder(Integer.parseInt(stats[3]));
}
}
if (stats[4] != null) {
if (Integer.parseInt(stats[4]) >= 0) {
crime.setRobbery(Integer.parseInt(stats[4]));
}
}
if (stats[5] != null) {
if (Integer.parseInt(stats[5]) >= 0) {
crime.setAssault(Integer.parseInt(stats[5]));
}
}
if (stats[6] != null) {
if (Integer.parseInt(stats[6]) >= 0) {
crime.setBurglary(Integer.parseInt(stats[6]));
}
}
if (stats[7] != null) {
if (Integer.parseInt(stats[7]) >= 0) {
crime.setLarceny(Integer.parseInt(stats[7]));
}
}
if (stats[8] != null) {
if (Integer.parseInt(stats[8]) >= 0) {
crime.setMotorTheft(Integer.parseInt(stats[8]));
}
}
crime.setTotalCrimes(Integer.parseInt(stats[3]), Integer.parseInt(stats[4]), Integer.parseInt(stats[5]), Integer.parseInt(stats[6]), Integer.parseInt(stats[7]), Integer.parseInt(stats[8]));
}
crimes.add(crime);
System.out.println(crime);
crimeInfo = bufferedReader.readLine();
} while (crimeInfo != null);
fileReader.close();
bufferedReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* For each crime, add the city to the cities ArrayList and return the count
*/
public static int getTotalCities() {
for(CityCrime crime : crimes) {
cities.add(crime.getCity());
}
int cityCount = cities.size();
return cityCount;
}
/**
* Displays the menu
* User can select which function they want to run
* #throws IOException
*/
#SuppressWarnings("unlikely-arg-type")
public static void showMenu() throws IOException {
#SuppressWarnings("resource")
Scanner menuSelect = new java.util.Scanner(System.in);
System.out.println("1. Display all crime stats by city");
System.out.println("2. Display all crime stats by selected city");
System.out.println("3. Display the murder stats by selected state ");
System.out.println("4. Display highest crime city - all crimes");
System.out.println("5. Display each state (in alphabetical order with the number of car thefts ");
System.out.println("6. Write / export all cities in descending order of Robbery rate ");
System.out.println("7. Quit");
System.out.println("Enter option 1-7");
#SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
int option = Integer.parseInt(menuSelect.next());
if(option<1 || option>7 ) {
System.out.println("Invalid input.");
return;
}
switch (option) {
case 1:
displayAllCityCrimeStats();
break;
case 2:
System.out.println("Enter city");
String cityOption = menuSelect.next();
displayCrimeStatsByCity(cityOption);
break;
case 3:
System.out.println("Enter state");
String stateOption = menuSelect.next();
displayMurdersByState(stateOption);
break;
case 4:
displayHighestCrimeStats();
break;
case 5:
displayStateCarThefts();
break;
case 6:
writeToFile("Robbery.csv");
break;
case 7:
return;
default:
option = Integer.parseInt(scanner.next());
}
}
My CityCrime file. It is a mess right now as I don't know what the right direction to go in is. I have cut down the setStates, there are 52 in reality so it's pretty long:
public class CityCrime {
//Instance variables
private String city;
private String state;
private int population;
private int murder;
private int robbery;
private int assault;
private int burglary;
private int larceny;
private int motorTheft;
public int totalCrimes;
public static ArrayList<CityState> abbreviations = new ArrayList<CityState>();
public String fromFile = ("C:/Users/ebeck/Downloads/StateAbbreviations.csv");
public static void main(String[] args) {
}
public static void readAbbrevData(String fromFile) {
File file = new File(fromFile);
FileReader fileReader;
BufferedReader bufferedReader;
String abbrevInfo;
String[] stats;
try {
fileReader = new FileReader(file);
bufferedReader = new BufferedReader(fileReader);
abbrevInfo = bufferedReader.readLine();
abbrevInfo = bufferedReader.readLine();
do {
CityState abbrev = new CityState(); // Default constructor
stats = abbrevInfo.split(",");
{
if (stats[0] != null) {
abbrev.setState(stats[0]);
}
if (stats[1] != null) {
abbrev.setAbbreviation(stats[1]);
}
}
abbreviations.add(abbrev);
System.out.println(abbrev);
abbrevInfo = bufferedReader.readLine();
} while (abbrevInfo != null);
fileReader.close();
bufferedReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
if(state.equalsIgnoreCase("ALABAMA")) {
this.state = "AL";
}
else if(state.equalsIgnoreCase("ALASKA")) {
this.state = "AK";
}
else if(state.equalsIgnoreCase("ARIZONA")) {
this.state = "AR";
}
else if(state.equalsIgnoreCase("ARKANSAS")) {
this.state = "AR";
}
else if(state.equalsIgnoreCase("CALIFORNIA")) {
this.state = "CA";
}
else if(state.equalsIgnoreCase("COLORADO")) {
this.state = "CO";
}
else if(state.equalsIgnoreCase("CONNECTICUT")) {
this.state = "CT";
}
//etc
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
public int getMurder() {
return murder;
}
//etc
}
I created a CityState file, however may be unnecessary:
public class CityState {
private String state;
private String abbreviation;
public static void main(String[] args) {
}
public String getState() {
return state;
}
public String getAbbreviation() {
return abbreviation;
}
public void setAbbreviation(String abbreviation) {
this.abbreviation = abbreviation;
}
public void setState(String state) {
this.state = state;
}
}
A couple reasons I want to change how I've set up the get state is 1. for my Junit test for state:
#Test
public void testValidState() {
CityCrime crimes = new CityCrime();
crimes.setState(state);
assertEquals(crimes.getState(), state);
}
I was getting the error:
expected: <A[K] but was: <A[LASKA]> if I set the state to "Alaska"
Then if I set it to "AK" I got the error:
expected: but was:
and 2. it doesn't look great either and I want to learn a better way
Thankyou for your help I appreciate it
Edit:
For each crime, if the state in CityCrimes csv file is equal to the state in the StatesAbbreviations file, then set the state as the abbreviation in the StatesAbbreviations file and return
Okay, first of all, I think it's better to split the data from the data parsing.
One class = one representation. Here CityCrime has two goals: represent quantity of crimes in a City (the goal indicated by the class name) and parse the abbreviation list. So I think it's better to create a new class whose goal is the parsing of your abbreviations.
Next, there is a consistency problem: you have a function that parse your abbreviation CSV, but you have also a list of if to "convert" a state name to a state abbreviation (setState function). There is, according to me, two ways to do this:
Define State as a type
Define State as resource
State as a type
The advantage of this method is to benefit from a strong typing. Indeed, with your setState solution, you define a State as a String, and you have to check if the passed value is correct (succession of if). Moreover, as it remains a String, you have no guarantee that the value returned by getState is formatted well (you have to trust all the functions that write on state variable).
So the solution here is to defined State as a type, using, for example, Enumeration.
public enum State {
ALABAMA("AL"),
ALASKA("AK"),
ARIZONA("AR"),
ARKANSAS("AR"),
CALIFORNIA("CA"),
COLORADO("CO"),
CONNECTICUT("CT");
private String abbreviation;
State(String abbreviation) {
this.abbreviation = abbreviation;
}
public String getAbbreviation() {
return abbreviation;
}
}
An enum is a particular type of class. Indeed, this one is not direclty instanciable (you can't do new State("foo")). The accepted instances for this type are defined as an enumeration, at the start of the class (ALABAMA, ALASKA...). So State.ALABAMA has for type State and State.ALABAMA.getAbbrevation() returns AL.
This solution works only if the set of all your states is closed, so if your have a fixed number of state.
In this situation, your state variable would have for type State, and your setState function would take a State variable. This is strong typed, because you can't pass a value that is not valid to the function (except null).
How to convert a State name to a State variable ?
Enumeration classes have a valueOf(String name) function. The parameter is the identifier of the enum constant (ALABAMA, ALASKA) as a String, and the returned value is the enum constant as State. If any enum constant was found, an IllegalArgumentException is throwed. This solution works well, but the string must correspond exactly to the identifier (case included).
If you want to do a similar function, but ignoring case, you can use values function that returns an array of all State values (State[]). For example:
public static State valueOfIgnoreCase(String name) {
for(var state: State.values())
if(state.name.equals(name)) // name function return the exact identifier of the state
return state;
return null; // Or throw IllegalArgumentException
}
This function can be create in the State class.
State as a resource
Another solution is to define State as a resource, that is, in an external file (or resource file). The advantage is you can add new State dynamically, without having to modify the program code. It's the solution you use with your parser.
For this solution, the parser is in a separated class.
Instead of put all your State in an List, you can put in a Map:
public class AbbreviationParser {
public static Map<String, State> parseState(InputStream stream) throws IOException { // InputStream is better than String or File, because it abstract the type of input (can works with a simple file, a network stream, a text downloaded from Internet...)
final var map = new HashMap<String, State>();
final var reader = new BufferedReader(new InputStreamReader(stream)); // Define a reader on the stream then bufferize it for better performance
reader.readLine();
String line;
while((line = reader.readLine()) != null) { // As long as there is an unread line
var array = line.split(",");
if(array.length == 2) {// Important, because if your line does not contain a comma, your actual code will crash at "array[1]"
var state = new State();
state.setState(array[0]);
state.setAbbreviation(array[1]);
map.put(state.getState(), state);
} else {
//TODO define a behavior if the line is not valid
}
}
reader.close();
stream.close();
return map;
}
To call this function for a File:
parseState(new FileInputStream(fromFile)); // FileInputStream is an implementation of InputStream for File
To secure your State from external instantiation, you can put the State constructor in package-only scope, and place this class and AbbreviationParser in the same package. Like this, only the class on the same package (so AbbreviationParser) can instantiate State, and you are thus sure not to have an incorrect value passed to your setState(State state):
public class State {
private String state;
private String abbreviation;
State() {}
public String getState() {
return state;
}
public String getAbbreviation() {
return abbreviation;
}
public void setAbbreviation(String abbreviation) {
this.abbreviation = abbreviation;
}
public void setState(String state) {
this.state = state;
}
}
Even if you prefer the first method for your State, I recommend you to take inspiration from my parser for your first CSV parser and to isolate it in a separated class.
You want to replace certain values in the first CSV file with corresponding values in the second CSV file. The code will be extremely long if you use Java to perform the association.
But it is easy to do the coding job using Java’s open-source package SPL. One line of code is enough:
+
1
=file("crimeUSA.csv").import#ct().switch(State,file("StateAbbreviations.csv").import#ct():State).new(City,State.Abbreviation: StateAbbreviation,Population,Murder,Robbery,Assault,Burglary,Larceny,MotorTheft,TotalCrimes)
SPL offers JDBC driver to be invoked by Java. Just store the above SPL script as abbr.splx and invoke it in Java as you call a stored procedure:
…
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
st=con.prepareCall("call abbr()");
st.execute();
…
Or execute the SPL string within a Java program as we execute a SQL statement:
…
st = con.prepareStatement("==file(\"crimeUSA.csv\").import#ct().
switch(State,file(\"StateAbbreviations.csv\").import#ct():State)
.new(City,State.Abbreviation,Population,Murder,Robbery,Assault
,Burglary,Larceny,MotorTheft,TotalCrimes)");
st.execute();
…

Java file-I/O not reading

I have a problem with maing java reading a file for me. I have a .txt-file with all the danish islands but somehow it will not display in the console no matter how i try.
This is the class with the main method. From here it reads the file and splits the lines in order to put the data into an ArrayList.
public class DanishIslandFileReader {
private File inFile;
private List<DanishIsland> islandList;
public DanishIslandFileReader(String fName) {
inFile = new File(fName);
}
private void readFile() {
islandList = new ArrayList<DanishIsland>();
Scanner scan = null;
try {
scan = new Scanner(inFile);
} catch (FileNotFoundException fnfe) {
System.out.println(fnfe);
}
while (scan.hasNext()) {
String line = scan.nextLine();
String[] tokens = line.split(" ");
String name = tokens[0];
double circ = Double.parseDouble(tokens[1]);
double area = Double.parseDouble(tokens[2]);
int addr = Integer.parseInt(tokens[3]);
int adkm = Integer.parseInt(tokens[4]);
DanishIsland island = new DanishIsland(name, circ, area, addr, adkm);
System.out.println(island.toString());
islandList.add(island);
}
scan.close();
}
public List<?> getList() {
return islandList;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException {
System.out.println(new File(".").getAbsolutePath());
// DanishIslandFileReader fr = new DanishIslandFileReader("Islands punktum.txt");
DanishIslandFileReader fr = new DanishIslandFileReader("Islands komma.txt");
fr.readFile();
System.out.println("Result:\n" + fr.getList());
}
}
When the line has been split it goes through another class which turns the data into a String and puts it into another Arraylist which will be printed in the consol.
public class DanishIsland {
private String name;
private double circumference;
private double area;
private int addresses;
private int addrPerKm2;
public DanishIsland(String name, double circumference, double area,
int addresses, int addrPerKm2) {
super();
this.name = name;
this.circumference = circumference;
this.area = area;
this.addresses = addresses;
this.addrPerKm2 = addrPerKm2;
}
public String getName() {
return name;
}
public double getCircumference() {
return circumference;
}
public double getArea() {
return area;
}
public int getAddresses() {
return addresses;
}
public int getAddrPerKm2() {
return addrPerKm2;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(name);
builder.append("\t");
builder.append(circumference);
builder.append("\t");
builder.append(area);
builder.append("\t");
builder.append(addresses);
builder.append("\t");
builder.append(addrPerKm2);
builder.append("\n");
return builder.toString();
}
}
I do not get any errors or exceptions and the program run till it thinks the list has been printed.
Problem is that the list is empty and I can't seem to make any sort of "sout" from the .txt-file. Whar am I doing wrong?
Lolland 298,388 1234,96 38919 32
Bornholm 108,047 588,025 27125 46
Falster 145,926 516,268 26654 52
Mors 139,254 361,745 12374 34
Have you tried debugging it?
I think it is not entering
while (scan.hasNext())
because scan.hasNext returns false.
This could be a file permission issue.
Also this may be related:
Why is hasNext() False, but hasNextLine() is True?

Separating Parsing Method

I'm creating a program which handles SKU's. I currently have two classes in my program, the SKU class is the main class and a Store class in which an ArrayList is initialised and SKU objects are stored in the array. I currently have a method in my SKU class which takes input from a file, parses the data and stores the data using a String tokenizer in the objects variables and adds the objects to the array in the Store class. The problem I'm facing is that I'm wanting to separate the parsing method in the SKU class so that it simply reads from a line, and then have a separate method which takes a file input for the parser and finally update my Store class so that it initialises the products with the parsed data. Please, can you help me in regards to this?
My parsing method in the SKU class is currently as follows:
public void parser() {
try {
// create a Buffered Reader object instance with a FileReader
BufferedReader br = new BufferedReader(new FileReader("products.txt"));
// read from first line from the text file
String fileRead = br.readLine();
// skip first line from sample file as it contains headings
int lineNumber = 0;
// loop until all lines are read
while (fileRead != null)
{
if(lineNumber == 0) {
lineNumber++;
continue;
}
lineNumber++;
// use string.split to load a string array with the values from each line of
// the file, using a tab as the delimiter
String[] tokenize = fileRead.split("\t");
// assume file is made correctly
// and make temporary variables for the three types of data
String tempProductCode = tokenize[0];
String tempDescription = tokenize[1];
BigDecimal tempPrice = new BigDecimal(tokenize[2]);
// create temporary instance of SKU object
// and load with three data values
SKU tempObj = new SKU();
tempObj.setProductCode(tempProductCode);
tempObj.setDescription(tempDescription);
tempObj.setPrice(tempPrice);
// add to array list
Store.mySkuArrayList.add(tempObj);
// read next line before looping
// if end of file reached
fileRead = br.readLine();
}
// close file stream
br.close();
}
// handle exceptions
catch (FileNotFoundException fnfe)
{
System.out.println("file not found");
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
My Store class is as follows:
public class Store {
public static ArrayList<SKU> mySkuArrayList = new ArrayList<SKU>();
public void addSKU(SKU sku) {
mySkuArrayList.add(sku);
}
Split your code to three separate classes. SkuFile class represents text file where sku codes is stored, this class knows how to every sku entry stored and able to parse it. Sku class contains data. Store class contains
list of Sku and accept SkuFile in it's constructor.
class SkuFile {
private String path;
SkuFile(String path) {
this.path = path;
}
List<Sku> readAllSku() {
ArrayList<Sku> result = new ArrayList<>();
try {
List<String> lines = Files.readAllLines(new File(path).toPath());
for(String skuLine : lines) {
result.add(parseFrom(skuLine));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return result;
}
private Sku parseFrom(String data){
String[] tokenize = data.split("\t");
productCode = tokenize[0];
description = tokenize[1];
price = new BigDecimal(tokenize[2]);
return new Sku(productCode, description, price);
}
}
class Sku {
private String code;
private String description;
private BigDecimal price;
Sku(String code, String description, BigDecimal price) {
this.code = code;
this.description = description;
this.price = price;
}
//getters setters methods
}
class Store {
private List<Sku> skus;
Store(SkuFile file) {
skus = file.readAllSku();
}
}
class Test {
public static void main(String[] args) {
Store store = new Store(new SkuFile("products.txt"));
}
}
One way to handle this is by making the parse method return a list of tokenizers(e.g. List tokenizeList) and a second method which takes that list as input and populates the SkuArrayList
Possible implementation of the parser method
public List<String[]> parser() {
List<String[]> tokenizeList = new ArrayList<>();
try {
... /*file opening logic*/
while (fileRead != null)
{
.../*line counting logic*/
String[] tokenize = fileRead.split("\t");
tokenizeList.add(tokenize);
fileRead = br.readLine();
}
// close file stream
br.close();
}// handle exceptions
catch (FileNotFoundException fnfe)
{
System.out.println("file not found");
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
return tokenizeList;
}
Possible implementation of the populate store method
public void populateStore(List<String[]> tokenizeList) {
for(String[] tokenize: tokenizeList) {
String tempProductCode = tokenize[0];
String tempDescription = tokenize[1];
BigDecimal tempPrice = new BigDecimal(tokenize[2]);
SKU tempObj = new SKU();
tempObj.setProductCode(tempProductCode);
tempObj.setDescription(tempDescription);
tempObj.setPrice(tempPrice);
// add to array list
Store.mySkuArrayList.add(tempObj);
}
}
And the main method from where you call these two methods
public void foo() {
populateStore(parser());
}

Java: Making .txt doc into String. Performing string methods [duplicate]

This question already has an answer here:
What does "Incompatible types: void cannot be converted to ..." mean?
(1 answer)
Closed 4 years ago.
import java.util.Scanner;
import java.io.File;
public class Book
{
private String bookString;
private String bookTitle;
private String bookAuthor;
public Book(String fileName, String title, String author)
{
readBook(fileName);
bookTitle = title;
bookAuthor = author;
}
public boolean containsTitle()
{
}
public int getNumOfCharacters()
{
}
public int countWords(String word)
{
}
public int countSentences()
{
}
public String randomWord(int length)
{
}
public int firstOccurrence(String word)
{
}
public String getSecondSentence()
{
}
public void readBook(String fileName)
{
bookString = "";
try
{
Scanner file = new Scanner(new File(fileName));
while (file.hasNextLine())
{
String line = file.nextLine();
bookString += line + "\n";
}
file.close();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
Here is some skeleton code that I am trying to finish. My first question is-- don't I have to store the readBook(fileName) in a variable? I tried to store it, then finish the getNumOfCharecters() method with:
bSL = bS.length()
return bSL
I am getting an error message. "incompatible types; void cannot be converted to java.lang.String"
Thanks to anyone willing to help.
The error you get should suggest you that the method is supposed to return a string. Change your method to :
public String readBook(String fileName)
{
bookString = "";
try
{
Scanner file = new Scanner(new File(fileName));
while (file.hasNextLine())
{
String line = file.nextLine();
bookString += line + "\n";
}
file.close();
}
catch (Exception e)
{
System.out.println(e);
}
return bookString;
}
then get the output into a variable like String bS = readBook( fileName );

Reading A File and Storing It In An Object

I am trying to read from a file and store the contents into an object called ToDoList(from what I assume is under the GetItem method). Then I am supposed to allow the user to add on to the list. But I am lost on how to create the object and print it.
public class ToDoList {
private ToDoItem[] items;
ToDoItem td = new ToDoItem();
String inputline;
Scanner keyboard = new Scanner(System.in);
int i = 0;
String[] stringArray = new String[100];
private void setItems(ToDoItem[] items) throws FileNotFoundException {
File file = new File("ToDoItems.txt");
Scanner ReadFile = new Scanner(file);
while (ReadFile.hasNext()) {
String ListString = ReadFile.nextLine();
stringArray[100] = (ListString);
}
}
private ToDoItem[] getItems() {
return items;
}
public void addItem(int id, String description) {
stringArray[100] = (td.getId() + td.getDescription());
}
public String[] getAddItem() throws FileNotFoundException {
try (PrintWriter fout = new PrintWriter(new File("ToDoItems.txt"))) {
do {
System.out.println("add to the list? [y/n]");
inputline = keyboard.nextLine();
if ("y".equals(inputline)) {
i++;
stringArray[i] = (td.getId() + ". " + td.getDescription() + "\n");
fout.print(stringArray[i]);
} else {
System.out.println("Here is the list so far:");
}
} while ("y".equals(inputline));
return stringArray;
}
}
#Override
public String toString() {
return "ToDoList{" + "items=" + getItems()
+ '}';
}
I am supposed to use the "getAddItem" method to allow the user to add to the list. But I can't figure out how to add an array to an object. let alone make the object.
A little code to expand on what pininfarina said and to help you get going.
You need a ToDoItem class. Something like this:
public class ToDoItem {
private String id;
private String description;
public ToDoItem(String id, String description) {
this.id = id;
this.description = description;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Then you need a ToDoList class to hold each item. You backed yours with an Array, but I used an ArrayList:
public class ToDoList {
private ArrayList<ToDoItem> items = new ArrayList<ToDoItem>();
public ToDoList(String fileName) throws FileNotFoundException {
File file = new File(fileName);
Scanner scanner = new Scanner(file);
try {
while (scanner.hasNext()) {
String nextLine = scanner.nextLine();
StringTokenizer tokenizer = new StringTokenizer(nextLine, ",");
String id = tokenizer.nextToken();
String description = tokenizer.nextToken();
items.add(new ToDoItem(id, description));
}
} finally {
scanner.close();
}
}
public void setItems(ArrayList<ToDoItem> newItems) {
this.items.addAll(newItems);
}
public List<ToDoItem> getItems() {
return items;
}
public void addItem(ToDoItem item) {
items.add(item);
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("ToDoList{");
for (ToDoItem item : items) {
builder.append(item.getId() + "," + item.getDescription() + "\n");
}
builder.append("}");
return builder.toString();
}
}
This includes a constructor that reads the file and parses out items. Each line in the file must be something like "1,something" because the tokenizer uses the comma. Note that the Scanner actually destroys the file as it reads it. You might consider using some sort of FileReader instead.
Finally you need a main class to run it. Something like this:
public class RunIt {
private static Scanner keyboard = new Scanner(System.in);
public static void main(String[] args) throws FileNotFoundException {
ToDoList list = new ToDoList("ToDoItems.txt");
try (PrintWriter fout = new PrintWriter(new File("ToDoItems.txt"))) {
String inputLine;
do {
System.out.println("add to the list? [y/n]");
inputLine = keyboard.nextLine();
if ("y".equals(inputLine)) {
System.out.println("enter a to-do using the format 'id,description'");
StringTokenizer tokenizer = new StringTokenizer(keyboard.nextLine(),
",");
String id = tokenizer.nextToken();
String description = tokenizer.nextToken();
list.addItem(new ToDoItem(id, description));
} else {
System.out.println("Here is the list so far:");
System.out.println(list);
}
} while ("y".equals(inputLine));
}
}
}
Please note that there is a lot of room for improvement here (exception handling, more robust file reading, etc), but this should get you started.
You are asking a broad question. Here's some design tips for you.
Create your collection class. This could be named ToDoList. Then create the attributes and behaviors of this class. One attribute will be the collection variable of your to do list items. You can use, List, ArrayList, etc. Behaviors could be add, remove, reorder, and etc.
Create your item class. Again with the attributes and behaviors. Attributes could include what to do, date, importance level, etc.
When you read your file, have your program to instantiate your ToDoItem class for every line, item etc. then save them into the previously created container class which is your ToDoList.
You can use your ToDoList class' addItem method (behavior) to have your users add more items into your ToDoList. If you want to keep the list even after your program closes. You can create a database to store your objects.
Good luck.

Categories