Java

입력과 출력

 

 

이전 시간에 메소드에서의 입력과 출력에 대해서 알아봤다. 이를 통해서 메소드가 좀 더 쓸모 있는 것이 될 수 있다는 것도 알게 되었을 것이다. 그럼 자바 에플리케이션도 입력과 출력을 할 수 있을까? 물론이다. 예를들어 사용자의 키보드, 마우스, 터치를 입력으로 받아들일 수 있고, 그에 따른 처리 결과를 모니터나 스피커등으로 출력 할 수 있다. 입력 값이 없는 에플리케이션은 입력 값이 없는 메소드처럼 똑같은 결과를 반복하는 것에 불과하다. 이번 시간에는 입력 값을 에플리케이션에 전달해서 좀 더 생동감있는 에플리케이션을 만들어보자.

 

String[] args

지금까지 미지의 영역으로 남겨두었던 Strings[] args의 의미를 파헤쳐 볼 시간이다. 아래 예제를 보자.

package org.opentutorials.javatutorials.io;

class InputDemo{
    public static void main(String[] args){
        System.out.println(args.length);
    }
}

아시다시피 main 메소드는 자바에서 특별한 의미를 가진 메소드다. main 메소드의 내용을 구현하면 자바 에플리케이션을 실행할 때 main 메소드가 호출되면서 프로그램이 구동하게 되는 것이다. 이 때 Strings[] args는 입력 값의 파라미터로 동작한다.

String[] args은 매개변수다. 매개변수는 메소드가 호출될 때 전달된 입력 값을 메소드 내부로 전달하는 역할을 하는 변수다. 이 변수의 데이터형은 String[]인데, String[]은 문자열을 담고 있는 배열이다. args.length는 배열의 길이를 의미한다. 이 점을 기억하고 위의 코드를 실행해보자.

javac InputDemo.java
java InputDemo 1 2 3 4 5 6;

결과는  6이다.

java InputDemo one two three;

결과는 3이다. 

이것을 통해서 추론 할 수 있는 것은 자바 에플리케이션 실행 명령인 java InputDemo 뒤에 따라오는 값의 숫자 만큼 변수 args에 어떤 값이 들어있다는 점이다.

그 값을 확인해보자.

class InputForeachDemo{
    public static void main(String[] args){
		for(String e : args){
			System.out.println(e);
		}
	}
}

위의 예제는 for-each 구문을 이용해서 변수 args에 담긴 값을 한줄씩 출력하고 있다.

즉 자바 에플리케이션에서는 메소드 main의 인자 String[] args를 통해서 사용자가 입력한 값을 전달하고 있다는 것을 알 수 있다.

조건문 수업에서 로그인 에플리케이션을 만든 것을 기억할 것이다. 해당 수업으로 다시 돌아가서 예제를 음미해보자. 더 많은 것이 보이지 않는가? 아는 만큼 더 많은 것이 보이는 것이 공부의 즐거움이 아닐까?

앱이 실행중에 입력 받기

이번에는 자바앱이 실행되고 있는 동안에 사용자의 입력을 받는 법을 알아보자. 자바에서 기본적으로 제공하는 라이브러리 중에 scanner을 이용하면 쉽게 사용자의 입력을 잡을 수 있다. 

안타깝게도 우리는 아직 라이브러리나 패키지와 같은 개념을 배우지 않았다. 아직은 이 로직을 샅샅이 이해하는 것은 무리이기 때문에 입력을 받는 방법에 대한 전체적인 흐름을 파악하는데 집중하자.
package org.opentutorials.javatutorials.io;

import java.util.Scanner;

public class ScannerDemo {

    public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int i = sc.nextInt();
		System.out.println(i*1000);
        sc.close();
	}

}

위의 예제를 실행하고 숫자를 입력하면 입력한 숫자의 1000배가 출력 될 것이다. 예제에서 우리가 주목해야 할 부분은 sc.nextInt()가 실행되면 자바는 사용자의 입력이 있을 때까지 변수 i에 값을 할당하지 않고 대기상태에 있게 된다. 키보드로 데이터를 입력하고 엔터를 누르면 비로서 i에 값이 담기고 i*1000을 통해서 입력값에 1000이 곱해지고 그 결과가 화면에 출력된다. 

아래의 코드는 연속적으로 값을 입력 할 수 있고, 입력한 값에 1000을 곱한 결과를 출력하는 예제다.

