代码之家  ›  专栏  ›  技术社区  ›  jameyb

对于Java中的文件I/O,如何仅使用具有不同数据的文本文件中的特定数据集?

  •  1
  • jameyb  · 技术社区  · 7 年前

    我正在为我的初级Java类解决一个问题。我找不到 具体的 这种情况的答案,但我确实看到了一些关于读取单行、常规文件I/O和从文件内部打印一组数据的答案。

    很多答案使用的东西超出了我的课程范围,并没有给我一个确切的想法去做什么。简而言之,我需要做的是只取文本文件的中间列,然后使用该数据计算并打印程序主类中的平均值。

    中间的数据都是双倍的,但程序不知怎的在计算左边的整数?我特别说过 input.nextDouble(); 所以我很困惑。Double的优先级高于Int,但为什么这些Int会被计算为Double?这可能实际上很简单,但我不确定我是怎么搞砸的。

    以下是迄今为止我键入的代码,以实现我的目标:

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.util.Scanner;
    
    public class HouseHold {
    
        public void displayFile() throws FileNotFoundException {
            File file = new File("Program10.txt");
            Scanner input = new Scanner(file);
    
            System.out.printf("%s   %s   %s%n%n", "ID#", "Yearly Income", "# of Occupants");
            while (input.hasNext()) {
                System.out.printf("%-10d %10.2f   %-10d %n", input.nextInt(), input.nextDouble(), input.nextInt());
            }
    
            System.out.println("\n");
            input.close();
        }
    
        //double
        public void averageIncome() throws FileNotFoundException {
            File file = new File("Program10.txt");
            Scanner input = new Scanner(file);
    
            int numMuns = 0;
            int sum = 0;
            while (input.hasNext()) {
    
                numMuns++;
                sum += input.nextDouble();
    
                //The next two lines are how I found the issue:
                System.out.println(numMuns);
                System.out.println(sum);
    
            }
    
        }
    
    
    
            //return sum / numMuns;
    }
    

    实际上,我必须从中复制数据。将下面的txt文件导入Microsoft Excel,以确保我是正确的。我很高兴我做到了,因为 戏剧性地 不同:

    1042  12180.06  3
    1062  13240.45  2
    1327  19800.56  2
    1483  22458.23  7
    1900  17000.09  3
    2112  18125  4
    2345  15623  2
    3210   3200  1
    3600  39500  5
    3601  11970  2
    4724   8900  3
    6217  45000.70  2
    9280   6200  1
    1000  31000  3
    1200  36000  2
    5601  51970  9
    5724  66900  3
    5217  10002.68  2
    5280  70000  1
    5000 100000  6
    5200  25000.4  3
    5230 120000  6
    6641  85000  7
    7000  45500  4
    7100  56500  3
    8110 110005.9  8
    9101  67590.40 6
    

    我已经格式化了文件数据,并将其显示在主类中(这是本项目的另一个规范):

    ID#     Yearly Income   # of Occupants
    
    1042         12180.06   3          
    1062         13240.45   2          
    1327         19800.56   2          
    1483         22458.23   7          
    1900         17000.09   3          
    2112         18125.00   4          
    2345         15623.00   2          
    3210          3200.00   1          
    3600         39500.00   5          
    3601         11970.00   2          
    4724          8900.00   3          
    6217         45000.70   2          
    9280          6200.00   1          
    1000         31000.00   3          
    1200         36000.00   2          
    5601         51970.00   9          
    5724         66900.00   3          
    5217         10002.68   2          
    5280         70000.00   1          
    5000        100000.00   6          
    5200         25000.40   3          
    5230        120000.00   6          
    6641         85000.00   7          
    7000         45500.00   4          
    7100         56500.00   3          
    8110        110005.90   8          
    9101         67590.40   6 
    

    我发现的问题是,ID#也被放入平均值中。

    ID#是一个整数。收入是双倍的。方法 averageIncome() 应该返回一个等于平均值的双精度 (sum / numMuns) ,但是,正如我所说,它没有。有什么建议吗?我可能忽略了一些东西,但我很感谢你的帮助。谢谢

    编辑- 以下是我为解决这一问题所做的努力,但仍有一些严重问题我难以解决:

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.util.Scanner;
    
    public class HouseHold {
    
        public void displayFile() throws FileNotFoundException {
            File file = new File("Program10.txt");
            Scanner input = new Scanner(file);
    
            System.out.printf("%s   %s   %s%n%n", "ID#", "Yearly Income", "# of Occupants");
            while (input.hasNext()) {
                System.out.printf("%-10d %10.2f   %-10d %n", input.nextInt(), input.nextDouble(), input.nextInt());
            }
    
            System.out.println("\n");
            input.close();
        }
    
        //double
        public void averageIncome() throws FileNotFoundException {
            File file = new File("Program10.txt");
            Scanner input = new Scanner(file);
    
            int numMuns = 0;
            double sum = 0.0;
            do {
                String inputRead = input.nextLine();
                String[] line = inputRead.split("  ");
                sum += Double.parseDouble(line[1]);
                /*
                if(inputRead.contains(".")) {
                    //System.out.println(inputRead);
                    sum += Double.parseDouble(inputRead);
                    numMuns++;
                    System.out.println(numMuns);
                    System.out.println("\n" + sum);
                }
                */
    
            } while (input.hasNext());
    
            System.out.println(numMuns);
             //return sum / numMuns;
    
        }
    
    
    }
    

    当我到达需要调试的部分时,会引发异常:

    Exception in thread "main" java.lang.NumberFormatException: For input string: "67590.40 6"
        at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
        at sun.misc.FloatingDecimal.parseDouble(Unknown Source)
        at java.lang.Double.parseDouble(Unknown Source)
        at program10.HouseHold.averageIncome(HouseHold.java:32)
        at program10.TestHouseHold.main(TestHouseHold.java:13)
    

    据我所知,问题是由于格式分散,它无法解析原始文件的数据。就像我很想修复一样。txt文件,我不能修改它,因为如果我修改它,讲师不会给我好分数(他用他为作业提供的原始文件编译并运行代码)。也许我可以尝试在没有分隔符的情况下解析它?原始文件中的间距显然不适合简单的字符串拆分。此外,我认为我需要将一些美元金额格式化为双倍,因为if语句没有看到它们(不是全部,有些只是作为int编写的)。 我也会寻找一些可能的解决方案,但如果有任何进一步的想法或指导,我将不胜感激!

    最终编辑: 该问题已通过KID94提供的以下解释得到解决。这比我想象的要简单得多。谢谢你们的帮助,伙计们!

    4 回复  |  直到 7 年前
        1
  •  0
  •   kezhenxu94    7 年前

    这很简单,因为您已经知道第一列和最后一列都是整数,只需使用 input.nextInt() 在阅读中间一列之前和之后传递它们,如下所示:

    public double averageIncome() throws FileNotFoundException {
        File file = new File("Program10.txt");
        Scanner input = new Scanner(file);
    
        int numMuns = 0;
        int sum = 0;
        while (input.hasNext()) {
    
            numMuns++;
    
            // Just read id and ignore it
            input.nextInt();
    
            sum += input.nextDouble();
    
            // Just read # of Occupants and ignore it
            input.nextInt();
    
            //The next two lines are how I found the issue:
            System.out.println(numMuns);
            System.out.println(sum);
    
        }
        return sum / numMuns;
    }
    
        2
  •  0
  •   Remzi Ibrahim Zayid    7 年前

    因此,看起来您正试图从每行中选取中间的项目,并将它们平均起来。

    一种方法是将每一行标记为一个元素数组,然后只获取中间的元素。

    我将替换:

    sum += input.nextDouble();
    

    使用:

    String line = input.nextLine();
    String[] tokens = line.split(" ") //You can replace the blank space with whatever it is that is separating each entry in the line. its hard to tell what that is from the original post
    sum += Double.parseDouble(tokens[1]);
    
        3
  •  0
  •   motti    7 年前
        Scanner scanner = new Scanner(file);
    
        int x = 0;
        double y = 0.0;
        while(scanner.hasNext()){
       //using regex and splitting the line at one or more whitespaces taking the second value and parsing it as double
            y += Double.parseDouble(scanner.nextLine().split("\\s+")[1]);
            x++;
        }
        System.out.println(y);
        System.out.println(x);
        System.out.println(y / x);
    
        4
  •  0
  •   user2872194    7 年前

    Jamey输入。nextDouble将尝试以双精度扫描下一个输入。这就是为什么你所有的数字都包含在总数中。(参见下面的链接) https://www.tutorialspoint.com/java/util/scanner_nextdouble.htm

    至于您的问题的解决方案,我将以字符串的形式读取输入,并使用十进制作为字符串是双精度的指示符。如果它有一个十进制数,则将字符串转换为双精度,并将其添加到求和中。

     File file = new File("program10.txt");
            Scanner input = new Scanner(file);
    
            int numMuns = 0;
            double sum = 0;
            while (input.hasNextLine()) {
    
                numMuns++;
                String inputToRead =  input.next();
                if(inputToRead.contains(".")) {
    
                    sum += Double.parseDouble(inputToRead);
                }
    
                //sum += input.nextDouble();
    
                //The next two lines are how I found the issue:
                //System.out.println(numMuns);
    
        }