We have an assignment/project where we create a parking lot with several different objects then typically each week we add/improve on it. This week we were given a .txt file with lines that look like this "Bicycle%4%2%ABC40%false" or "Auto%22%7%ABC21%false". Each % is used as a delimiter denoting a separate attribute (speed, passenger capacity, serial number, and boolean lock status for bikes) for the respective object (car or bicycle).
We need to read through the file and create a new object in an array with that line using split. What I'm having trouble with is taking the number which is currently a string, parsing it as an int or boolean, then adding that to the new Bicycle (or Auto). Just can't seem to get the syntax right.
Also wondering if my "if" logic is right for if it says Bicycle to start creating a bicycle?
Update:
I think I have the parsing issue figured out, but now it's saying that it can't find my attributes for bicycle... saying "Cannot find symbol" So close!
Here's my code:
public class Driver
{
private static Object myBicycle;
private static Object myAuto;
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException
{
Scanner scan = new Scanner(new File("Vehicles.txt"));
ArrayList<Object> myVehicles = new ArrayList<Object>();
while (scan.hasNext())
{
String line = scan.nextLine();
String [] data = line.split("%");
if (data[0].equals("Bicycle"))
{
speed = (Integer.parseInt(data[1]));
PassCap = (Integer.parseInt(data[2]));
serialNumber = (Integer.parseInt(data[3]));
locked = (Boolean.parseBoolean(data[4]));
brand = Brand.randomBrand();
Bicycle myBicycle = new Bicycle(speed, PassCap, serialNumber, locked, brand);
myVehicles.add(myBicycle);
}
I'm not sure what your implementation is, but you could try something like this:
public static void main(String[] args) throws FileNotFoundException
{
Scanner scan = new Scanner(new File("/home/buddha/MYDRIVE/exploring/java/src/Vehicles.txt"));
ArrayList<String> myVehicles = new ArrayList<String>();
while(scan.hasNext()) {
String line = scan.nextLine();
String[] data = line.split("%");
if (data[0].toLowerCase().equals("bicycle")) {
System.out.println(Integer.parseInt(data[1]));
System.out.println(Integer.parseInt(data[2]));
System.out.println(data[3]);
System.out.println(Boolean.parseBoolean(data[4]));
}
else if (data[0].toLowerCase().equals("auto")) {
System.out.println(Integer.parseInt(data[1]));
System.out.println(Integer.parseInt(data[2]));
System.out.println(data[3]);
System.out.println(Boolean.parseBoolean(data[4]));
}
}
}
and just like the setter functions, you can create getter functions and check if the values have been correctly stored.
So, this line:
String [] data = line.split("%");
...takes strings like this:
"Bicycle%4%2%ABC40%false" or "Auto%22%7%ABC21%false"
and turns them into arrays of strings like this:
data[0] : `Bicycle` or `Auto`
data[1] : `4` or `22`
data[2] : `2` or `7`
data[3] : `ABC40` or `ABC21`
data[4] : `false` or `false`
So now you just need to parse those strings into their int and bool equivalents:
speed = Integer.parseInt(data[1]);
passCap = Integer.parseInt(data[2]);
serialNumber = data[3]; // This is a string, right?
locked = Boolean.parseBoolean(data[4]);
If serialNumber is a numeric, then you probably only want the numeric part at the end (e.g. "21" vs "ABC21"):
serialNumber = Integer.parseInt(data[3].Substring(3));
Related
I wonder is it possible to store the current scan.nextLine() after comparing it to a String variable without creating any new variable? Language: Java
Scanner scan = new Scanner(System.in);
String words = "something";
if(!scan.nextLine().equalsIgnoreCase(words)) {
// replace words with `scan.nextLine();
}
No, you would need to write a new class, and Scanner is final = non-extendable.
It would be not a large effort though. Maybe you can use a BufferedReader instead.
Otherwise use an expression inside which one assigns to a single variable declared in front. The same pattern one sees with BufferedReader.
String line = "";
Scanner scan = new Scanner(System.in);
String words = "something";
if (!(line = scan.nextLine()).equalsIgnoreCase(words)) {
// replace words with `scan.nextLine();
... line ...
}
Not necessarily good taste.
Initially, another variable won't be made but when you access the method it will make a variable and store it but it will go on in the background, you won't have to make a new variable in your main class. Variable made in class don't occupy memory till an object is made out of it.
public class testing {
Scanner sc = new Scanner(System.in);
String str = "something";
String hello(String which_you_want_to_store) {
which_you_want_to_store = sc.nextLine();
if (!which_you_want_to_store.equalsIgnoreCase(this.str)) {
this.str = which_you_want_to_store;
}
return which_you_want_to_store;
}
public static void main(String[] args) {
testing obj = new testing();
obj.hello(null);
System.out.println(obj.str);
}
}
basically I'm trying to store data from a text file and perform some tasks with that data. So far I've parsed the data into different types (component, stock num, stock, and price), loaded the data into an object and put the object into an array list. I have a problem though as some of the rows in the txt file only have four data types while everything else has 5.
Therefore, I can only parse it to four data types instead of 5 because I get an ArrayIndexOutOfBounds Exception because diode doesn't have anything at index[4]. I know that I should use the length of the array but I'm not sure how. Also, how would I add together everything in a data type such as stock and get the total stock for all the components? Thanks.
try
{
List<Inventory> invItem = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader("inventory.txt"));
String fileRead = br.readLine();
while (fileRead != null)
{
String[] tokenize = fileRead.split(",");
String tempItem = tokenize[0];
String tempNumber = tokenize[1];
double tempStock = Double.parseDouble(tokenize[2]);
double tempPrice = Double.parseDouble(tokenize[3]);
double tempResist = Double.parseDouble(tokenize[4]);
Inventory tempObj = new Inventory(tempItem, tempNumber, tempPrice, tempStock, tempResist);
invItem.add(tempObj);
fileRead = br.readLine();
}
I'm only using some pseudo code here, because you haven't showed us what you have tried so far, to try to explain what you need to do:
for each line in CSV-file {
split line by ',' and store in array
check first item in array =>
if array[0].equals("diode") => create diode object from array of size 4
if array[0].equals("capacitor") => create capacitor object from array of size 5
...
store created object in a List<>
}
Both the diode class and the capacitor class extends a class that is used for the type of List<>
Now that your question has been updated with some code, I will give an example with real code. This example uses only an Inventory class, no Diode or Capacitor classes.
public class Inventory {
private String item;
private String number;
private double price;
private double stock;
private double resist;
public Inventory(String[] csvLine) {
if (csvLine.length > 0) item = csvLine[0];
if (csvLine.length > 1) number = csvLine[1];
if (csvLine.length > 2) stock = Double.parseDouble(csvLine[2]);
if (csvLine.length > 3) price = Double.parseDouble(csvLine[3]);
if (csvLine.length > 4) resist = Double.parseDouble(csvLine[4]);
}
// getters and setters
}
And some code using this class:
public static void main(String[] args) {
List<Inventory> invItem = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader("inventory.txt"));
String fileRead;
while ((fileRead = br.readLine()) != null) {
invItem.add(new Inventory(fileRead.split(",")));
}
br.close();
double totalStock = 0;
for (Inventory inv : invItem) {
totalStock += inv.getStock();
}
System.out.println(totalStock); // prints the total stock
}
A simple solution to avoid ArrayIndexOutOfBounds is... to check the length before attempting to read values. This code can help:
double tempResist = tokenize.length <= 4 ? 0 :
Double.parseDouble(tokenize[4]);
However, it is even better to ensure that all resistors have length 5; otherwise you would receive no warning when invalid resistors (missing a resistance value) are read:
double tempResist = "resistor".equals(tempItem) ? 0 :
Double.parseDouble(tokenize[4]);
And, even better, you would have separate Resistor and Capacitor subclasses of Item, and have an ItemParser class with a static Item parse(String[] tokens) method that parses the common bits, and creates an object of the correct subclass, passing the remaining tokens to its constructor. In their constructors, resistors would complain if they are missing values, while capacitors would complain if they get passed excess, unexpected values. This would also complain if a "chicken" is read, because there would be no subclass to parse its values.
Edit: it is better to have an ItemParser as a separate class than to place that functionality in the Item class directly, because this allows you to add new types if Item without touching the base Item base class.
Hey everybody i'm new to java and I'm doing a bonus assignment for my intro to java class and i was wondering if some one could help guide me for the bonus questions: i just need a starting point! Thanks for any help!
This is the original Requirements for the assignment :
1) A constructor that accepts a single argument, a String for the name of the input file to process. DONE
2) A function named processFile(), that accepts no arguments, and throws an IOException. This function must read the input file's contents and count the number of times each token (word) exists in the file. A member variable HashMap is a good class to use for this.
3) A getFileName() function, no arguments, returns a String that contains the input file name.
4) A getTokenCount() function, no arguments, returns an int that is the total number of tokens (words) in the input file.
5) A getTokenCount() function, that accepts a String argument, and returns the number of times that token (word) appears in the input file.
6) A getTokensHavingCount() function that accepts an int argument (the count), and returns an ArrayList of Strings, where those Strings are the tokens that appear exactly "count" times in the input file.
7) A getTokensHavingLength() function that accepts an int argument (the length), and returns an ArrayListof Strings, where those Strings are the tokens in theinput file that have that exact length.
8) A getAverageOfCounts() function, no arguments, returns the average of the token counts.
As this is the code i have so far,
import java.io.*;
public class Assignment4 {
// Your member variables go here
private String filename;
private int wordcount; // ?
private Map<String, Integer> freq = new HashMap<>(); // <Key,Value>
public Assignment4(final String fileName) {
this.filename = fileName;
}
public void processFile() throws IOException {
File file = new File(filename);
BufferedReader reader;
try {
FileReader fileReader = new FileReader(file);
reader = new BufferedReader(fileReader);
file = null;
String text = "";
String line = reader.readLine();
while (line != null) {
text = text + line + " ";
line = reader.readLine();
}
StringTokenizer st = new StringTokenizer(text);
wordcount = st.countTokens();
}
}
public String getFileName() {
return filename;
}
public int getTokenCount() {
return freq.size;
}
public int getTokenCount(final String key) {
return freq.get(key);
}
public ArrayList<String> getTokensHavingCount(final int count) {
ArrayList<String> wordCount = new ArrayList<String>();
Set<String> set = freq.keySet();
for (String word : set) {
int noOfTimes = freq.get(word);
if (noOfTimes == count)
freq.add(word);
}
return wordCount;
}
public ArrayList<String> getTokensHavingLength(final int length) {
ArrayList<String> wordlength = new ArrayList<String>();
Set<String> set = freq.keySet();
for (String word : set) {
if (word.length() == length)
wordlength.add(word);
}
return wordlength;
}
public int getCountOfTokensHavingCount(final int count) {
return getTokensHavingCount(count).size();
}
public int getCountOfTokensHavingLength(final int length) {
return getTokenHavingLength(count).size;
}
public double getAverageOfCounts() {
ArrayList<String> wordlength = new ArrayList<String>();
double sum = 0.0d;
Set<String> set = freq.keySet();
for (String word : set) {
sum += freq.get(word);
}
return sum / (double) freq.size();
}
}
Bonus #1: Add a function named getCountOfTokensHavingCount(), that accepts an int argument (count), and returns the number of tokens which appear in the input file exactly "count" times.
Bonus #2: Add a function named getCountOfTokensHavingLength(), that accepts an int argument (length), and returns the number of tokens which appear in the input file having exactly "length" characters in the token.
Ok, a few things.
Your function processFile doesn't do what it should do. Your task is to count how often each word appears in the text. Idea: Read the file word by word (take a look at java.util.Scanner); if the word isn't already in your HashMap you add the word as the Key and the number 1 as the value; if the word is already in your HashMap you increase the value by one.
Why do you set file = null in processFile? You should properly close the BufferedReader instead by using a finally. Java can actually do that for you automatically: try(FileReader freader = new FileReader(file); BufferedReader breader = new BufferedReader(freader)) { // Your actual code }.
Your getTokenCount function should return freq.size() (you call a function, not an attribute!).
Also please use always curly braces after an if or a loop, regardless of there is only one thing you do or a huge code block.
I have a set of data that look like this.
1:2:3:4:5
6:7:8:9:10
I have manage to use array list to store the information using a delimiter of ":".
However i would like to store the information of their line numbers together in the array list.
class test
{
String items;
String linenumber;
}
Example:
test(1,1)
test(2,1)
test(6,2)
test(7,2)
Here is my current code.
Scanner fileScanner = new Scanner(new File(fname));
fileScanner.useDelimiter("\n");
int counter = 0; String scounter;
String test;
String events;
while(fileScanner.hasNext())
{
events = fileScanner.next();
scounter = Integer.toString(counter);
Base obj = new Base(scounter, events);
baseArrayList.add(obj);
}
fileScanner.close();
I have try using delimiter "\n" and then trying to split out the string and it is not very successful.
Any advice would be appreciated.
public void Base_Seperator()
{
String temp, temp2;
String[] split;
String days, events;
for(int i = 0; i < baseArrayList.size(); i++)
{
temp = baseArrayList.get(i).events;
temp2 = baseArrayList.get(i).days;
split = temp.split(":");
}
}
Despite the code in #Alex's answer that may solve your problem, your attempt is almost close to get what you want/need. Now you only need to create Test instances and store them in a container, usually a List. I'll add the necessary code to start this from your code:
//it is better to return the List instead of declaring it as a static field
public List<Test> Base_Seperator() {
//try to declare variables in the narrower scope
//String temp, temp2;
//String[] split;
//String days, events;
//this variable must be recognized in all the paths of this method
List<Test> testList = new ArrayList<Test>();
for(int i = 0; i < baseArrayList.size(); i++) {
//these variables should only work within the for statement
String temp = baseArrayList.get(i).events;
String temp2 = baseArrayList.get(i).days;
String[] split = temp.split(":");
//you have splitted the String by :
//now you have every element between : as an item stored in split array
//go through each one and create a new Test instance
//first, let's create the lineNumber variable as String
String lineNumber = Integer.toString(i+1);
//using enhanced for to go through these elements
for (String value : split) {
//now, let's create Test instance
Test test = new Test(value, lineNumber);
//store the instance in testList
testList.add(test);
}
}
//now just return the list with the desired values
return testList;
}
Not part of your question, but some advices:
There are plenty other ways to write code to achieve the same solution (take #Alex's answer as an example). I didn't posted any of them because looks like you're in learning phase, so it will be better for you to first achieve what you're looking for with your own effort (and a little of help).
Not sure if you're doing it (or not) but you should not use raw types. This is, you should always provide a generic type when the class/interface needs it. For example, it is better to define a variable as ArrayList<MyClass> myClassList rather than ArrayList myClass so the class become parameterized and the compiler can help you to avoid problems at runtime.
It is better to always program oriented to interfaces/abstract classes. This means, it is better to declare the variables as an interface or abstract class rather than the specific class implementation. This is the case for ArrayList and List:
List<String> stringList = new ArrayList<String>();
//above is better than
ArrayList<String> stringList2 = new ArrayList<String>();
In case you need to use a different implementation of the interface/abstract class, you will have to change the object initialization only (hopefully).
More info:
What is a raw type and why shouldn't we use it?
What does it mean to "program to an interface"?
Looks like you want to store days instead of lineNumber in your Test instances:
//comment this line
//Test test = new Test(value, lineNumber);
//use this one instead
Test test = new Test(value, days);
First of all you don't need to keep line number info in the test object because it can be inferred from the ArrayList that holds them. If you must though, it should be changed to an int. So,
class test
{
ArrayList items<Integer>;
int linenumber;
public test(int line, String[] input){
items=new ArrayList();
linenumber=line;
//populate with the line read by the Scanner
for(int i=0; i<input.lenth; i++)
items.add(Integer.parseInt(input[i]));
}
}
I use an ArrayList inside test because you don't know how many elements you'll be handling. Moving on to the scanner
Scanner fileScanner = new Scanner(new File(fname));
// fileScanner.useDelimiter("\n"); You don't need this!
String tmp[];
int line=0; //number of lines
while(fileScanner.hasNext()) {
line++;
//this returns the entire line, that's why you don't need useDelimeter()
//it also splits it on '.' I'm not sure if that needs to be escaped but
//just to be sure
tmp=fileScanner.nextLine() . split(Pattern.quote("."));
baseArrayList.add(new test(line, tmp));
}
fileScanner.close();
Here I use test to store the objects you read, I'm not sure what Base is supposed to be.
A Java Bean/construct is required that will hold the day and the item together. The following code will read the text file. Each line will be converted to a List where finally the application will populate the List DayItems collection properly.
public class DayItem {
private int day;
private String item;
public int getDay() {
return day;
}
public void setDay(final int day) {
this.day = day;
}
public String getItem() {
return item;
}
public void setItem(final String item) {
this.item = item;
}
}
And main code
public class ReadFile {
private static final List<DayItem> dayItems = new ArrayList<DayItem>();
public static void main(String args[]) throws FileNotFoundException{
final BufferedReader bufferReader = new BufferedReader(new FileReader("items.txt"));
int lineNumber=0;
try
{
String currentLine;
while ((currentLine = bufferReader.readLine()) != null) {
lineNumber++;
List<String> todaysItems = Arrays.asList(currentLine.split(":"));
addItems(todaysItems,lineNumber);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void addItems(final List<String> todaysItems,final int day){
int listSize = todaysItems.size();
for(int i=0;i<listSize;i++){
String item = todaysItems.get(i);
DayItem dayItem = new DayItem();
dayItem.setDay(day);
dayItem.setItem(item);
dayItems.add(dayItem);
}
}
}
public class Pig {
private int pigss;
private Pig[] pigs;
public Pig[] pigNumber (int pigss)
{
pigs = new Pig [pigss];
return pigs;
}
Code that includes main method:
public class animals{
public static void main(String[] args){
Pig cool = new Pig();
Scanner keyboard = new Scanner (System.in);
System.out.println("How many pigs are there?");
int pigss = Integer.parseInt( keyboard.nextLine() );
cool.pigNumber(pigss);
//This is where I have trouble. I want to use the array pigs here in the main method, this is what i tried:
Pig[] pigs = cool.pigNumber(pigss);
I then tried to use a for loop and assign values (String) to the index of arrays (pigs[]). But the error that gives me is: cannot convert from String to Pig. Any tips are appreciated. THank you.
for(int j = 0; j < pigs.length; j++)
{
System.out.println("What is the pig " + (j+1) + "'s name");
pigs[j] = keyboard.nextLine();
}
Your pigs will need an attribute to contain the string values you are trying to pass:
public class Pig {
private String name;
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
Then when you want to assign this string value to your pig:
int indexOfPig = 0; // Or whatever it is supposed to be
pigs[indexOfPig].setName("I am a string");
In java you can only use ints as the indexes of arrays
It is saying 'cannot convert from String to Pig' because you can't do that!
If you want somehow convert a String to a Pig, you are going to need to write some code to do the conversion. For example, you might write a constructor that creates a new Pig from some kind of description. Or you might write a method that looks up a Pig by name or number or something.
It is hard to offer any more concrete advice because you don't tell us what is in the string values ... or how you expect the strings to become pigs. (The only suggestion I have is to try Macrame :-) )
Pig doesn't have a name member or even method that accepts a string. Also you are trying to assign a String(keyboard.nextline() to a Pig(pigs[j].
Add an attribute name to your pig.
class Pig{
public String name:
public void Pig(String name){
this.name = name;
}
}
Then assign a new instance of Pig in the loop.
pigs[j] = new Pig(keyboard.nextLine());
Also get rid of the useless class pigNumber. All you need is an ArrayList of Pigs. The array list can be dynanically sized.
List<Pig> pigs = new ArrayList<Pig>
so your loop could be something like
String name = ""
while(true){
name = keyboard.readline();
if(name== "stop"){
break;
}
pigs.add(new Pig(names);
}
Then getting the number of pigs is a simple
System.out.println(pigs.length());