package org.opentutorials.javatutorials.io;

import java.util.Scanner;

public class Scanner2Demo {

    public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(sc.hasNextInt()) {
			System.out.println(sc.nextInt()*1000); 
		}
		sc.close();
	}

}

sc.hasNextInt()는 입력값이 생기기 전까지 실행을 유보시키는 역할을 한다. 만약 입력한 값이 int 형이 아닐 경우는 false를 리턴하고, int로 표현할 수 있는 형식의 숫자형인 경우는 true를 리턴한다. 따라서 위의 코드는 사용자가 입력을 할 때가지 실행을 기다렸다가 입력이 일어나면 반복문이 동작하면서 입력값의 1000배를 곱한 수가 출력된다. 

여러형태의 입출력

사용자의 키보드 제어만이 입력은 아니다. 아래 예제는 out.txt라는 파일을 입력 받아서 화면에 출력하는 예를 보여주고 있다. 예제를 실행하려면 프로젝트의 루트 디렉토리(src와 bin 디렉토리가 위치하고 있는 경로)로 이동해서 아래와 같이 명령을 실행한다. out.txt 파일이 존재해야 한다. 이에 대한 자세한 이야기는 동영상을 참고하자.

package org.opentutorials.javatutorials.io;

import java.util.Scanner;
import java.io.*;

public class Scanner3Demo {

    public static void main(String[] args) {
		try {
			File file = new File("out.txt");
			Scanner sc = new Scanner(file);
			while(sc.hasNextInt()) {
				System.out.println(sc.nextInt()*1000); 
			}
			sc.close();
		} catch(FileNotFoundException e){
			e.printStackTrace();
		}
		
	}

}

결과는 파일의 내용이 무엇인가에 따라서 달라질 것이다. 이 또한 분명한 입력값이다. 프로그램으로 유입되는 모든 정보는 입력값이다. 

GUI

물론 입력이나 출력이 꼭 텍스트여야 하는 것은 아니다. 아래 URL에 담겨있는 코드는 자바를 이용해서 그래픽컬한 사용자 조작 수단을 만드는 방법을 보여준다. 이 예제는 복잡하기 때문에 지금은 코드의 내용을 생각하지 말자.  

Java Tutorials Code Sample - DialogDemo.java

위의 코드의 실행결과는 아래와 같다.

 

직접 실행해보고 싶다면 아래 URL의 파일을 다운받아서 실행해보자. (Java Web Start가 필요하다)

다운로드

이클립스에서 입력 값 사용하기

파일을 선택하고 Run Configuration을 선택한다. Arguments 탭에서 Program Arguments에 입력 값을 작성하면 콘솔에서 입력 값을 전달하는 것처럼 할 수 있다. 텍스트 만으로는 이해하는데 어려움이 있을 것이다. 동영상 수업을 참고하자.

시즌1을 마치며

이렇게 해서 Java 수업 시즌 1이 끝났다. 시즌 2의 핵심은 객체지향(Object Oriented Programming)이다. 자바가 PHP나 JavaScript, Python과 같은 언어보다 어려운 이유는 객체지향 때문이라고 해도 과언이 아니다. 이들 언어도 자바와 유사한 객체지향 기능을 가지고 있다. 하지만 객체지향을 모르고도 프로그래밍이 충분히 가능하다. 반면에, 자바는 객체지향을 사실상 강제한다. 객체지향을 안 쓰고도 훌륭한 Python 프로그램을 만들 수 있지만, 객체지향을 모르고 좋은 Java 프로그램을 만들수는 없다. 바로 이런 이유 때문에 Java 입문에는 더 많은 시간과 인내와 노력이 필요한 것이다.

