Java 使用txt输入文件和扫描仪处理空行

Java 使用txt输入文件和扫描仪处理空行,java,error-handling,io,Java,Error Handling,Io,我的程序完成了。我需要的一件事是它处理空白行的方法。我读过其他文章,但没有一篇帮助我将它们实现到我自己的代码中。我在读取文件的循环中尝试了各种语法,但都不起作用。谁能帮帮我吗。这看起来应该比现在感觉的容易。我正试图在我的代码中实现这一点,但在实现时遇到了困难。下面是我的两个类和input.txt。按原样,此程序按预期运行。谢谢你的帮助 String line = in.nextLine(); while (line.length() == 0) { if (in.hasNext()) {

我的程序完成了。我需要的一件事是它处理空白行的方法。我读过其他文章,但没有一篇帮助我将它们实现到我自己的代码中。我在读取文件的循环中尝试了各种语法,但都不起作用。谁能帮帮我吗。这看起来应该比现在感觉的容易。我正试图在我的代码中实现这一点,但在实现时遇到了困难。下面是我的两个类和input.txt。按原样,此程序按预期运行。谢谢你的帮助

String line = in.nextLine();
while (line.length() == 0) {
  if (in.hasNext()) {
     line = in.nextLine();
  } else {
    break;
  }
}
if (line.length() == 0) {
   // reaches the end of input file
}
Product.java

/**
 * Product
 * 
 *   A simple class framework used to demonstrate the design
 *   of Java classes.
 *   
 *   @author 
 *   @version 02042015
 */
import java.util.*;

public class Product {
    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.0;
        type = "";
        userRatings = new ArrayList<Integer>();

    }
     public Product(Product productObject) {
            this.name = productObject.getName();
            this.code = productObject.getInventoryCode();
            this.quantity = productObject.getQuantity();
            this.price = productObject.getPrice();
            this.type = productObject.getType();
            this.userRatings = new ArrayList<Integer>();
        }

    public Product(String name, String code, int quantity, double price, String type) {
        this.name = name;
        this.code = code;
        this.quantity = quantity;
        this.price = price;
        this.type = type;
        this.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) {
        if(code.length()!= 8){
            System.out.println("An invalid code has been entered. Please enter a code that is 8 characters in length.");
        }
        else{
        }
        this.code=code;
    }

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

    /*
     * setRatings
     * @param code the new set of ratings for the product
     */
    public void setRatings(ArrayList<Integer> Ratings){
        this.userRatings = Ratings;
    }

    /*
     * getRatings
     * @return the ratings of the product
     */
    public ArrayList<Integer> getRatings(){
        return userRatings;
    }

    /*
     * 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(Integer rating1) {
        if(rating1 > 5 || rating1 < 0){
            System.out.println("You have entered an invalid rating. Please enter a rating between one and five stars.");
        }
        this.userRatings.add(rating1);
    }


    /*
     * 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) {
        int a = this.userRatings.get(index);
        return a;
    }

    /*
     * 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() {
        int a = this.userRatings.size();
        return a;
    }

    /*
     * 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 String getAvgUserRating() {
         int sum = 0;
          String avgRating = "";
         if (userRatings.size() != 0){
          for (int i = 0; i < this.userRatings.size(); i++) {
              int a = getUserRating(i);
                sum += a;
          }
          double avg = sum/this.userRatings.size();
          if(avg >= 3.5){
              avgRating = "****";
          }
          else if(avg >= 2.5){
              avgRating = "***";
          }
          else if(avg >= 1.5){
              avgRating = "**";
          }
          else if(avg >= 0.5){
              avgRating = "*";
          }
          else{
          }
         }
         else{
             avgRating = "";
         }
          return avgRating;
}
}

分解问题时,您会发现有两个主要问题:

  • 逐行阅读输入
  • 跳过空白行。 第一个问题可以通过
    而在.nextLine()中(in.hasNext)解决。要解决第二个问题,只需在发现行为空时添加一个
    continue

    while (in.hasNextLine()) {
        line = in.nextLine();
        // skip blank lines
        if (line.length() == 0) continue;
        // do your magic
    }
    
    现在,如何把这个放到你的主程序中?如果我们能做到这一点,那就太好了:
    infle.nextNonBlankLine()
    ,对吗?所以,让我们创建我们自己的扫描仪,有这种方法

    首先,我们想如何使用自己的扫描仪?一个例子是:

    SkipBlankScanner in = new SkipBlankScanner(inFile);
    while (in.hasNextNonBlankLine()) {
        line = in.nextNonBlankLine();
    }
    
    不幸的是,
    Scanner
    是一个
    final
    类,因此我们无法扩展它来添加我们的功能。下一个最好的方法是使用委托:

    public class SkipBlankScanner {
        private Scanner delegate;
        private String line;
    
        public SkipBlankScanner(Scanner delegate) {
             this.delegate = delegate;
        }
    
        public boolean hasNextNonBlankLine() {
            while (delegate.hasNextLine())
                // return true as soon as we find a non-blank line:
                if ((line = delegate.nextLine()).length > 0)
                     return true;
            // We've reached the end and didn't find any non-blank line:
            return false;
        }
    
        public String nextNonBlankLine() {
            String result = line;
            // in case we didn't call "hasNextNonBlankLine" before:
            if (result == null && hasNextNonBlankLine())
                result = line;
            // try to read past the end:
            if (result == null) throw new IllegalStateException();
            line = null;
            return result;
        }
    }
    
    现在你有了它,你自己的扫描仪可以忽略空白行

    您可以更进一步,创建一个扫描整个产品的扫描仪,例如(使用一些Java-8):

    公共类ProductScanner{
    私人Skipblank扫描仪;
    私人产品;
    公共产品扫描仪(SkipBlank扫描仪){
    this.scanner=扫描器;
    }
    公共布尔hasNextProduct(){
    下一个产品=新产品();
    如果(填充(行->下一个.setTitle(行))&&
    填充(行->下一个.setInventoryCode(行))&&
    填充(行->下一个.setQuantity(整型.parseInt(行)))&&
    填充(行->下一个.setPrice(Double.parseDouble(行)))&&
    填充(行->下一个.setType(行))){
    试一试{
    while(scanner.hasNextNonBlankLine(){
    int rating=Integer.parseInt(scanner.nextNonBlankLine());
    如果(额定值<0){
    产品=下一个;
    返回true;
    }
    下一步。添加用户评级(评级);
    }
    }捕获(数字格式){
    }
    }
    返回false;
    }
    专用布尔填充(使用者操作){
    if(scanner.hasNextNonBlankLine(){
    试一试{
    action.accept(scanner.nextNonBlankLine());
    返回true;
    }捕获(例外e){
    }
    }
    返回false;
    }
    公共产品下一个产品(){
    产品结果=产品;
    if(result==null&&hasNextProduct())
    结果=产品;
    如果(结果==null)
    抛出新的非法状态异常();
    product=null;
    返回结果;
    }
    }
    
    您的文件似乎没有任何空行(而且它似乎是固定格式);此外,您不应该将
    nextInt()
    nextLine()
    混合使用……这会给您带来各种痛苦(因为
    nextInt()
    不会占用新行)@ElliottFrisch如果我添加一个空行,它就不能像现在这样处理它。我需要它来处理它,以防出现一个空行。你能把它放在github的摘要中吗?@Ron我从来没有使用过github。这里有什么问题吗?如果我想玩,我就必须复制/粘贴它,把它打过来。制作摘要,使它更容易使用我有一些想法,但我想先检查一下
    SkipBlankScanner in = new SkipBlankScanner(inFile);
    while (in.hasNextNonBlankLine()) {
        line = in.nextNonBlankLine();
    }
    
    public class SkipBlankScanner {
        private Scanner delegate;
        private String line;
    
        public SkipBlankScanner(Scanner delegate) {
             this.delegate = delegate;
        }
    
        public boolean hasNextNonBlankLine() {
            while (delegate.hasNextLine())
                // return true as soon as we find a non-blank line:
                if ((line = delegate.nextLine()).length > 0)
                     return true;
            // We've reached the end and didn't find any non-blank line:
            return false;
        }
    
        public String nextNonBlankLine() {
            String result = line;
            // in case we didn't call "hasNextNonBlankLine" before:
            if (result == null && hasNextNonBlankLine())
                result = line;
            // try to read past the end:
            if (result == null) throw new IllegalStateException();
            line = null;
            return result;
        }
    }
    
    public class ProductScanner {
        private SkipBlankScanner scanner;
        private Product product;
    
        public ProductScanner(SkipBlankScanner scanner) {
            this.scanner = scanner;
        }
    
        public boolean hasNextProduct() {
            Product next = new Product();
            if (fill(line -> next.setTitle(line)) &&
                fill(line -> next.setInventoryCode(line)) &&
                fill(line -> next.setQuantity(Integer.parseInt(line))) &&
                fill(line -> next.setPrice(Double.parseDouble(line))) &&
                fill(line -> next.setType(line))) {
    
                try {
                    while (scanner.hasNextNonBlankLine() {
                        int rating = Integer.parseInt(scanner.nextNonBlankLine());
                        if (rating < 0) {
                            product = next;
                            return true;
                        }
                        next.addUserRating(rating);
                    }
                } catch (NumberFormatException e) {
                }
            }
            return false;
        }
    
        private boolean fill(Consumer<String> action) {
            if (scanner.hasNextNonBlankLine() {
                try {
                    action.accept(scanner.nextNonBlankLine());
                    return true;
                } catch (Exception e) {
                }
            }
            return false;
        }
    
        public Product nextProduct() {
            Product result = product;
            if (result == null && hasNextProduct())
                result = product;
            if (result == null)
                throw new IllegalStateException();
            product = null;
            return result;
        }
    }