如何从文本文件中获取 2 个单独的数字平均值?

How to get 2 separate number averages from a text file?

我是 java 语言的新手,我不知道如何一次从文本文件中读取一行并获取该行的平均值。

到目前为止,我的工作代码获得了整个文件的平均值:

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

public class NumAverage { 
    public static void main(String[] args) throws IOException { 
        Scanner keyboard = new Scanner(System.in); 

        File myFile = new File("Num.txt"); 
        Scanner inputFile = new Scanner(myFile); 

        int numbersCounter = 0;  
        int sum = 0; 

        while (inputFile.hasNext()) { 
            int numList = inputFile.nextInt(); 

            sum = sum + numList; 
            numbersCounter++; 
        } 

        System.out.println("Average: " + (sum/numbersCounter)); 

        inputFile.close(); 
    } 
}

这是文本文件的样子

 1 2 3 4
 5 6 7 8 

我认为您还必须检查“\n”(新行), 并在循环内打印平均值:

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

public class NumAverage{ 
public static void main(String[] args) throws IOException{ 
Scanner keyboard = new Scanner(System.in); 

File myFile = new File("Num.txt"); 
Scanner inputFile = new Scanner(myFile); 

int numbersCounter = 0;  
int sum = 0; 

while (inputFile.hasNext()) 
{ 
    if(inputFile.hasNextInt(){
        int numList = inputFile.nextInt(); 
        sum = sum + numList; 
        numbersCounter++;
    }
    if(inputFile.next().Equals("\n"){
        System.out.println("Average: " + (sum/numbersCounter));
        sum = 0;
        numbersCounter=0;
    }

} 



inputFile.close(); 

} }

你需要两个循环。一个遍历文件的每一行,一个遍历文件中的数字。修改您的代码以使用两个扫描仪:

package com.test;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class TestAverageFromFileLines {

    public static void main(String[] args) throws FileNotFoundException {

        File myFile = new File("Num.txt");
        try (Scanner input = new Scanner(myFile)) {
            while (input.hasNextLine()) {
                String line = input.nextLine();

                int numbersCounter = 0;
                int sum = 0;

                try (Scanner lineScanner = new Scanner(line)) {
                    while (lineScanner.hasNext()) {
                        int numList = lineScanner.nextInt();
                        sum = sum + numList;
                        numbersCounter++;
                    }
                }
                System.out.println("Average: " + ((double)sum / numbersCounter));
            }
        }
    }

}

此外,Java 中的整数除法默认会截断小数部分。因此,要强制 Java 执行非截断除法,您需要将其中一个操作数转换为 float 或 double。

Scanner 对象有一个函数 scanner.nextLine() 它会 return 一个字符串,您可以将其处理为一系列数字,因为您知道文件的格式。

 String[] myNumbersArray = myNumbers.split(" ");
 for (String s : myNumbersArray) {
      int myNumber = Integer.parseInt(s);
 }

你必须学习 Java 的流 API(知道装饰器模式可以简化它的理解)。

针对您的情况,我们可以这样做:

FileInputStream stream = new FileInputStream("nums.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line;

while((line = reader.readLine()) != null) {
    StringTokenizer tokenizer = new StringTokenizer(line, " ");
    int tokens = tokenizer.countTokens();
    float average = 0;

    while(tokenizer.hasMoreTokens()) {
        String token = tokenizer.nextToken();
        int value = Integer.valueOf(token);
        average += value;
    }

    System.out.println(average / tokens);
}

在第一行中,我创建了一个 FileInputStream 允许我们从文件中读取。

在第二行中,我将 stream 修饰为 InputStreamReader,然后修饰为 BufferedReader(第二行具有很好的 API 用于逐行读取输入)。

然后我逐行遍历您的文件(在循环中使用 readLine() 方法)并使用 StringTokenizer 我将行拆分为标记。

在第二个循环中,我正在做所有必要的计算。

当然你需要记住异常(为了简单起见我省略了它们)。

还有一件事值得一提 - 你需要知道在消费令牌之前应该使用 countTokens() 方法 - 否则它会 return 不正确的值(它 return这是在收到异常之前可以调用多少个 nextToken() 的数字)。

试试这个。

File myFile = new File("Num.txt"); 
try (Scanner c = new Scanner(myFile)) {
    while (c.hasNextLine()) {
        System.out.println("Average: " +
            Stream.of(c.nextLine().split("\s+"))
                .mapToInt(x -> Integer.parseInt(x))
                .average().getAsDouble());
    }
}

结果:

Average: 2.5
Average: 6.5

您可以使用 Files.lines() 创建一个文本行流,然后将每一行解析为一个数字数组并计算它们的平均值。

    Files.lines(Paths.get("nums.txt"))
            .map(str -> str.split(" "))   
            .mapToDouble(arr -> Arrays.stream(arr).mapToInt(Integer::valueOf).average().orElse(0.0))
            .forEach(avg -> System.out.println("Average: " + avg));

Files.lines() 处理所有文件 I/O 并创建一个 Stream<String> 允许在从文件中读取每一行时对其进行延迟处理。如果有一天您需要处理内存中放不下的非常大的文件,这将非常有用,因为每一行只有在前一行被 Stream 完全处理后才会被读取。它会在完成后自动为您关闭文件。

下一行获取文件中的每一行并将其转换为一个字符串数组,每个数字一个。此时,流从 Stream<String> 更改为 Stream<String[]>

下一行将每个 String[] 转换为一个数字,该数字是该行数字的平均值。它通过获取字符串数组并使用 Arrays.stream() 从中创建流,使用 Integer.valueOf() 将每个字符串更改为整数,然后调用 average() 获取整个流来实现整数并计算平均值。此时 Stream 现在是 DoubleStream.

下一行取每个平均值并打印出来。

整个操作序列发生在每一行上,因此在从文件中读取下一行之前先打印第一行的平均值。