#java #while-loop #switch-statement #user-input #nosuchelementexception
Вопрос:
У меня проблема с моим университетским заданием.
Как запустить программу: введите 1, чтобы создать файл, затем запишите имя текстового файла и заполните его словами. После этого нажмите enter 2 раза, и вы получите мою проблему -> Исключение NoSuchElementException.
Я пытался решить эту проблему, создавая различные типы циклов или изменяя структуру проекта, но до сих пор не знаю, как это исправить. Я просто застрял и потратил некоторое время на эту проблему. Если бы кто-то более знающий мог мне помочь, это было бы замечательно.
Мой код все в одном классе:
import java.io.*;
import java.util.Scanner;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
showMenu();
}
static void showMenu() throws IOException {
menuOptions();
Scanner scan = new Scanner(System.in);
int userMenuInput = 0;
if (scan.hasNextLine()) {
try {
userMenuInput = Integer.parseInt(scan.nextLine());
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
while (true) {
switch (userMenuInput) {
case 1:
System.out.println("Create a file");
String userFileName = scan.nextLine();
createFile(userFileName ".txt");
break;
case 2:
System.out.println("Delete a file");
String userDeleteFile = scan.nextLine();
deleteFile(userDeleteFile);
break;
case 3:
System.out.println("Write to a file");
break;
case 4:
System.out.println("Exit from program");
System.exit(0);
break;
default:
System.out.println("Please type from 1 to 4!");
}
}
}
private static void createFile(String fileName){
System.out.println(System.getProperty("user.dir"));
File myFile = new File(System.getProperty("user.dir") "\" fileName);
try {
myFile.createNewFile();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
// Create PrintWriter to write to file
PrintWriter out = new PrintWriter(new FileWriter(myFile));
String s;
System.out.print("Enter text: ");
while ((s = in.readLine()) != null amp;amp; (s.length() != 0)) {
out.println(s);
}
in.close(); // Close reader from input
out.close(); // Close writer to file
} catch (IOException e) {
System.out.println("File writing failed!");
}
System.out.println(myFile.getAbsolutePath());
}
private static void deleteFile(String fileNameToDelete){
try{
System.out.println("Enter file name to delete: ");
File sourceFile = new File(fileNameToDelete ".txt");
sourceFile.delete();
}
catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
private static void menuOptions(){
System.out.println("Choose from these choices");
System.out.println("-------------------------n");
System.out.println("1 - Create file");
System.out.println("2 - Delete file");
System.out.println("3 - Write to file");
System.out.println("4 - Quit");
System.out.println();
}
}
Комментарии:
1. У тебя есть пара проблем. Во-первых, ваше приглашение находится вне цикла, поэтому у вас никогда не будет возможности изменить опцию. Во-вторых, в файле создания вы закрываете устройство чтения ввода. Обычно это было бы хорошей формой, но когда вы читаете из System.in, вы закрываете этот входной поток без возможности его повторного открытия. Тебе было бы лучше иметь одного System.in считыватель и повторное использование. Вам нужно сделать это консольным приложением? потому что было бы намного чище и проще писать как приложение с графическим интерфейсом.
2. Короче говоря, вы закрываетесь
System.in
, и вы никогда (до тех пор, пока JVM не завершится) не сможете снова читатьSystem.in
. Чтобы исправить: не закрывайтеSystem.in
.
Ответ №1:
чтобы добавить к ответу Ryans, исключение связано с тем фактом, что закрытие любого объекта, использующего поток ввода/вывода, на самом деле закрывает не этот объект, а весь поток ввода/вывода. Грязным решением было бы просто НЕ закрывать их. поэтому измените свой метод CreateFile с:
private static void createFile(String fileName){
System.out.println(System.getProperty("user.dir"));
File myFile = new File(System.getProperty("user.dir") "\" fileName);
try {
myFile.createNewFile();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
// Create PrintWriter to write to file
PrintWriter out = new PrintWriter(new FileWriter(myFile));
String s;
System.out.print("Enter text: ");
while ((s = in.readLine()) != null amp;amp; (s.length() != 0)) {
out.println(s);
}
in.close(); // Close reader from input
out.close(); // Close writer to file
} catch (IOException e) {
System.out.println("File writing failed!");
}
System.out.println(myFile.getAbsolutePath());
}
Для:
private static void createFile(String fileName){
System.out.println(System.getProperty("user.dir"));
File myFile = new File(System.getProperty("user.dir") "\" fileName);
try {
myFile.createNewFile();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
// Create PrintWriter to write to file
PrintWriter out = new PrintWriter(new FileWriter(myFile));
String s;
System.out.print("Enter text: ");
while ((s = in.readLine()) != null amp;amp; (s.length() != 0)) {
out.println(s);
}
//were close used to be
} catch (IOException e) {
System.out.println("File writing failed!");
}
System.out.println(myFile.getAbsolutePath());
}
Я буду настаивать на том, что это НЕ идеально. Вы должны сделать то, что сказал Райан, и сделать так, чтобы вы использовали только один System.in читатель. Делать это-твоя работа, а не моя. Но если это делается только для того, чтобы заставить что-то работать, чтобы вы могли отправить задание вовремя, это сработает.
Другая проблема заключается в том, что приглашение с запросом опции меню находится за пределами цикла while. Это означает, что он будет принимать только один вход, а затем застрянет в бесконечном цикле. Вы могли бы перенести это в цикл, но более чистая альтернатива состоит в том, чтобы поместить всю логику меню в метод меню, передать ссылку сканера этому методу и заставить его вернуть значение int для вашего переключателя. например:
Меню():
private static int menuOptions(Scanner scan){
System.out.println("Choose from these choices");
System.out.println("-------------------------n");
System.out.println("1 - Create file");
System.out.println("2 - Delete file");
System.out.println("3 - Write to file");
System.out.println("4 - Quit");
System.out.println();
if (scan.hasNextLine()) {
try {
return Integer.parseInt(scan.nextLine());
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
return 0;
}
Шоумену():
static void showMenu() throws IOException {
Scanner scan = new Scanner(System.in);
while (true) {
switch (menuOptions(scan)) {
case 1:
System.out.println("Create a file");
String userFileName = scan.nextLine();
createFile(userFileName ".txt");
break;
case 2:
System.out.println("Delete a file");
String userDeleteFile = scan.nextLine();
deleteFile(userDeleteFile);
break;
case 3:
System.out.println("Write to a file");
break;
case 4:
System.out.println("Exit from program");
System.exit(0);
break;
default:
System.out.println("Please type from 1 to 4!");
}
}
}
все эти изменения приводят к тому, что это окончательный код:
import java.io.*;
import java.util.Scanner;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
showMenu();
}
static void showMenu() throws IOException {
Scanner scan = new Scanner(System.in);
while (true) {
switch (menuOptions(scan)) {
case 1:
System.out.println("Create a file");
String userFileName = scan.nextLine();
createFile(userFileName ".txt");
break;
case 2:
System.out.println("Delete a file");
String userDeleteFile = scan.nextLine();
deleteFile(userDeleteFile);
break;
case 3:
System.out.println("Write to a file");
break;
case 4:
System.out.println("Exit from program");
System.exit(0);
break;
default:
System.out.println("Please type from 1 to 4!");
}
}
}
private static void createFile(String fileName){
System.out.println(System.getProperty("user.dir"));
File myFile = new File(System.getProperty("user.dir") "\" fileName);
try {
myFile.createNewFile();
BufferedReader in = new BufferedReader(new
InputStreamReader(System.in));
// Create PrintWriter to write to file
PrintWriter out = new PrintWriter(new FileWriter(myFile));
String s;
System.out.print("Enter text: ");
while ((s = in.readLine()) != null amp;amp; (s.length() != 0)) {
out.println(s);
}
//were close used to be
} catch (IOException e) {
System.out.println("File writing failed!");
}
System.out.println(myFile.getAbsolutePath());
}
private static void deleteFile(String fileNameToDelete){
try{
System.out.println("Enter file name to delete: ");
File sourceFile = new File(fileNameToDelete ".txt");
sourceFile.delete();
}
catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
private static int menuOptions(Scanner scan){
System.out.println("Choose from these choices");
System.out.println("-------------------------n");
System.out.println("1 - Create file");
System.out.println("2 - Delete file");
System.out.println("3 - Write to file");
System.out.println("4 - Quit");
System.out.println();
if (scan.hasNextLine()) {
try {
return Integer.parseInt(scan.nextLine());
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
return 0;
}
}
Не забудьте закрыть сканирование в своем методе выхода.