#java #arraylist
#java #arraylist
Вопрос:
У меня есть .txt
файл с таким содержимым: "17.23;12.1;20.34;88.23523;"
. Я хочу прочитать этот файл как удвоенный в ArrayList
. И в конечном итоге распечатайте ArrayList
(и в конечном итоге распечатайте min. и макс., но я не думаю, что это будет проблемой после решения этого).
Но я получаю только вывод «[ ]».
Что я делаю не так? Я боролся с этим более 15 часов, просматривал здесь, youtube, учебные пособия…
Мой код:
public static void main(String[] args) throws IOException {
File myFile = new File("text.txt");
Scanner scan = new Scanner(myFile);
ArrayList<Double> aList = new ArrayList<>();
while (scan.hasNextDouble()) {
double nextInput = scan.nextDouble();
if (nextInput != 0) {
break;
}
aList.add(nextInput);
}
System.out.println(alist);
}
Комментарии:
1.
if (nextInput != 0) break;
зачем вам нужна эта строка? Из-за них ваш код никогда не должен добавлять что-либо в ArrayList с учетом вашего ввода2. Поскольку в вашем файле есть числа, разделенные точкой с запятой, вы не сможете прочитать их с помощью
scan.hasNextDouble()
по умолчанию. Однако существует так много способов сделать это, например, прочитать строку как строку и обработать каждое число из нее после разделения его на точки с запятой. Другой способ — переопределить разделитель по умолчанию и т. Д.
Ответ №1:
Вы должны настроить свой сканер так, чтобы он принимал:
;
в качестве разделителя,
в качестве десятичного разделителя
Рабочий код:
File myFile = new File("input.txt");
// Swedish locale uses ',' as a decimal separator
Scanner scan = new Scanner(myFile).useDelimiter(";").useLocale(Locale.forLanguageTag("sv-SE"));
ArrayList<Double> aList = new ArrayList<>();
while (scan.hasNextDouble()) {
double nextInput = scan.nextDouble();
aList.add(nextInput);
}
System.out.println(aList);
С выводом [17.23, 12.1, 20.34, 88.23523]
Комментарии:
1. Отличный ответ, 1 от меня, хотя я считаю, что слово «Uppgift» в имени файла — шведское, и Швеция
,
также используется, поэтому изменениеLocale.FRENCH
наLocale.forLanguageTag("sv-SE")
, вероятно, будет более точным для вопроса. Тот же результат, конечно.2. Да, конечно, французский — это просто пример (язык «ru-RU» тоже работает)
Ответ №2:
Scanner
работает путем разделения входных данных на токены, где токены разделены пробелами (по умолчанию). Поскольку в тексте нет пробелов, первым / единственным маркером является весь текст, и поскольку этот текст не является допустимым double
значением, hasNextDouble()
возвращает false
.
Два способа исправить это:
-
Измените разделитель токенов на
;
:scan.useDelimiter(";");
-
Прочитайте файл с
BufferedReader
помощью и используйтеsplit()
:String filename = "text.txt"; try (BufferedReader in = Files.newBufferedReader(Paths.get(filename))) { for (String line; (line = in.readLine()) != null; ) { String[] tokens = line.split(";"); // code here } }
Теперь это приведет к следующим токенам: 17,23
, 12,1
, 20,34
, 88,23523
.
К сожалению, ни одно из этих double
значений не является допустимым, поскольку они используют форматирование, зависящее от локали, то есть десятичная точка — это a ,
, а не a .
.
Это означает, что если вы продолжали использовать Scanner
, вы не можете использовать hasNextDouble()
и nextDouble()
, и если вы изменили на use split()
, вы не можете использовать Double.parseDouble()
.
Вам нужно использовать a NumberFormat
для анализа форматов чисел, зависящих от локали. Поскольку «Uppgift» выглядит по-шведски, мы можем использовать NumberFormat.getInstance(Locale.forLanguageTag("sv-SE"))
, или просто NumberFormat.getInstance()
, если ваш язык по умолчанию — Швеция.
String filename = "text.txt";
try (BufferedReader in = Files.newBufferedReader(Paths.get(filename))) {
NumberFormat format = NumberFormat.getInstance(Locale.forLanguageTag("sv-SE"));
for (String line; (line = in.readLine()) != null; ) {
List<Double> aList = new ArrayList<>();
for (String token : line.split(";")) {
double value = format.parse(token).doubleValue();
aList.add(value);
}
System.out.println(aList); // Prints: [17.23, 12.1, 20.34, 88.23523]
}
}
Ответ №3:
Вы можете сделать это, просто изменив разделитель. Это работает путем чтения из строки, но вы также можете сделать это из файла. Вам решать поместить значения в некоторую структуру данных. Это предполагает, что ваш язык по умолчанию использует ‘,’ в качестве десятичной точки.
String str = "17,23;12,1;20,34;88,23523;";
Scanner scan = new Scanner(str);
scan.useDelimiter("[;] ");
while(scan.hasNextDouble()) {
System.out.println(scan.nextDouble());
}
С принтами
17.23
12.1
20.34
88.23523
Комментарии:
1. Запятая — это десятичный разделитель в вопросе OP, а не разделитель чисел
2. Маловероятно, что оба
,
и;
являются разделителями значений. Гораздо более вероятно, что;
это разделитель значений, и это,
десятичная точка, зависящая от локали, тем более, что слово «Uppgift» в имени файла — шведское, а Швеция использует,
в качестве десятичной точки.3. Ну, OP не указал это в вопросе (но это имеет смысл), поэтому я уточнил это в своем ответе. Спасибо вам обоим!
4. Привет, Андреас прав. Теперь я изменил это на более международный стандарт! Большое спасибо за ответы!
Ответ №4:
Поскольку в вашем файле есть числа, разделенные точкой с запятой, вы не сможете прочитать их с помощью scan.hasNextDouble()
по умолчанию. Однако существует так много способов сделать это, например
- Переопределите разделитель по умолчанию.
- Чтение строки как строки и обработка каждого числа из нее после разделения на точки с запятой.
Вариант-1:
scan.useDelimiter(";")
Обратите внимание, что, поскольку в вашем файле вместо точки в качестве десятичного символа используется запятая, вы можете использовать a Locale
, в котором он используется по умолчанию.
scan.useLocale(Locale.FRANCE);
Кроме того, следующий блок кода в вашем коде приведет к завершению цикла после считывания самого первого числа как первого числа в вашем файле, не равного нулю. Просто удалите эти строки, чтобы получить желаемый результат:
if (nextInput != 0) {
break;
}
Вариант-2:
Прочитайте строку, разделите ее точкой с запятой, замените запятую точкой, проанализируйте каждый элемент из результирующего массива в Double
и сохраните его в aList
.
ДЕМОНСТРАЦИЯ:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
File myFile = new File("file.txt");
Scanner scan = new Scanner(myFile);
List<Double> aList = new ArrayList<>();
while (scan.hasNextLine()) {
String nextInput = scan.nextLine();
String[] arr = nextInput.split(";");
for (String s : arr) {
aList.add(Double.valueOf(s.replace(",", ".")));
}
}
System.out.println(aList);
}
}
Вывод:
[17.23, 12.1, 20.34, 88.23523]
Альтернативой замене запятой точкой является использование NumberFormat
, как показано ниже:
import java.io.File;
import java.io.FileNotFoundException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException, ParseException {
File myFile = new File("file.txt");
Scanner scan = new Scanner(myFile);
NumberFormat format = NumberFormat.getInstance(Locale.FRANCE);
List<Double> aList = new ArrayList<>();
while (scan.hasNextLine()) {
String nextInput = scan.nextLine();
String[] arr = nextInput.split(";");
for (String s : arr) {
aList.add(format.parse(s).doubleValue());
}
}
System.out.println(aList);
}
}