• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

    • About
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Java 정리 27

19 Dec 2018

Reading time ~6 minutes

Java 정리 27 - IO Stream(1)


IO(Input/ Output) Stream

  • JVM 외부에 존재하는 데이터를 처리하기 위해 사용하는 클래스들
  • java.io 패키지에서 관련 클래스를 제공
  • 단방향 IO
    • 읽기 스트림은 읽기만, 쓰기 스트림은 쓰기만 가능
  • 8bit Stream, 16bit Stream 두가지 제공
    • 8bit Stream (byte기반 스트림)
      • 모든 데이터를 읽고 쓸 수 있음
    • 16bit Stream (문자열기반 스트림)
      • 문자열 데이터만 읽고 쓸 수 있음

01

  • 클래스 이름뒤에 Input,OutStream이면 8bit, Reader,Writer면 16bit Stream
  • Input, OutputStream을 부모로 두면 8bit Stream
    • DataInputStream / DataOutputStream
    • FileInputStream / FileOutputStream
    • ObjectInputStream / ObjectOutputStream
    • …
  • Reader, Writer를 부모로 두면 16bit Stream
    • BufferedReader / BufferedWriter
    • FileReader / FileWriter
    • InputStreamReader / OutputStreamWriter
    • …
  • 8bit Stream과 16bit Stream은 결합하여 사용할 수 있다.
    • 8bit와 16bit를 같이쓰면 속도가 보완이 된다.
    • 8bit Stream이 속도가 빠름
      • 데이터의 양은 적다.
    • 16bit Stream은 속도가 느림
      • 데이터의 양은 많다.

입력 Stream

02

  • JVM이 시작될 때 자동으로 표준 error OutputStream, 표준 input InputStream, out OutputStream 이 생성된다.
    • 이 표준 Stream을 close하면 JVM을 다시 실행할때까지 다시 Stream 연결을 못함
  • 키보드로 입력하면 메인보드 Keyboard Buffer에 값이 들어가짐
    • 버퍼의 크기는 256(0~255), 크기만큼 입력 가능
    • Enter가 떨어지면 Buffer 내용이 OS로 전달됨
      • cpu에 따라 입력순서를 그대로 처리하는 Little Endian, 입력순서를 거꾸로 처리하는 Big Endian 처리방식(RISC 계열 cpu(MAC계열) )이 존재.
      • 인텔계열 cpu는 Little Endian 방식
    • OS에 전달된 키입력 내용은 JVM의 System.in(InputStream)을 통해 JVM으로 들어오게 되고 JVM에 존재하는 instance는 InputStream의 read() 를 통해 해당 값을 읽어올 수 있다.

03


키보드 입력 처리

  • System.in
    • in은 InputStream
    • read()로 키보드로 입력된 내용을 읽어들일 수 있다.
// 입력 값 중 최초 입력 문자 받기
public class UseKeyboardInput {
     public UseKeyboardInput() {
          System.out.println("아무키나 누르고 엔터");
          try {
              int input = System.in.read();
              System.out.println("입력값 : " + input);

          } catch (IOException e) {
              e.printStackTrace();
          }
     }
     public static void main(String[] args) {
          new UseKeyboardInput();
     }
}

04

// 여러 단어 입력받기
public class UseKeyboardInput {
     public UseKeyboardInput() {
          System.out.println("아무키나 누르고 엔터");
          try {
              int input = 0;
              while(true) {
                   input = System.in.read();
                   
                   System.out.print((char)input);
                   
                   // enter는 13, 13나오면 종료
                   if (input == 13) {
                        break;
                   }
              }
          } catch (IOException e) {
              e.printStackTrace();
          }
     }
     public static void main(String[] args) {
          new UseKeyboardInput();
     }
}

05

06

  • 위에 입력을 찍어보면 윈도우는 엔터 입력 시 \r\n이 함께 입력됨
    • \r (Carriage Return) : 그 줄 맨 앞으로 이동
    • \n (Line Feed) : 다음 줄로 이동
  • 한글 입력받기
    • 한글을 입력받기위해선 8bit과 16bit Stream을 연결해야 한다.
      • 한글은 8bit Stream을 사용하면 깨짐, 16bit Stream은 안깨짐
      • 두 Stream의 크기가 달라 바로 연결 못함
        • 두 Stream을 연결하는 Stream이 필요

