Я новичок в языке 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
6 ответов
Вы должны изучить API потоков Java (знание шаблона декоратора упрощает его понимание).
Для вашего случая мы можем сделать:
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 () следует использовать перед потреблением токенов - в противном случае он вернет неправильное значение (он возвращает число из того, сколько вы можете вызвать nextToken()
до получения исключения).
Я думаю, вам также нужно проверить наличие «\ 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();
} }
У объекта Scanner есть функция scanner.nextLine()
. Она возвращает строку, которую вы можете обрабатывать как серию чисел, потому что вы знаете формат файла.
String[] myNumbersArray = myNumbers.split(" ");
for (String s : myNumbersArray) {
int myNumber = Integer.parseInt(s);
}
Вам понадобится две петли. Один для перебора каждой строки файла и один для перебора чисел в файле. Изменен ваш код для использования двух сканеров:
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.
Попробуй это.
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()
заботится обо всех операциях ввода-вывода файла и создает Stream<String>
, который позволяет лениво обрабатывать каждую строку при ее чтении из файла. Это действительно полезно, если когда-нибудь вам понадобится иметь дело с очень большими файлами, которые не помещаются в памяти, поскольку каждая строка читается только после того, как предыдущая строка была полностью обработана Stream. По завершении он автоматически закроет файл для вас.
Следующая строка берет каждую строку в файле и преобразует ее в массив строк, по одной для каждого числа. В этот момент поток меняется с Stream<String>
на Stream<String[]>
Следующая строка преобразует каждый String [] в число, которое представляет собой среднее значение чисел в строке. Он делает это, беря массив строк и создавая из него поток с помощью Arrays.stream()
, превращая каждую строку в целое число с помощью Integer.valueOf()
, а затем вызывая average()
, чтобы взять весь поток целые числа и вычислить среднее. На данный момент поток теперь является DoubleStream
.
В следующей строке каждое среднее значение печатается.
Вся последовательность операций происходит в каждой строке, поэтому среднее значение первой строки печатается до того, как следующая строка будет считана из файла.
Похожие вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.