如何用Java连续读取文件?

时间:2018-12-19 02:40:45

标签: java

有一个包含5组8个数字的文件。每套都是参赛者的“分数”(总共5名参赛者)。我的任务是读取文件以获取每组,切出最高和最低分数,然后计算每个参赛者的平均分数。 该任务还要求我们使用一种方法来计算平均值,因此不允许我将整个程序塞入main方法中。

以下是供参考的数据集:

8.4 9.1 8.5 8.4 9.1 8.7 8.8 9.1
7.0 7.0 7.0 7.0 7.0 7.0 7.0 7.0
8.0 7.9 8.0 8.0 8.0 8.0 8.0 8.1
7.0 9.1 8.5 8.4 7.0 8.7 8.8 9.1
7.0 7.9 7.0 7.8 7.0 5.0 7.0 7.5

但是,我遇到了一个问题。每个参赛者的平均值计算为相同。这是因为每次我调用average()方法时,它都会创建文件读取的新实例,因此它每次都读取第一个8位数字。

这是我的代码:

//Code

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

public class DhruvPTheWinner{

 //Method for averaging
 public static double average()
 {
     double avg = 0.0;
     double sum = 0.0;
     double val = 0.0;
     double highest = -999.0;
     double lowest = 999.0;

     //This is how we were taught to read a file, using Try and Catch to "import" the file
     Scanner inFile = null;
     try{
            inFile = new Scanner (new File("theWinner.dat"));
        }
     catch (FileNotFoundException e){
            System.out.println("File not found");
            System.exit(0);
        }

     for(int j = 1; j <= 8; j++){
         val = inFile.nextDouble();
         //If statement to contain highest
         if(val > highest)
         {
             highest = val;
         }
         //If statement to contain lowest
         if(val < lowest)
         {
             lowest = val;
         }

         //Add the value (one of 8 #s) to the sum
         sum += val;

        }

     //Take out highest and lowest so avg only includes middle 6
     sum = (sum-highest)-lowest;
     avg = sum/6;

     return avg;
    }

 public static void main(String[] args){
        //Scores for the Contestants
        double c1Score = average();
        double c2Score = average();
        double c3Score = average();
        double c4Score = average();
        double c5Score = average();
        //Printing the scores
        System.out.printf("c1 is %.3f \nc2 is %.3f \nc3 is %.3f \nc4 is %.3f \nc5 is %.3f", c1Score, c2Score, c3Score, c4Score, c5Score);

 }
}

运行时,这是输出:

c1 is 8.767 
c2 is 8.767 
c3 is 8.767 
c4 is 8.767 
c5 is 8.767

如何解决此问题并使计算机继续读取文件,而不是重新开始?

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

问题在于,每次调用average时,您都将重新打开文件(在开头)。

尝试分为两部分

1)在main函数中:打开和关闭Scanner对象,并将一行数据读入数组

2)将数组传递到average

伪代码为

Main

for(int j = 0; j < 8; j++){
     val[j] = inFile.nextDouble();
}

average (val);

public static double average(double [] arr)

for(int j = 0; j < 8; j++){
    val = arr[j];
    .... // as before
}

答案 1 :(得分:0)

或者,您可以将Scanner inFile声明为静态全局变量,并在调用main()函数之前仅在average()中对其进行一次初始化。

这属于类范围:

public class DhruvPTheWinner{
    private static Scanner inFile=null;

将其放置在主要位置:

     try{
            inFile = new Scanner (new File("theWinner.dat"));
        }
     catch (FileNotFoundException e){
            System.out.println("File not found");
            System.exit(0);
        }

其余的保持不变。

答案 2 :(得分:0)

我同意可怕的袋熊,您必须在Scanner方法之外声明average()

我认为您可以从面向对象的角度来看这个问题。你到底有什么?您有上下文,其中包含一些数字。另外,上下文具有基于其数据的预先计算的属性。此上下文应从文件中读取。

让我们定义一个上下文并将所有相关计算封装到其中。

public class Contest {

    private static int nextId = 1;

    public final String id;
    private final double[] data;  // optionally, you can avoid storing whole array
    public final double avg;
    public final double sum;
    public final double highest;
    public final double lowest;

    public Contest(String... data) {
        id = "c" + nextId++;
        // you can calculate all this using one loop (instead of Streams)
        this.data = Arrays.stream(data).mapToDouble(Double::parseDouble).toArray();
        sum = Arrays.stream(this.data).sum();
        avg = Arrays.stream(this.data).average().orElse(Double.NaN);
        highest = Arrays.stream(this.data).max().orElse(Double.NaN);
        lowest = Arrays.stream(this.data).min().orElse(Double.NaN);
    }

}

然后,您需要一个方法,该方法接受所需文件的路径并返回现有竞赛的列表:

public static List<Contest> readContests(Path path) throws IOException {
    return Files.lines(path)
                .map(line -> line.split("\\s+"))
                .map(Contest::new)
                .collect(Collectors.toList());
}

如您所见,这是基于OOP的完整设计。然后,您可以使用它并预想一下:avg,sum ...:

List<Contest> contests = readContests(Paths.get("theWinner.dat"));
contests.forEach(contest -> System.out.format(Locale.US, "%s is %.3f\n", contest.id, contest.avg));

输出:

c1 is 8.763
c2 is 7.000
c3 is 8.000
c4 is 8.356
c5 is 7.025