하지만 객체지향은 프로그래밍 역사상 가장 중요한 패러다임 중의 하나다. 그리고 이러한 패러다임은 한순간 툭 튀어나온 것이 아니다. 오랜 시간, 많은 사람에 의해서, 수많은 시행착오를 경유해서 도달한 웅장한 성취라고 할 수 있다. 이러한 성취에 다가선다는 것은 설레는 일이 아닐 수 없다. 이러한 성취를 시행착오 없이, 빠른 속도로 인계받을 수 있다는 것은 기쁜 일이 아닐까? 다만, 그 성취가 너무 거대해져서 그것 흡수하는 것만으로도 벅찬 것은 후대가 짊어져야 할 고충이기도 할 것이다. 그래서 우리에게 필요한 것은 시간이다. 사람에게는 어떤 일을 시작하기 전에 그 일을 완수하기 위한 시간을 배정하는 습관이 있는 것 같다. 그 시간을 너무 짧게 잡으면 그 시간을 다 사용했을 때 그 일을 포기하게 될 확률이 높다. 자바의 배열을 너무 작게 만들면 나중에 ArrayIndexOutOfBoundsException이 발생하는 것처럼 말이다. 필자가 부탁하고 싶은 것은 지금 생각하고 있는 것 보다 더 많은 시간을 이 일에 할당해 달라는 것이다. 당분간은 머릿속에서 수많은 개념들이 난리를 칠 것이다. 그리고 그 소동은 곧 잠잠해 질 것이다. 이것은 둘 중의 하나다. 잊어버렸거나, 완전히 내것이 되었거나.

 

댓글

