I have a CarModel class that has three fields: name, fuelEconomy, and gasTankSize.
class CarModel {
private String name;
private double fuelEconomy;
private double gasTankSize;
CarModel(String name, double fuelEconomy, double gasTankSize) {
this.name = name;
this.fuelEconomy = fuelEconomy;
this.gasTankSize = gasTankSize;
}
String getName() {
return name;
}
double getFuelEconomy() {
return fuelEconomy;
}
double getGasTankSize() {
return gasTankSize;
}
}
Given the input as a string of text separated by a new line:
MODEL Camry 6.5 58
MODEL Civic 7.5 52
FINISH
How can I create a new object every time the word MODEL is in the input, store the model in an array, use the following words as the data for those fields and end the program when FINISH is in the input?
Inside main method, try doing something like this (Using try with resources):
public static void main(String args[]){
String line;
List<CarModel> cars = new ArrayList<>();
try(Scanner sc = new Scanner(System.in)){
while(sc.hasNextLine()){
line = sc.nextLine();
String[] arr = line.split(" ");
if(arr[0].equalsIgnoreCase("Model")){
cars.add(new CarModel(arr[0], Double.parseDouble(arr[1]), Double.parseDouble(arr[2])));
}else if(arr[0].equalsIgnoreCase("Finish"){
break;
}
}
}catch(ArrayIndexOutOfBoundsException ex){
// do something here!
}catch(Exception ex){
// do something here as well!
}
}
I would use the String.split method. You pass a delimiter, in your case a space character, and then the method chops the string into pieces based on your provided delimeter. Getting the input into your program depends on where the input will be coming from, whether by file or terminal or some other source.
Once you've read a line of input, call String[] values = line.split(" ")
Again, how to read the input depends on where the input is coming from, which you haven't specified.
Related
I have been tasked with creating a game called Taboo. It consists of a main word and 3 banned words. The aim of the game is for the words to display on the screen and the user then has to describe the main word without using the word itself or the banned words.
I have so far been able to read in the data that I have stored in a CSV and have it so that when I choose to output BannedWords, it does so. The problem now, is that when it outputs either MainWord or BannedWord1, etc... it outputs the data for each record in the CSV.
Below is the data from my CSV (it is just a test with few records so that when it works I can introduce the rest).
Tree,Brown,Green,Nature
Lake,Blue,Water,Wet
Apple,Green,Fruit,Healthy
If I chose to output MainWord, which is the first word, it outputs like this:
Tree
Lake
Apple
I need to somehow store the data being read in from the CSV individually in a collection so that when I need to use them, they output properly and they in a such a way that I can display them later on in a GUI JLabel.
It might also be useful to note that I am using NetBeans so I am able to use any of the built in functions as well.
public class Card
{
private String sMainWord;
private String sBannedWord1;
private String sBannedWord2;
private String sBannedWord3;
public Card(String sMW, String sBW1, String sBW2,String sBW3)
{
sMainWord = sMW;
sBannedWord1 = sBW1;
sBannedWord2 = sBW2;
sBannedWord3 = sBW3;
}
public void setsMainWord(String sMW)
{
sMainWord = sMW;
}
public String getsMainWord()
{
return sMainWord;
}
public void setsBannedWord1(String sBW1)
{
sBannedWord1 = sBW1;
}
public String getsBannedWord1()
{
return sBannedWord1;
}
public void setsBannedWord2(String sBW2)
{
sBannedWord2 = sBW2;
}
public String getsBannedWord2()
{
return sBannedWord2;
}
public void setsBannedWord3(String sBW3)
{
sBannedWord3 = sBW3;
}
public String getsBannedWord3()
{
return sBannedWord3;
}
public static void main(String[] args) throws FileNotFoundException
{
String fileNameDefined = "/Users/student/NetBeansProjects/TabooGameComplete/CSData.csv";
File file = new File(fileNameDefined);
try
{
Scanner inputStream = new Scanner(file);
while(inputStream.hasNext() != false)
{
String TabooCardWords = inputStream.nextLine();
String[] information = TabooCardWords.split(",");
String MainWord = information[0];
String BannedWord1 = information[1];
String BannedWord2 = information[2];
String BannedWord3 = information[3];
Card TBC = new Card (MainWord, BannedWord1, BannedWord2, BannedWord3);
System.out.println("*" + BannedWord1 + "*");
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
You are executing the output statement in the loop that generates your Cards so that everytime a card is created, you are outputting its BannedWord1. As you are creating them all, one after another, they will all output, one after another.
i.e.
//For each line in file
while(inputStream.hasNext() != false)
{
//Create Card
//Output BannedWord1 used to create Card
}
If you want to output one element of one Card, you will need to keep the Card objects you create to be used outside the loop:-
Card[] cards = new Cards[3];
int i=0;
//For each line in file
while(inputStream.hasNext() != false)
{
//Create Card
cards[i++] = newlyCreatedCardObject; //Store card object for later
//Output BannedWord1 used to create Card
}
//Output BannedWord1 from the Card created from the second line
System.out.println(cards[1].getsBannedWord1());
Additional Point
By convention, java variables begin with lowercase letters and classes with uppercase, so this can be confusing
String TabooCardWords; //Should really be 'tabooCardWords'
...
String MainWord = information[0]; //-> 'mainWord'
String BannedWord1 = information[1]; //-> 'bannedWord1'
String BannedWord2 = information[2]; //-> 'bannedWord2'
String BannedWord3 = information[3]; //-> 'bannedWord3'
I'm a beginner to programming and I need some help trying to read from a text file into an ArrayList that contains objects of different types. I've created a program that controls an inventory of videos which I currently have hard coded into an ArrayList in the program but I would like to change this so every time the program runs, the program reads from the text file which contains the inventory and converts that into an ArrayList instead of reading from the ArrayList that is already in the program. I've already added a function that writes the inventory to the text file once the program has quit but I can't seem to get it to read from the text file.
The problem I'm having is that my ArrayList (videos) contains (String, String, Character, String). I don't know how to change the code I have so that scanner splits each line in the text file into the appropriate chunks (for title, type, availability and return date) and then inserts each individual chunk into the appropriate place in the ArrayList. I hope that made sense.
I've tried creating a CSV and using the split() function but I couldn't figure out how to use that to insert into an ArrayList as I end up with four strings in a line rather than (String, String, Character, String). I've even tried changing my current ArrayList so that every element is a string but I still wasn't sure how to make that work.
Any help would be really appreciated. Let me know if you need further information.
EDIT: To sum up, my question is: if I have a text file as seen below, how do I split that into 4 lines and then each line into 4 strings (or 3 strings and 1 character) and insert each string into an ArrayList so that I end up with an ArrayList of four InventoryRow's like this:
("Casablanca", "Old", 'Y', null)
Inventory Row Class:
class InventoryRow {
private String name;
private String type;
private Character availability;
private String returndate;
public InventoryRow(String name, String type, Character availability,
String returndate) {
this.name = name;
this.type = type;
this.availability = availability;
this.returndate = returndate;
}
public String getReturndate() {
return returndate;
}
public void setReturndate(String returndate) {
this.returndate = returndate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Character getAvailability() {
return availability;
}
public void setAvailability(Character availability) {
this.availability = availability;
}
public String toString() {
return name + " " + type + " " + availability + " " + returndate;
}
}
Main method (including my current code which doesn't work):
public class InventorySort {
public static void main(String[] args) throws ParseException, JSONException, FileNotFoundException {
/*
* List<InventoryRow> videos = new ArrayList<InventoryRow>();
*
* videos.add(new InventoryRow("Casablanca", "Old", 'Y', null));
* videos.add(new InventoryRow("Jurassic Park", "Regular", 'N',
* "31/07/2015")); videos.add(new InventoryRow("2012", "Regular", 'Y',
* null)); videos.add(new InventoryRow("Ant-Man", "New", 'Y', null));
*/
// Get's today's date and adds three to it = return date
Calendar cal = Calendar.getInstance();
SimpleDateFormat dateReturn = new SimpleDateFormat("dd/MM/yyyy", Locale.UK);
cal.add(Calendar.DATE, 3);
Scanner input = new Scanner(System.in);
boolean run = true;
while (run) {
// Read from text file
Scanner s = new Scanner(new File("videos.txt"));
List<InventoryRow> videos = new ArrayList<InventoryRow>();
while (s.hasNext()) {
videos.add(new InventoryRow(s.next(), null, null, null));
}
s.close();
// Output the prompt
System.out.println("Do you want to list, rent, check, return, add, delete or quit?");
// Wait for the user to enter a line of text
String line = input.nextLine();
// List, rent and check functions
// List function
if (line.equals("list")) {
// Sort videos alphabetically
list(videos);
// Rent function
} else if (line.equals("rent")) {
rent(videos, cal, dateReturn, input);
// Check function
} else if (line.equals("check")) {
check(videos, input);
// If anything else is entered
} else if (line.equals("return")) {
returnVideo(videos, input);
} else if (line.equals("add")) {
add(videos, input);
} else if (line.equals("delete")) {
delete(videos, input);
} else if (line.equals("quit")) {
run = false;
writeFile(videos);
} else {
other();
}
}
}
The code I have for writing to the text file:
private static void writeFile(List<InventoryRow> videos) {
String fileName = "videos.txt";
try {
FileWriter fileWriter = new FileWriter(fileName);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
for (InventoryRow ir : videos) {
bufferedWriter.write(ir.toString() + System.getProperty("line.separator"));
}
bufferedWriter.close();
} catch (IOException ex) {
System.out.println("Error writing to file '" + fileName + "'");
}
}
My text file looks like this:
2012 Regular Y null
Ant-Man New Y null
Casablanca Old Y null
Jurassic Park Regular N 31/07/2015
You probably need something like this:
List<InventoryRow> videos = new ArrayList<InventoryRow>();
while (s.hasNextLine()) {
String[] split = s.nextLine().split(" ");
// TODO: make sure the split has correct format
// x.charAt(0) returns the first char of the string "x"
videos.add(new InventoryRow(split[0], split[1], split[2].charAt(0), split[3]));
}
It looks like you are trying to do basic serialization & deserialization.
I will focus on your while(run) loop so that you are able to populate the ArrayList from the file. Your InventoryRow class is good enough and the array list is correctly parameterized.
//This creates an object to read the file
Scanner s = new Scanner(new File("videos.txt"));
while (s.hasNext()) {
//This is where the problem is:
videos.add(new InventoryRow(s.next(), null, null, null));
}
s.next() will return a String like:
"name;type;a;date" you need to split this on your separator character by doing something like:
String line = s.next();
String[] fields = line.split(","); //use your choice of separator here & check how to use the split method.
Create a InventoryRow object with the obtained fields and then add that to the ArrayList in your while loop. Unless you specifically want the availability to be a character you could leave it as a string.
Here is the code I'm using
import java.util.Scanner;
import java.io.*;
import java.util.ArrayList;
public class Message{
Scanner input;
String emailLine = "";
String line;
ArrayList<String> email = new ArrayList<String>();
String emailString;
String sender;
String subject;
String emailMIN;
String[] newString;
StringBuilder emailStringBuilder = new StringBuilder();
public Message(String m)throws IOException{
File inFile = new File ("mail.txt");
input = new Scanner (inFile);
String message;
getEmails();
}
public void getEmails(){
while(input.hasNextLine()){
line = input.nextLine();
System.out.println("Test, line: " + line);
if(line.equals("<END>")){
System.out.println("Test, <END> reached");
System.out.println("Test, email String: " +
emailStringBuilder.toString());
email.add(emailStringBuilder.toString());
}
else{
emailStringBuilder.append("\n" + line);
}
}
}
I'm trying to pass the email ArrayList into a different class so that I can break up the Strings of the ArrayList into separate Arrays. How do I do this? Also once I get it into a different class, how do I access each element of the ArrayList and break each element up into another ArrayList with each element separated by the lines?
Use message.getEmails() to get your emails.
Below is a sample code
public class Message{
Scanner input;
String emailLine = "";
String line;
List<String> emails = new ArrayList<String>();
String emailString;
String sender;
String subject;
String emailMIN;
String[] newString;
StringBuilder emailStringBuilder = new StringBuilder();
public Message(String m)throws IOException{
File inFile = new File ("mail.txt");
input = new Scanner (inFile);
String message;
populateEmails();
}
public void populateEmails(){
while(input.hasNextLine()){
line = input.nextLine();
System.out.println("Test, line: " + line);
if(line.equals("<END>")){
System.out.println("Test, <END> reached");
System.out.println("Test, email String: " +
emailStringBuilder.toString());
emails.add(emailStringBuilder.toString());
}
else{
emailStringBuilder.append("\n" + line);
}
}
}
public List<String> getEmails() {
return emails;
}
}
Well first of all an ArrayList is not a List of arrays. It's simply a List of items, in your case String.
If you want to pass an ArrayList to a different class you could simply do something like this:
public class MyOtherClass {
public void doSomething(ArrayList<String> myList) {
// do something with "myList"
}
And then in your Message class:
MyOtherClass myClass = new MyOtherClass();
myClass.doSomething(email);
Is this helping?
NOTE
From your editing of the question I think you don't fully understand how ArrayList works. It is not a List of Array! It is simply an array implementation of the List interface for better performance in certain tasks. For more information read the javadocs about ArrayList
EDIT
As peeskillet was suggesting, you could also instantiate a Message class object in your new class and get the ArrayList from there, but then email would have to be a public field in your class Message or declare a getter method for email.
EDIT
Since you added more questions:
You can go through all the elements of an ArrayList like this:
For (String nextString : email) {
System.out.println(nextString); // Or do whatever you want with it :)
}
I have several classes designed to simulation a book catalog. I have a book class (isbn, title, etc...), a BookNode class, a BookCatalog which is a LinkedList of books and a driver class (gui).
My problem is that I have a toString() method in BookCatalog that supposed to return a String representation of all the books. The Book class also overrides toString(). I'm supposed to have each field of the book separated by a "tab" and each book separated by a "new line". When I try to use PrintStream to print the book catalog to a .txt file, the \n doesn't register.
I've tried to change it to System.getProperty(line.separator) which displays the bookcatalog correctly. But now, I have a problem where the Scanner will not read the file correctly and throws a "NoSuchElementException". How do I get the scanner to 1) Ignore the line.separator or 2) have printStream use \n?
Book.java
public String toString(){
return isbn+"\t"+lastName+"\t"+firstName+"\t"+title+"\t"+year+"\t"+
String.format("%.2f",price);
BookCatalog.java
public String toString() {
BookNode current = front;
String s="";
System.out.println(s);
while (current!=null){
//each book is listed on separate line
s+=current.getData().toString()+"\n ";//System.getProperty("line.separator")
current = current.getNext();
}
return s;
}
Driver.java
public void loadDirectory() throws FileNotFoundException {
if (f.exists()){
Scanner input = new Scanner(f);
while (input.hasNextLine()){
String bookLine = input.nextLine();
processBookLine(bookLine);
}
}
}
public void processBookLine(String line){
Scanner input = new Scanner(line);
String isbn = input.next();
String lastName = input.next();
String firstName = input.next();
String title = input.next();
while (input.hasNext() && !input.hasNextInt()){//while next token is not an integer
title += " "+input.next();
}
int year = input.nextInt();
double price = input.nextDouble();
Book book = Book.createBook(isbn, lastName, firstName, title, year, price);
if (book!=null){
catalog.add(book);
}
}
The linefeed character \n is not the line separator in certain operating systems (such as windows, where it's "\r\n") - my suggestion is that you use \r\n instead, then it'll both see the line-break with only \n and \r\n, I've never had any problems using it.
Also, you should look into using a StringBuilder instead of concatenating the String in the while-loop at BookCatalog.toString(), it is a lot more effective. For instance:
public String toString() {
BookNode current = front;
StringBuilder sb = new StringBuilder();
while (current!=null){
sb.append(current.getData().toString()+"\r\n ");
current = current.getNext();
}
return sb.toString();
}
I'm working on a project which reads from csv file, then uses StringTokenizer to chop up the elements and place them into JLabels. So far I have that part down. I have buttons to scroll through each position, but I'm not sure about how I can type in the fields and add on to the array ?
This is the main part of my program so far
// program reads in csvfile.
private void loadCarList() {
try{
BufferedReader CSVFile = new BufferedReader(new FileReader("car.txt"));
String dataRow = CSVFile.readLine();
while(dataRow != null){
carList.add(dataRow);
dataRow = CSVFile.readLine();
}
}catch(Exception e){
System.out.println("Exception while reading csv file: " + e);
}
}
}
//this will click cycle through the elements in the Jlabels.
private void loadNextElement(){
try {
StringTokenizer st = new StringTokenizer((String)carList.get(position), ",");
while(st.hasMoreTokens() && position <= carList.size() -1) {
position ++;
String CarID = st.nextToken();
String DealerShipID = st.nextToken();
String ColorID = st.nextToken();
String Year = st.nextToken();
String Price = st.nextToken();
String Quantity = st.nextToken();
tCarID.setText(CarID);
tDealerShip.setText(DealerShipID);
tColor.setText(ColorID);
tYear.setText(Year);
tPrice.setText(Price);
tQuantity.setText(Quantity);
}
} catch(Exception e){
JOptionPane.showMessageDialog(null, "youve reached the end of the list");
}
}
Is there a simpler way where I can just type in the jlabels I have laid out and add onto the array?
I'm kind of lost at this point, and am unsure how to go further with this.
Your problem appears to be that you're trying to do too much inside one class. It's possible to do, but not very well organized.
Create a separate class for holding a single Car record. It should be simple "bean" or "POJO" class typically composed of some private properties and public getters and setters (aka accessors and mutators). Your List of Cars will be composed of these objects.
public class Car {
private String carID;
...
private Integer quantity;
public getCarID() {
return this.carID;
}
...
public setQuantity(Integer quantity) {
this.quantity=quantity;
}
}
Define your list of Cars as a property of your current class, and each time you add a Car to your list, construct it from your Car class.
Car car=new Car();
car.setCarID(st.nextToken());
...
car.setQuantity(Integer.valueOf(st.nextToken()));
this.carList.add(car);