07

InputStream is = System.in;
InputStreamReader isr = new InputStreamReader(is); // has-a 
BufferedReader br = new BufferedReader(isr);       // is-a

08

  • InputStreamReader
    • 8bit-16bit Stream 결합
    • 읽어들인 charset을 변환(파라미터 2개받는 생성자 사용시)
  • BufferedReader
    • 속도개선
    • 줄단위로 읽는 기능(readLine())
// 한줄로 바꾼다면
BufferedReader br = new BufferedReader(
    new InputStreamReader(System.in));

try {
    // br의 readLine()을 사용하면 한줄 읽어서
    String s = br.readLine();
} catch (IOException ie) {
    ie.printStackTrace();
}

// 사용 후 연결을 끊어야 한다.
br.close();
public class UseKeyboardInput {
     public UseKeyboardInput() {
          System.out.println("아무키나 누르고 엔터");
          
          // 8bit Stream과 16bit Stream을 연결
          BufferedReader br = new BufferedReader(
                        new  InputStreamReader(System.in));
          
          try {
              // 16bit Stream을 사용하여 입력된 데이터를 줄단위로 읽어 들인다.
              String s = br.readLine();
              System.out.println(s);
              
              // 스트림 사용이 끝났으면 스트림의 연결을 끊는다.
              br.close();

          } catch (IOException ie) {
              ie.printStackTrace();
          }
     }
     public static void main(String[] args) {
          new UseKeyboardInput();
     }
}

09


File 입력 처리

  • FileInputStream
    • 8bit
    • 모든 형식의 파일을 읽어들일 수 있다.
      • 이미지, 동영상, 문서열
      • 파일을 복사할때 사용
        • 웹에서 파일 첨부
  • FileReader
    • 16bit
    • 독자 포맷으로 만들어지지 않은 문자열 파일만 읽어들일 수 있다.
      • txt (hwp, doc 등은 읽어들일 수 없다.)

파일시스템

  • FAT
    • File Allocation Table
    • 단일파일로 4GB까지만 저장됨
    • USB에 파일포맷이 이거면 4GB 이상 파일을 넣을 수 없음
  • NTFS
    • NTFS (New Technology File System)
    • FAT 파일 시스템을 개선하여 만든 새로운 파일 시스템
  • exFAT
    • Extended File Allocation Table

Character Set

  • EUC-KR
    • 한글 인코딩 방식 중 하나, 현재 산업 표준
    • 글자 코드 세트에 쓸 문자를 현대 한국어에서 빈도가 높은 한글을 추려내어 ‘가’부터 ‘힝’까지 배당한 후 문자를 기록하는 방식
    • 과거에 사용빈도가 많은 단어를 토대로 만듦
      • ‘아햏햏’같은 단어는 사용을 못함, ‘햏’이란 문자가 없기 때문에 사용을 못함.
    • 초기 MS Office가 EUC-KR기반이었다
      • 문서가 저장 안되는 문제가 발생
      • MS에서 해결하고자 만들어줌 MS949(CP949)
  • CP949 (code page 949)
    • MS Windows의 기본 코드 페이지
    • 한글 인코딩의 한 종류, EUC-KR의 확장형
  • UTF-8
    • 유니코드를 위한 가변 길이 문자열 인코딩 방식 중 하나
    • Universal Coded Character Set + Transformation Format - 8bit의 약자
    • 한글은 3byte로 표기

File

  • java.io 패키지에서 제공하는 클래스
  • File에 대한 정보를 얻는 일
  • Directory를 생성
  • File 삭제
// 생성
File file = new File("경로");

// 길이(크기)
long l = file.length(); // byte로 반환, 정수보다 큰 값을 반환가능하므로 long

// 파일인지 확인할 때
file.isFile();

// 폴더인지 확인할 때
file.isDirectory();

// 읽기 가능한지 확인할 때
file.canRead();

// 쓰기 가능한지 확인할 때 
file.canWrite();

// 실행 가능한지 확인할 때
file.canExecute();

// 숨김파일인지 확인할 때
file.isHidden();

// 폴더 내 모든 폴더/파일을 얻기
File[] f = file.listFiles();

// 파일 삭제
file.delete();

// 디렉토리 생성
file.mkdir();  // root부터 생성하는 디렉토리는 생성불가(과거에, 현재는 mkdirs와 동일)
file.mkdirs(); // 어느 경로의 디렉토리든 생성가능

