使用从文本文件创建的对象为库存报告编写Java程序

时间:2014-09-19 14:28:08

标签: java arraylist inventory

我有一个学校的项目,我无法正确编译。

可以在this链接找到相关说明。

我相信我在 Product.java 中正确创建了类。我的代码如下:

import java.util.*;

public class Product {

// Private member variables go here - you will need to add them yourself.
private String name;
private String code;
private int quantity;
private double price;
private String type;
private ArrayList<Integer> userRatings;


/*
 * Product constructor
 */
public Product() {
    name = "";
    code = "";
    quantity = 0;
    price = 0;
    type = "";
    userRatings = new ArrayList<Integer>();
}

/*
 * setName
 *  @param name - new name for the product
 */
public void setName(String name) {
    this.name = name;
}

/*
 * getName
 *  @return the name of the product
 */
public String getName() {
    return name;
}

/*
 * setType
 *  @param type - the type of the product
 */
public void setType(String type) {
    this.type = type;
}

/*
 * getType
 * @return - the product type
 */
public String getType() {
    return type;
}

/*
 * setPrice
 * @param price - the price of the product
 */
public void setPrice(double price) {
    this.price = price;
}

/*
 * getPrice
 * @return the price of the product
 */
public double getPrice() {
    return price;
}

/*
 * setQuantity
 * @param quantity - the number of this product in inventory
 */
public void setQuantity(int quantity) {
    this.quantity = quantity;
}

/*
 * getQuantity
 * @return the number of this product in inventory
 */
public int getQuantity() {
    return quantity;
}

/*
 * setInventoryCode
 * @param code - the new inventory code for the product
 */
public void setInventoryCode(String code) {
    this.code = code;
}

/*
 * getInventoryCode
 * @return the inventory code of the product
 */
public String getInventoryCode() {
    return code;
}

/*
 * addUserRating
 * NOTE: Each individual rating is stored with the product, so you need to maintain a list
 * of user ratings.  This method should append a new rating to the end of that list
 * @param rating - the new rating to add to this product
 */
public void addUserRating(int rating) {
    userRatings.add(rating);
}

/*
 * getUserRating
 *  NOTE:  See note on addUserRating above.  This method should be written to allow you
 *  to access an individual value from the list of user ratings 
 * @param index - the index of the rating we want to see
 * @return the rating indexed by the value index
 */
public int getUserRating(int index) {
    return userRatings.get(index);
}

/*
 * getUserRatingCount
 *  NOTE: See note on addUserRating above.  This method should be written to return
 *  the total number of ratings this product has associated with it
 * @return the number of ratings associated with this product
 */
public int getUserRatingCount() {
    return userRatings.size();
}

/*
 * getAvgUserRating
 *  NOTE: see note on addUserRating above.  This method should be written to compute
 *  the average user rating on demand from a stored list of ratings.
 * @return the average rating for this product as a whole integer value (use integer math)
 */
public int getAvgUserRating() {
    int sum = 0;
    if(userRatings.size() > 0){
        for (int i = 0; i < userRatings.size(); i++){
            sum += userRatings.get(i);
        }
        return sum / userRatings.size();
    }

    else return 0;
}
}

但问题在于测试代码。我尝试了多种方法并且不断出现InputMismatchException错误。对于第2部分,我将需要ArrayList个Product对象,因此我尝试将其合并到测试代码中。以下是 ProductTest.java

import java.util.*;
import java.io.*;

public class ProductTest {

/*
 * A simple main loop to load product objects from a file
 * and then display them to the console
 */
public static void main(String[] args) {
    Scanner keyboard = new Scanner(System.in);
    System.out.print("Enter an inventory filename: ");
    String fname = keyboard.nextLine();
    ArrayList<Product> products = loadProducts (fname);
    displayProducts(products);

}

/*
 * loadProducts
 * Given a filename, opens the file and reads Products from
 * the file into an ArrayList of Product objects. Returns the
 * Arraylist.
 * 
 * @param fname - String containing the input file name
 * @return - An ArrayList of Product objects
 */

public static ArrayList<Product> loadProducts(String fname) {
    ArrayList<Product> products = new ArrayList<Product>();
    try {
        Scanner inFile = new Scanner(new File(fname));
        while (inFile.hasNext()) {
            Product pr = new Product();
            pr.setName(inFile.next());
            pr.setInventoryCode(inFile.next());
            pr.setQuantity(inFile.nextInt());
            pr.setPrice(inFile.nextDouble());
            pr.setType(inFile.next());
            while(inFile.nextInt() != -1){
                pr.addUserRating(inFile.nextInt());
            }
            products.add(pr);
        }
        inFile.close();
    }
    catch(IOException e) {
        System.out.println("ERROR: "+e);
    }
    return products;
}

/*
 * displayProducts
 *  Given an ArrayList of Product objects, outputs them
 *  to the console in the specified format.
 *  
 *  The format for this method is:
 *  NAME, INVENTORY_CODE, QUANTITY, PRICE, TYPE, RATING
 *  
 *  @param products - ArrayList of Product objects
 */

public static void displayProducts(ArrayList<Product> products) {
    for(int i = 0; i<products.size(); i++) {
        Product tmpProduct = products.get(i);
        System.out.println(tmpProduct.getName());
        System.out.println(tmpProduct.getInventoryCode());
        System.out.println(tmpProduct.getQuantity());
        System.out.println(tmpProduct.getPrice());
        System.out.println(tmpProduct.getType());
        System.out.println(tmpProduct.getAvgUserRating());
        System.out.println();
    }

}

}

