#java #arrays #java.util.scanner
#java #массивы #java.util.scanner
Вопрос:
я создаю простую программу отчетов о продажах, которая считывает данные из текстового файла и присваивает их массиву
Текстовый файл содержит:
Coke
34 3.00 5.00
Sprite
18 2.89 4.30
Fanta Mango
21 3.35 5.99
Orange Crush
35 4.00 6.00
Browns Cream Soda
43 4.25 5.75
Проблема возникает, когда я использую сканер для чтения каждой строки и присваиваю ее массиву.
Мой код выглядит так:
while(in.hasNext()) {
sodaBrand[sodaBrand.length - 1]= in.nextLine();
numberOfBottles[numberOfBottles.length -1] = in.nextInt();
costOfBottles[costOfBottles.length - 1] = in.nextDouble();
retailCost[retailCost.length - 1] = in.nextDouble();
}
Как я и ожидал, это дает мне исключение несоответствия ввода, поскольку оно обрабатывает весь текст из файла как строки.
Есть идеи, с чего я мог бы начать, чтобы решить эту проблему? Любая помощь будет принята с благодарностью.
Спасибо
Ответ №1:
Я скопировал ваш файл в свой блокнот. Позвольте мне добавить n в ваш файл для лучшего объяснения. Это не так, как ваш файл. Это просто для большей ясности.
Здесь n представляет переход к следующей строке.
Coken
34 3.00 5.00n
Spriten
18 2.89 4.30n
Fanta Mangon
21 3.35 5.99n
Orange Crushn
35 4.00 6.00n
Browns Cream Sodan
43 4.25 5.75
Я заметил это, когда скопировал его в свой блокнот. В последней строке вашего файла нет n в конце.
Я также приведу синтаксис различных методов, которые вы использовали в своем коде. Посетите здесь для получения дополнительной информации о сканере. https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
boolean hasNext()
//Returns true if this scanner has another token in its input.
int nextInt()
//Scans the next token of the input as an int.
double nextDouble()
//Scans the next token of the input as a double.
String nextLine()
//Advances this scanner past the current line and returns the input that was
//skipped.
Теперь давайте посмотрим, что происходит в каждой строке вашего кода.
Вот код с комментариями.
while(in.hasNext()) //returns true as Coke is available as a token for input
{
sodaBrand[sodaBrand.length - 1]= in.nextLine(); //reads Coke and moves the cursor to next line
numberOfBottles[numberOfBottles.length -1] = in.nextInt(); //reads 34
costOfBottles[costOfBottles.length - 1] = in.nextDouble(); //reads 3.00
retailCost[retailCost.length - 1] = in.nextDouble(); //reads 5.00
}
Обратите внимание, что после последнего ввода in.nextDouble() курсор не переместился на следующую строку.
Теперь на этот раз, когда проверяется условие while , это произойдет,
while(in.hasNext()) //returns true as it has Sprite as String available for input
Но, как я уже сказал, ваш курсор все еще находится перед n в этой строке
34 3.00 5.00n
Следующий вызов in.nextLine() вернет «» и переместит курсор на следующую строку, которая является Sprite n .
Теперь следующий вызов in.nextInt() вызывает исключение InputMismatchException, поскольку для ввода доступен спрайт, который не является int.
Измените свой код на это.
while(in.hasNext())
{
sodaBrand[sodaBrand.length - 1]= in.nextLine();
numberOfBottles[numberOfBottles.length -1] = in.nextInt();
costOfBottles[costOfBottles.length - 1] = in.nextDouble();
retailCost[retailCost.length - 1] = in.nextDouble();
in.nextLine(); //this will cause the scanner to return "" and move the control to the next line
}
Ваш код все равно выдаст исключение NoSuchElementException после прочтения всех строк. Это происходит потому, что в вашем текстовом файле нет n в последней строке.
Перейдите к своему файлу и переместите курсор на последнюю строку. Вы увидите, что последняя позиция курсора находится после 5.75. Если вы нажмете стрелку вниз, курсор не будет перемещаться. Это показывает, что ваш файл заканчивается здесь. В конце нет ввода или n .
Нажмите enter и сохраните файл. Теперь вы увидите, что последняя позиция курсора находится в следующей строке после 5.75.Теперь ваш файл заканчивается здесь. Теперь ваш файл становится.
Coken
34 3.00 5.00n
Spriten
18 2.89 4.30n
Fanta Mangon
21 3.35 5.99n
Orange Crushn
35 4.00 6.00n
Browns Cream Sodan
43 4.25 5.75n
После всего этого ваш код должен работать хорошо.
Последний совет. Я сам новичок, и со сканером не так просто работать, как кажется. Его nextInt() next() nextLine() и различные методы кажутся похожими, но это не так. Это может привести к ошибкам, которые трудно отлаживать. Попробуйте использовать BufferedReader.
43 4.25 5.75n
Надеюсь, я вам помог.
Комментарии:
1. Большое вам спасибо за ваш вклад, после прочтения вашего ответа это помогло мне лучше понять, как работает сканер, особенно при вводе / выводе текстовых файлов.
Ответ №2:
После последней строки retailCost[retailCost.length - 1] = in.nextDouble();
должен быть дополнительный in.nextLine();
Рассмотрим пример текстового файла ниже:
1234
word
Это было бы то же самое, что:
1234.56nword
где n обозначает символ новой строки. nextDouble() или любой другой метод сканирования, принимающий ввод числа, вернет следующий доступный номер. nextLine() возвращает все данные от текущей позиции до следующей строки.
рассмотрим этот код (где ‘in’ — это объект сканера с указанным выше текстовым файлом в качестве входного потока):
double a = sc.nextDouble(); //remaining input stream: nword
String b = sc.nextLine(); //remaining input stream: word
String c = sc.nextLine();
Как видно, во второй строке объект scanner немедленно встречает ‘ n’, который сигнализирует о конце строки. Таким образом, в конце выполнения значения:
a = 1234.56
b = ""
c = "word"