// 파일의 마지막 수정날짜
long date = file.lastModified();

// 파일의 경로
String path = file.getPath();

// 파일의 파일명
String fName = file.getName();

// 파일의 절대경로(AbsolutePath)
String aPath = file.getAbsolutePath(); // Drive 레터가 소문자, 대문자 다 됨

// 파일의 규범경로(CanonicalPath), 파일에 접근하는 유일한 경로
String cPath = file.getCanonicalPath(); // Drive 레터가 대문자만 가능

// 파일이 존재
file.exists();

// 파일명 변경
file.renameTo(변경할이름);
// File method사용 예제
public class UseFile {
     public UseFile() {
          String path =  "c:/.../temp/java_read.txt";
          
          // 1. 생성
          File file = new File(path);
          System.out.println(file);
          
          if (file.exists()) { // 파일이 존재할 때
              System.out.println("절대 경로 :  "+file.getAbsolutePath());
              try {
                   System.out.println("규범 경로 :  "+file.getCanonicalPath());
              } catch (IOException e) {
                   e.printStackTrace();
              }
              System.out.println("경로 :  "+file.getPath());
              System.out.println("폴더명 :  "+file.getParent());
              System.out.println("파일명 :  "+file.getName());
              
               System.out.println(file.isFile()?"파일":"디렉토리");
               System.out.println(file.isDirectory()?"디렉토리":"파일");
              
              System.out.println("파일 길이 :  "+file.length()+" byte");
              System.out.println("실행  "+(file.canExecute()?"가능":"불가"));
              System.out.println("읽기  "+(file.canRead()?"가능":"불가"));
              System.out.println("쓰기  "+(file.canWrite()?"가능":"불가"));
              System.out.println(file.isHidden()?"숨긴파일":"일반파일");

              Date d = new Date(file.lastModified());
              SimpleDateFormat sdf = new  SimpleDateFormat("yyyy-MM-dd a HH:mm:ss");
              System.out.println("마지막 수정일 :  "+sdf.format(d));
              
          } else {
              System.out.println("경로를  확인해주세요.");
          }
     }
     public static void main(String[] args) {
          new UseFile();
     }
}

10

// File 생성, 삭제 예제
public class UseFile2 {
     
     public void createDirectory() {
          File file = new File("c:/young/oh");
          
          if (file.mkdir()) {
              System.out.println("폴더 생성 성공");
          } else {
              System.out.println("같은 이름의 폴더가  존재");
          }
     }
     
     public void removeFile() {
          File file = new  File("C:/.../temp/a.txt");
          boolean flag = file.delete();
          
          if (flag) {
              System.out.println("파일 삭제 성공");
          } else {
              System.out.println("파일 삭제 실패");
          }
     }
     
     public static void main(String[] args) {
          UseFile2 uf2 = new UseFile2();
          // uf2.createDirectory();
          uf2.removeFile();
     }
}

File 내용 읽기

11

  • File을 FileInputStream을 사용해서 read()로 1byte씩 읽어온다면 한글은 깨짐.
File f = new File(경로);
FileInputStream fis = new FileInputStream(f);

int i = 0;
while ((i = fis.read()) != -1) { // 읽어들인 내용이 있을 때까지 
    System.out.println(i);
}

숙제1

  • 프로그램이 실행되면 콘솔에 “디렉토리명 입력 : “ 메세지가 출력
  • 사용자가 콘솔에 디렉토리 “예) c:/dev”를 입력
    • 입력값이 디렉토리라면 해당 디렉토리내 파일정보를 JOptionPane.showMessageDialog에 출력
    • 디렉토리가 아니라면 “파일은 취급하지 않습니다.”를 콘솔에 출력

12

  • 숙제풀이1

숙제2

  • JOptionPane.showInputDialog를 사용하여 경로를 입력 받음
  • 입력받은 경로에 확장자가 java인 파일이 존재한다면 JOptionPane.showConfirmDialog를 사용하여 삭제여부를 묻는다.
    • ConfirmDialog의 메세지는 “java 파일이 x개 존재합니다. 삭제하시겠습니까?”
      • “예”를 누르면 해당 파일을 삭제
      • “아니오”나 “취소”가 눌려지면 종료
  • 숙제풀이2

13



Java