댓글 본문
  1. 24.01.14 시즌1 완료
  2. 서달
    20230320
  3. coster97
    .
  4. wwwqiqi
    시즌1 완료
  5. 오뇽
    시즌1완료
  6. 혜봉
    9/18 완료
  7. Alan Turing
    09/17
  8. 하앙
    완료
  9. 너굴
    220807
  10. 치키티타
    220610
  11. 20220425
  12. 김은희
    20220410 완료
  13. 윤성호
    220408. 수강완료
  14. aesop0207
    220316. Wed
  15. 모찌말랑카우
    22.02.14 완료
  16. 행달
    22.02.04 완료
  17. 구니
    22.01.20 완료
  18. syh712
    2021-12-01
    1. 입력과 출력
    - IO= Input , Output


    2. 앱이 실행중에 데이터를 입력 1
    - Strings[] args는 입력 값의 파라미터로 동작

    3. 앱이 시작할 떄 데이터를 입력2
    - 자바 에플리케이션에서는 메소드 main의 인자 String[] args를 통해서 사용자가 입력한 값을 전달하고 있다

    4. 앱이 시작할 떄 데이터를 입력3
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int i = sc.nextInt();
    System.out.println(i*1000);
    sc.close();
    }

    5. 앱이 시작할 떄 데이터를 입력4
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    while(sc.hasNextInt()) {
    System.out.println(sc.nextInt()*1000);
    }
    sc.close();
    }
    => sc.hasNextInt()는 입력값이 생기기 전까지 실행을 유보시키는 역할
    입력한 값이 int 형이 아닐 경우는 false를 리턴하고,
    int로 표현할 수 있는 형식의 숫자형인 경우는 true를 리턴

    6. 여러 형태의 입출력
    - GUI vs CLI(커맨드 라인 인터페이스)


    7. 시즌1 종료
    - 절차적 P
    - 객체지향 P
    "시간을 너무 짧게 잡으면 그 시간을 다 사용했을 때 그 일을 포기하게 될 확률이 높다. 자바의 배열을 너무 작게 만들면 나중에 ArrayIndexOutOfBoundsException이 발생하는 것처럼 말이다."
    "필자가 부탁하고 싶은 것은 지금 생각하고 있는 것 보다 더 많은 시간을 이 일에 할당해 달라는 것이다."
  19. 드림보이
    2021.11.24. 입력과 출력 파트 수강완료
  20. IaaS
    - nextInt() 와 hasNextInt 차이 (정리)

    ---------nextInt()----------

    Scanner sc = new Scanner(System.in);
    int i = sc.nextInt(); // 입력한 int형 data를 읽고 i라는 변수에 저장한다.
    System.out.println(i*1000);
    sc.close();

    위와 같이 nextInt()를 사용한 코드를 짜면 하나의 데이터만 받고 프로그램이 종료된다.
    그래서 아래와 같이 코드를 변경해보았다.

    Scanner sc = new Scanner(System.in);
    int i = sc.nextInt();
    while(true){
    //while문은 트루라는 boolean값이 나와야지만 while문이 동작하기 때문에 while문 안에 true라는 값을 임의적으로 넣어주었다.
    System.out.println(i*100);
    }
    sc.close(); // Scanner를 통해 더 이상 입력 값을 받지 않는다는 의미

    이 코드에 대한 예상결과는 원하는 때에 데이터를 넣고 그 때 마다 출력을 해주는 것이었다.
    sc.close(); 에서 Unreachable code 오류 발생. 해석하자면 연결 할 수가 없는 코드라고한다.

    코드를 다시 수정

    Scanner sc = new Scanner(System.in);
    int i = sc.nextInt();
    sc.close();
    while(true){
    System.out.println(i*100);
    }

    디버깅 오류가 발생하지 않았다. 하지만 i(입력한 int형 데이터) * 100 만 무수히 콘솔화면에 출력된다.
    내가 원하는 결과값이 아니었다.

    이래서 사용하는게 hasNextInt() 메소드다.

    -----------hasNextInt()-----------

    Scanner sc = new Scanner(System.in);

    while(sc.hasNextInt()) {
    System.out.println(sc.nextInt()*100);

    }
    sc.close();

    nextInt()가 입력한 값을 무조건 반환이었다면.
    hasNextInt() 의 경우 입력한 값이 있는지 확인을 하고 입력한 값이 있다면 true라는 값을 반환한다.
    그렇기 때문에 while문의 조건으로 boolean값을 반환 해줄 수 있는 hasNextInt()라는 메소드를 사용할 수가 있다.

    그리고

    while(sc.hasNextInt()) {
    System.out.println(sc.nextInt()*100);
    }
    sc.close(); // nextInt()를 사용할 시에 항상 바로 아래 코드에 sc.close()문을 사용 해야했지만 이제는 sc.close()를 while문 아래에 작성을 하여도 디버깅 오류가 발생하지 않는다.

    결론 : 1. int i 라는 변수를 안 써도된다.
    2. while문의 조건으로 hasNextInt() 메소드를 사용 할 수가 있다.
    3. sc.close() 문이 while문 아래에 작성되어 있다.
    4. while의 조건으로 hasNextInt()라는 값을 넣었다면 System.out.println()에서는 nextInt()를 사용 해주어야 한다.
  21. IaaS
    2021-10-30 수강완료.

    -수강 노트-

    1. Scanner라는 클래스를 사용하는 방법은 ?
    = import java.util.Scanner

    2. Scanner sc = new Scanner(System.in)
    = System.in은 사용자가 표준입출력 장치로 입력을 하기위해 사용했다. (C언어의 표준입출력함수 scanf,
    getchar, gets와 비슷하다.) 그리고 sc라는 변수?에 그 값을 넣어준다.

    3. int i = sc.nextInt()
    = sc.nextInt()로 인해 이클립스 콘솔화면은 사용자가 정수형 데이터를 입력할때 까지 기다리고 입력한 값은 i라는 정수형 데이터 변수에 저장된다.

    -추측-
    4. sc.close()
    = 신기하게도 자바같은경우 입력자가 입력 값을 입력하면 일일이 이렇게 더 이상 입력 하지 않겠다는 특정한 메소드를 사용해야 되는 것 같다. 일종의 스트림 혹은 버퍼의 개념인 것 같은대 이것을 닫아준다는 의미로 추정된다.
  22. H4PPY
    1014
  23. 미NI언
    10.8 완료!
  24. 하성호
    210908
  25. 귀여운오징어
    저도 수현님과 같은 에러 나서 고쳤습니다.
    `https://comsperger.tistory.com/350` 이 사이트 보셔서 이클립스 설정을 바꿔보세요.
    이클립스 설정 바꾸니까 저는 잘 됩니다.
    참고로 자바버전은 cmd에 java -version치시면 나와요.
    아마 java compiler가 16으로 되어있을거예요. 저도 그랬거든요 ㅋㅋ
    보통 java compiler를 16에서 1.8로 바꾸면 해결됩니다!
    도움되셨기를 바랍니다.
    대화보기
    • 귀여운오징어
      java -cp bin org.opentutorials.javatutorials.io.InputDemo1
      java-cp 가 아니라 java -cp 입니다.
      뛰어쓰기 안하셔서 생긴 문제인거 같습니다.
      대화보기
      • 건우
        저는 아래처럼 오류가 뜨는데 이런 경우 어디서 잘못된건가요?
        C:\Users\keonw\eclipse-workspace\Java_tutorials>java-cp bin org.opentutorials.javatutorials.io.InputDemo1
        'java-cp'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는
        배치 파일이 아닙니다.
      • 베이스박
        210824학습했습니다. 감사합니다.
      • super1Nova
        210818
      • 이하영
        https://comsperger.tistory.com/350
        JDK 버젼이 이클립스와 맞지 않은 것 같네요.
        대화보기
        • 정수현
          잘 듣고 있습니다 ^^ 두번째 영상을 보고 따라 해봤는데
          Error: A JNI error has occurred, please check your installation and try again
          Exception in thread "main" java.lang.UnsupportedClassVersionError: test/input/InputDemo has been compiled by a more recent version of the Java Runtime (class file version 60.0), this version of the Java Runtime only recognizes class file versions up to 52.0

          다음과 같은 오류가 발생하네요.
          단순히 버전의 문제인가요?? 해결방법이 궁금합니다!
        • 개발꾸꾸
          5.13 개발갓..
        • 악어수장
          2021-5.12
        • 돌이크다
          멘탈까지 신경써준는 선생님이 얼마나 될까요 감동이에요
        • 코딩마스터꿈나무
          package javapractice;
          import java.util.Scanner;
          import java.io.BufferedWriter;
          import java.io.FileWriter;
          import java.io.IOException;
          import java.io.PrintWriter;


          public class File {
          public static void main(String args[])throws IOException{
          Scanner sc = new Scanner(System.in);
          Scanner sc1 = new Scanner(System.in);

          System.out.print("파일 이름를 입력해주세요:");
          String F = sc.next();
          System.out.print("암호를 설정할 IP를 입력하세요");
          String IPNUM = sc1.next();
          BufferedWriter bw = new BufferedWriter(new FileWriter("F",true));

          PrintWriter pw = new PrintWriter(bw,true);


          pw.write(IPNUM);
          pw.flush();
          pw.close();
          }
          }

          해당 부분에서 파일 경로를 제가 입력한 값의 경로로 설정을 하고 싶은데 뭐가 문제인가요?? 경로 설정에 대해 좀 알려주세요
        • 하연주
          210205 완료
        • 자바남
          자바남 수업완료. 마지막 영상은, 공부와 별개로 좋은 말이네요. 감사합니다
        • 김태현
          수업 2차완료
        • 정민규
          0819
        • 김보안
          System.out.println(args); 가 아닌,

          System.out.println(args.length); 를 적어주셔야 args의 길이를 출력합니다.
          대화보기
          • hvii
            20200810 학습완료
          • 태쩡이
            감사합니당!
          • yulrinam
            200807 시청완료 감사합니다 :)
          • EunSeok Kang
            잘봤습니다. 감사해요
          • 으헝
            첫번째 예제에서 java -cp bin 패키지명,파일명 하면 [Ljava.lang.String;@2ff4acd0 이렇게 뜨는데 왜그런지 아시나요?ㅠㅠ 뒤에 숫자를 붙여도 계속 똑같이 나오네요..흑흑
          • isz03072
            while문이 계속되는 이유는 조건이 계속 참이기 때문입니다.
            대화보기
            • login
              nextint가 무한반복으로 값이 나오는 게 아닌 밖에서 한번만 초기화되기에 nextint가 무엇인지 몰라 반환 준비를 하느라 값이 들어오기 전까지 while문 안에서 멈춰지는 게 아니어서입니다.
              대화보기
              • yuji
                2020-03-03 복습 완료

                예전에는 CLI로 썻다가 GUI로 쓰는 추세이고 File클래스를 이용해 파일명을 정의한 다음 Scanner 객체를 이용해 파일명에 적혀져있는 내용들을 꺼내와서 알맞은 데이터 형식이면 true를 리턴해주고 맞지않으면 false를 리턴해주는 역할을 한다.

                String[] args는 args.length와 같은 의미로 1,2,3으로 인자가 이루어져있으면 3이 최대이기 떄문에 3만 출력이된다.
              • 자짤이
                안녕하세요. 자바에 대한 짧은 지식을 가진 자짤이 입니다.

                제가 추론하기로는

                while(sc.hasNextInt()) 문이 종결 되는 조건이 없기 때문입니다.
                대화보기
                • 뉸뉸
                  안녕하세요 강의 감사합니다. 한가지 질문이있는데

                  package org.javatutorials.eclipse.io;

                  import java.util.Scanner;

                  public class Scanner2Demo {

                  public static void main(String[] args) {
                  Scanner sc = new Scanner(System.in);
                  int i = sc.nextInt();
                  while(sc.hasNextInt()) {
                  System.out.println(i*1000);
                  }
                  sc.close();

                  }

                  }

                  이렇게 sc,nextInt() 를 i 라는 변수로 선정하고 프로그램을 실행시켰을때는 왜 값을 반복해서 끝없이 출력하는지 궁금합니다.