这是运行当前ProductTest产生的错误消息:

Exception in thread "main" java.util.InputMismatchException
    at java.util.Scanner.throwFor(Scanner.java:840)
    at java.util.Scanner.next(Scanner.java:1461)
    at java.util.Scanner.nextInt(Scanner.java:2091)
    at java.util.Scanner.nextInt(Scanner.java:2050)
    at osu.cse2123.ProductTest.loadProducts(ProductTest.java:46)
    at osu.cse2123.ProductTest.main(ProductTest.java:23)

我正在使用的文本文件包含以下内容:

The Shawshank Redemption
C0000001
100
19.95
DVD
4
5
3
1
-1
The Dark Knight
C0000003
50
19.95
DVD
5
2
3
-1
Casablanca
C0000007
137
9.95
DVD
5
4
5
3
-1
The Girl With The Dragon Tattoo
C0000015
150
14.95
Book
4
4
2
-1
Vertigo
C0000023
55
9.95
DVD
5
5
3
5
2
4
-1
A Game of Thrones
C0000019
100
8.95
Book
-1

对此问题的任何帮助都将不胜感激。

5 个答案:

答案 0 :(得分:5)

您一次只读一个字。目前,Scanner正在阅读您的文件,如下所示:

inFile.next()=中 inFile.next()= Shawshank

提示:inFile.nextLine()= Shawshank Redeption

答案 1 :(得分:1)

您的问题在于while循环阅读评分:

while(inFile.nextInt() != -1){
    pr.addUserRating(inFile.nextInt());
}

每轮循环读取两个项 - 一个在while条件下,另一个在循环内。由于评分结束后有一个String(下一个标题),如果有一个偶数个评级,那么在尝试将其解释为int时会失败(如果不是失败你只是得到错误的结果,因为你正在跳过一半的评级)。解决此问题的一种方法是将评级提取到本地变量:

int rating;
while(rating = inFile.nextInt() != -1){
    pr.addUserRating(rating);
}

答案 2 :(得分:0)

我建议您了解连续多次调用readInt。想象一下另一种读取值,检查它并重复使用它而无需重新读取的方法。

答案 3 :(得分:0)

如果没有更好的格式化文件(没有行尾),则需要使用正则表达式匹配:

这样的事情:

public static ArrayList<Product> loadProducts(String fname) {
    ArrayList<Product> products = new ArrayList<Product>();
    Pattern p = Pattern.compile("([\\w ]*) (C[0-9]*) (\\d*) ([\\d\\.]*) (\\w*) ([\\d -]*)");
    Matcher m = p.matcher(fname);
    while (m.find()) {
        Product pr = new Product();
        pr.setName(m.group(1));
        pr.setInventoryCode(m.group(2));
        pr.setQuantity(Integer.parseInt(m.group(3)));
        pr.setPrice(Double.parseDouble(m.group(4)));
        pr.setType(m.group(5));
        for (String rate : m.group(6).split(" ")) {
            pr.addUserRating(Integer.parseInt(rate));
        }
        products.add(pr);
        System.out.println(pr);
    }
    return products;
}

答案 4 :(得分:0)

当您从扫描仪实例调用InputMismatchExceptionnextDouble()而您输入的数字不是数字时,会发生nextInt()。错误消息显示该缺陷位于loadProducts方法中。 在该方法中,您可以拨打next()来获取产品名称和广告资源代码。但是,由于您的商品名称包含空格,因此您应该拨打nextLine()

您的计划会发生以下情况:在next()上致电"The Shawshank Redemption"将返回"The"。当您到达pr.setQuantity(inFile.nextInt());时,您的程序将抛出InputMismatchException,因为它会尝试从"Redemption"读取整数。

还考虑到mureinik的建议: https://stackoverflow.com/a/25936439/4056420