[자바프로그래밍] FileWriter를 while문에서 돌릴 때, 에러가 납니다.

조회수 3678회

안녕하세요. 자바를 배우고 있는 학생입니다. 학교 과제로 다이어리 프로그램을 만들고있는데요. 자바에서 FileWriter, FileReader 등 File클래스를 이용하여 일기나 스케줄을 메모장으로 저장하고, 저장된 메모장 내용을 읽기를 구현했는데, 스케줄이나 일기를 저장할 때 내용을 입력하고 엔터와 Ctrl + Z를 누르는 순간 NoSuchElementException에러가 납니다(첨부한사진).

어떻게 해결할 수 있을까요?? (자바 이클립스를 사용합니다.)

아래는 코드입니다.

/*DiaryMenu.java 메인메소드가 있는 클래스*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Scanner;
public class DiaryMenu{
    public static void main (String args[]) throws IOException{
        Scanner scanner = new Scanner(System.in);
        int choice =0;
        int choice2 =0;
        ScheduleAdd scheduleAdd = new ScheduleAdd();
        WriteDiary writeDiary = new WriteDiary();

        while (choice!=5) {
            System.out.print("(1) 스케줄 (2) 일기 (3) 학점 계산기 (4) 사용자 설정 (5) 종료 >>");
            choice = scanner.nextInt();

            switch (choice) {
            case 1:
                System.out.print("(1) 달력보기 (2) 스케줄 등록 (3) 스케줄 보기  >>");
                choice2 = scanner.nextInt();
                if (choice2 == 1) {
                    BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
                       System.out.print("년도를 입력하시오: " ); 
                       int year = Integer.parseInt(br.readLine()); 
                       System.out.print("월 입력하시오: " ); 
                       int month = Integer.parseInt(br.readLine()); 
                       Calender cal = new Calender(year, month); 
                       cal.Display();
                }

                if (choice2 == 2) {//스케줄 등록
                    scheduleAdd.scheduleAdd();
                }

                if (choice2 == 3) {//스케줄 보기
                }
                else {
                    System.out.print("잘못입력하셨습니다.");
                }

                break;
            case 2:
                System.out.print("(1)일기 쓰기 (2)일기 읽기 >>");
                choice2 = scanner.nextInt();

                if (choice2 == 1) {
                    writeDiary.addDiary();
                }

            }
        }
    }
}

/*ScheduleAdd.java (1) 스케줄 -> (2) 스케줄등록*/
import java.io.*;
import java.util.Scanner;

public class ScheduleAdd {
    InputStreamReader in = new InputStreamReader(System.in);
    FileWriter sch = null;
    String schedule_day = null;

    Scanner scanner = new Scanner(System.in);

    public void scheduleAdd () {
        System.out.print("스케줄 등록할 날짜 입력 (ex:160611) >>");
        schedule_day = scanner.nextLine();
        int c;
        //System.out.println();
        System.out.print("스케줄 내용 입력 후 엔터, ctrl+z>>");

        try {
            sch = new FileWriter("d:\\KNKDiary\\schedule\\"+schedule_day+".txt");

            while ((c=in.read())!= -1) {
                sch.write(c);
            }
            in.close();
            sch.close();
        }
        catch (IOException e) {
            System.out.println("입출력 오류");
        }
        System.out.println("저장되었습니다.");
    }
}

이미지

  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • 윈도우완경에서 콘솔에서 Ctrl+Z 를 입력하는 것은 EOF(End of File)을 애플리케이션에 보내는 것과 같습니다. (유닉스에서는 Ctrl+D)

    일반적으로 EOF는 파일의 끝임으로 InputStream에게는 더 이상 읽을 것이 없다는 의미가 됩니다.

    System.in 에서 EOF로 마킹되면 그 이후에는 모두 EOF만 읽게 되며, 더이상의 입력이 안되는 것으로 알고 있습니다.

    우선 에러 없이 종료하려면 다음과 같이 코드를 수정하면 될 것 같습니다.

    while (choice!=5) {
                System.out.print("(1) 스케줄 (2) 일기 (3) 학점 계산기 (4) 사용자 설정 (5) 종료 >>");
                if( scanner.hasNext() ) {
                    choice = scanner.nextInt();
                } else {
                    // 종료.
                    break;
                }
    

    수정답변:

    수정 예시: scheduleAdd 메서드

    다음과 같이 변경해보세요.

    private static String TERMINATE = "."; // 종료문자
    public void scheduleAdd() {
         System.out.print("스케줄 등록할 날짜 입력 (ex:160611) >>");
         schedule_day = scanner.nextLine();
         //System.out.println();
         System.out.print("스케줄 내용 입력 후 엔터, 종료하려면, 마지막줄에 마침표(.)만 입력하세요>>");}
    
         int lines = 0; // 팁: 한줄도 입력되지 않은 경우 삭제하기.
         Path path = Paths.get("d:\\KNKDiary\\schedule\\"+schedule_day+".txt");
         // 자바 NIO2 사용시 예,  java.nio.file.Path와 java.nio.file.Paths를 import 해야함.
         try(sch = new FileWriter(path.toFile())) {
            // Java7 이후부터 Autoclose를 지원합니다.
            // try 구문이 끝나면 자동으로 close합니다.
    
            while(scanner.hasNext()) {
                String line = scanner.nextLine();
                if( TERMINATE.equals(line) ) { // 현재 글자가 마침표이면.
                    sch.flush();
                    break;
                }
                lines++;
                sch.write(line);  // scanner로 line을 읽으면, 끝의 줄바꿈 문자가 제거됨.
                sch.write(System. lineSeparator()); // 줄바꿈. Java7 부터는 줄구분자는 System.lineSeparator() 을 사용하면 됩니다.            
            }
         } catch(IOException e) {
            System.out.println("입출력 오류");
         }
        if(lines == 0) { // 팁: 한줄도 입력하지 않은 경우, 취소 처리함.
            Files.delete(path); // 파일 삭제. java.nio.file.Files를 import 해야함.
            System.out.println("취소되었습니다.");
        } else {
            System.out.println("저장되었습니다.");
        }
    
    }
    
    
    • 지금 실행시켜보니 오류는 안뜨는데 ctrl z를 이용한 메뉴를 사용하면 프로그램 자체가 종료되어버리네요ㅠㅠ 정상적으로 계속 while문이 돌수있게 하는 방법은 없을까요?? 알 수 없는 사용자 2016.6.13 12:36
    • 음... 아마 순수하게 Java로 만으로는 안될 것 같습니다. Ctrl+Z(EOF)를 입력하면 System.in으로부터 아무 내용도 읽을 수 없습니다. 아마 스케줄 내용 입력 종료방식으로 마지막 라인에 "." 마침표 하나만 입력하는 식으로 바꾸지 않으면 힘들것 같에요. 허대영(소프트웨어융합대학) 2016.6.13 16:53
    • 답변 정말 감사합니다.ㅠㅠ 그렇다면 혹시 마지막라인에 마침표를 하나만 입력해서 저장하는 방법에 대해 설명해주실수있나요?? 많이 어려운가요??ㅠㅠ 알 수 없는 사용자 2016.6.13 18:18
    • 수정한 내용을 답변에 기록하였습니다. 참고하세요. 허대영(소프트웨어융합대학) 2016.6.13 18:43
    • 정말 감사드립니다. 답변한대로 바꿨더니 와일문이 안끊기네요ㅠㅠ 도움이 많이 되었습니다 감사합니다... 알 수 없는 사용자 2016.6.13 23:00

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)