[JAVA] IO 스트림

msung99·2022년 5월 9일
0
post-thumbnail

스트림

  • 입력 스트림
    • 스트림 모듈, 스트림 객체라고도 부름.
  • 출력 스트림

스트림 종류

  • 바이트 기반 스트림

    • 자바에서는 유니코드까지 처리 가능하므로, 2바이트씩 들어오고 나간다.
    • 최상위 클래스 - 입력 스트림 : InputStream, 출력 스트림 : OutputStream
  • 문자 기반 스트림

    • 최상위 클래스 - 입력 스트림 : Reader, 출력 스트림 : Writer

    InputStream

  • 바이트 기반 입력 스트림의 최상위 클래스

  • 상속받은 하위 클래스 : FileInputStream / BufferedInputStream / DataInputStream

  • main 메소드 작성시 뒤에 throws Exception 을 붙여야함

    • 예외처리 관련된 내용인데, 시험에 안나오므로 설명 pass

주요 메소드

  • read()

    • 입력 스트림(파일)으로부터 1 바이트를 읽어오고 리턴
    • 파일의 끝인 경우 EOF(= -1) 을 리턴
    • 리턴타입 : int
  • read(byte[] b)

    • 입력 스트림(파일)로 부터 읽은 바이트들을 매개값으로 주어진 바이트 배열 b 에 저장
    • 한번 읽어올때 배열의 크기만큼 읽어옴
      (ex. 배열 크기가 3이면 3바이트만큼 읽어옴)
    • 리턴값 : 읽어온 바이트 수
  • read(byte[] b, int off, int len)

    • 파일로 부터 바이트를 len 개를 읽어와서 배열 b의 인덱스 off 부터 시작해서 길이 len 개만큼 저장
  • close()

    • 스트림을 닫음

read() 예시

import java.io.FileInputStream;
import java.io.InputStream;

public class ReadExample1{
  public static void main(String[] args) throws Exception{
    InputStream is = new FileInputStream("C:/Temp/test.txt")
    
    int readByte;
    while((readByte = is.read()) ! = -1)  // EOF 를 읽어오기 전까지 계속 파일에서 데이터를 읽어오고 출력 
      System.out.println((char)readByte); // read() 의 리턴타입이 int인데 이것을 char 타입으로 형변환해서 출력
    
    is.close();  // 마지막엔 객체 닫아줘야함
  }
}

read(byte[] b) 예시

InputStream is = new FileInputStream("C:/Temp/test.txt")

int readByteNo;
byte[] byte_array = new byte[3]; // 바이트 배열 만들고
String data = "";
while((readByteNo = is.read(byte_array)) != -1)  // 배열의 크기인 3바이트 만큼 읽어옴
   // 리턴값은 배열의 크기가 아니라, 내가 읽은 바이트 수가 리턴
   // 맨 마지막에 읽어올때는 만일 배열 크기(3) 보다 적은 수의 데이터가 있다면, 그만큼만 읽어옴
  data += new String(byte_array, 0, readByteNo); // byte_array 배열에 있는 내용을 0번 부터 readByteNo 크기 만큼 String 타입으로 바꿈
     // 즉, data 에 저장되는 값은 byte_array 배열에서 3바이트를 계속 읽어오고 저장할 것이다. 맨 마지막에는 상황에 따라 0~3 사이의 바이트가 저장됨
   
System.out.println(data);
is.close();

실행결과
pby 19909212

read(byte[] b, int off, int len) 예시

InputStream is = new FileInputStream("C:/Temp/test.txt")

int readByteNo;
byte[] byte_array = new byte[8]; 

// 파일로부터 바이트 3개를 읽어옴
readByteNo = is.read(byte_array, 2, 3); // byte_array 배열의 인덱스 2번 부터 기록하기(=읽어오는 내용을 저장하기) 시작

for(int i = 0; i < readBytes.length; i++)
  System.out.println((char)byte_array[i]));
  
is.close();

실행결과

p  // 2번 인덱스에 저장된 내용
b  // 3번 인덱스에 저장된 내용
y  // 4번 인덱스에 저장된 내용

OutputStream

  • 바이트 기반 출력 스트림의 최상위 클래스

  • 상속받은 하위 클래스 : FileOutputStream / PrintStream / BufferedOutputSream / DataOutputSream

주요 메소드

  • write(int b) : 출력 스트림(파일)에 1바이트를 쓴다

  • write(byte[] b) : 배열 b의 모든 내용을 출력 스트림(파일)에다 쓴다

  • write(byte[] b, int off, int len) : 배열 b 의 인덱스 off 부터 길이 len 만큼을 파일에 쓴다.

  • flush() : 버퍼에 잔류하는 모든 바이트를 출력

  • close() : 스트림을 닫는다


write() 예제

import java.io.FileOutputStream;
import java.io.OutputStream;

OutputStream s = new FileOutputStream("C:/Temp/test2.txt")

// 문자열 "dlwlrma" 라는 내용을 파일에 쓰고 싶은경우
// 1. 문자열의 각 원소를 바이트 단위로 변경해서 바이트 배열에 저장
// 2. 바이트 배열을 순회하며 write() 로 데이터를 1바이트씩 파일에 쓴다.

byte[] data = "dlwlrma".getBytes(); // 바이트 배열에다 문자열을 바이트 단위로 변경해서 넣음

for(int i = 0; i = data.length; i++){
  s.write(data[i]); // 파일에다 1바이트씩 바이트 배열의 내용을 쓴다
}

s.flush();
s.close();

예제2

OutputStream s = new FileOutputStream("C:/Temp/test2.txt")

byte[] data = "dlwlrma".getBytes(); // 바이트 배열에다 문자열을 바이트 단위로 변경해서 넣음

s.write(data);  // 배열 전체를 인자값으로 넣어서 파일에 한번에 쓴다

s.flush();
s.close();

예제3

OutputStream s = new FileOutputStream("C:/Temp/test2.txt")

byte[] data = "dlwlrma".getBytes(); // 바이트 배열에다 문자열을 바이트 단위로 변경해서 넣음

s.write(data, 1, 2);  // 바이트 배열 data의 인덱스 1부터 길이 2만큼의 내용을 파일에다 쓴다

s.flush();
s.close();

Reader

  • 문자 기반 입력 스트림의 최상위 클래스

  • 하위 클래스 : FileReader / BufferedReader / InputStreamReader

  • 앞서 알아본 InputStream 와 인자값이 char 인가, int 인가 차이 빼고는 똑같음

주요 메소드

  • read() : 문자 한개를 파일로부터 읽어오고 리턴

  • read(char[] cbuf) : char 배열 cbuf 에 읽어온 내용 저장후, 실제로 읽어온 문자 수를 리턴 ( OutputStream 과 마찬가지로 배열의 크기만큼 읽어옴)

  • read(char[], cbuf, int off, int len)

  • close()


예제1

import java.io.FileReader;
import java.io.Reader;

Reader reader = new FileReader("C:/Temp/test.txt")

int readData;
while((readData = reader.read()) != -1)
  System.out.println((char)readData);   // 문자 한개 읽어온거 출력
  
reader.close();

예제2

import java.io.FileReader;
import java.io.Reader;

Reader reader = new FileReader("C:/Temp/test.txt")

int readcharNo;
char[] cbuf = new char[2];  // char 배열을 만드는 것만 차이가 있지, 결국 똑같은 원리

String data = "";
while((readcharNo = reader.read(cbuf)) != -1)
  data += new String(cbuf, 0, readcharNo);
  
System.out.println(data);
reader.close();

예제3

import java.io.FileReader;
import java.io.Reader;

Reader reader = new FileReader("C:/Temp/test.txt")

int readcharNo;
char[] cbuf = new char[4];  

readcharNo = reader.read(cbuf, 1, 2);
for(int i = 0; i < cbuf.length; i++)
  System.out.println(cbuf[i]);

reader.close();

Writer

  • 문자 기반 출력 스트림 최상위 클래스

주요 메소드

  • write(int c) : 문자 하나 읽어옴
  • write(char[] cbuf) : OuputStream 과 char 배열 차이밖에 없다.
  • write(char[] cbuf, int off, int len)
  • write(String str) : String 타입을 넣어도 동작한다.
  • write(String str, int off, int len)
  • flush()
  • close()
Writer writer = new FileWriter("C:Temp/test3.txt");

char[] data = "dlwlrma".toCharArray();  // char 배열로 변환
for(int i=0; i<data.length; i++)
  writer.write(data[i]);    // 1바이트씩 파일에 쓰기

writer.flush();
writer.close();

예제2

char[] data = "dlwlrma".toCharArray();

writer.write(data, 1, 2);
writer.flush();
writer.close();

예제3

String data = "dlwlrma wook";

writer.write(data);  // String 객체를 write() 에 넣을 수 있다.

writer.flush();
writer.close();

System.in 필드

콘솔에서 값을 읽어오려면 System.in 을 활용하면 되고, 이것은 Inputstream 타입 변수에 할당해서 사용한다.
ex. InputStream is = System.in;

  • system.in 은 Inputstream 데이터 타입이다.

  • Inputstream 타입이므로, 바이트 단위로 읽어옴.
    읽은 바이트는 키보드각 문자에 대응하는 아스키 코드 문자값을 가져옴

Inputstream i = System.in; // Inputstream 객체를 만들고 System.in 필드를 연결시켜줌

// 콘솔에서 입력을 받아오는 기능을 해주는 System.in 이라는 녀석을 
// Inputstream 타입으로 받았기 때문에 Inputstream 있는 메소드를  다 이용 가능하다. 


char inputChar = (char)i.read()  // 1바이트 읽어온 것을 char 타입을 변환해서 변수에 저장

swtich(inputChar){
  case '1':
    System.out.println("예금 조회를 선택하셨습니다.")
    break;
  case '2':
    System.out.println("예금 출금을 선택하셨습니다.")
    break;
}

예제2

InputStream i = System.in;

byte[] datas = new byte[100];

System.out.print("이름:");
int nameBytes = is.read(datas);   // 콘솔에서 읽어온 내용을 배열 datas에 저장 
String name = new String(datas, 0, nameBytes-2);  // nameBytes 에서 읽어들인 거에서 2바이트를 빼고 문자열로 변환 => 엔터키를 제외하기 위함

System.out.print("하고 싶은말:");
int commentBytes = is.read(datas);
String comment = new String(datas, 0, commentBytes-2);

System.out.println("입력한 이름:" + name);
System.out.println("입력한 하고 싶은말:" + comment);

System.out

  • 반대로 콘솔에다 내용을 쓰고 싶다면 System.out 을 활용

  • PrintStream ( OutputStream 의 하위클래스 ) 의 데이터 타입이다.

    • 즉, OutputStream 으로 받아와도 상관x
  • OutputStream 변수에 System.out 을 할당시키면 된다.
    ex. OutputStream s = System.out

  • OutputStream 의 메소드 (ex. write() ) 를 사용해서 파일에 콘솔의 내용을 쓴다.

OutputStream s = System.out;

// 출력하는(쓰는) 내용들을 보면 다 숫자이다.
// System.out 은 아스키값을 출력하면 문자가 출력된다.
// 즉, 숫자(아스키코드)에 대응하는 문자가 파일에 출력된다.

for(byte b = 48; b < 58; b++)
  s.write(b);
  
s.write(10);

for(byte b=97; b<123; b++)
  s.write(b);
  
s.write(10);

String hangul = "가나다라마바사아자차카타파하";
byte[] hangulBytes = hangul.getBytes();

s.write(hangulBytes);

s.flush();

Scanner 클래스

  • 콘솔로부터 기본 타입의 값을 바로 읽을 수 있다!

  • System.in 을 사용해서 1바이트씩 값을 가져오는 것은 불편한다.

  • 콘솔 창에서 데이터 값을 가져올때 애초에 데이터 타입에 맞게끔 가져오고 싶다면, Scanner 클래스를 활용하자.

Scanner scan1 = new Scanner(System.in);

메소드

nextBoolean() : boolean 값을 읽는다
nextByte() : byte 값을 읽는다
nextShort()
nextInt()
nextLong()
nextFloat()
nextDouble()
nextLine()

  • 다음 입력을 받을떄, 이 데이터 타입에 맞게 입력을 받는다.

  • nextInt() 를 활용했다면,
    콘솔을 이용해서 5 라는 정수를 입력했다면 그 정수에 해당하는 4바이트가 있을 것인데, 이를 1바이트씩 잘라서 가져온다
    ( 애초에 Scanner 도 System.in 을 활용하므로 )

    • 1바이트씩 자른 것들을 내부적으로 묶어서 int 타입으로 바꿔서 리턴하는 것이다.
  • 내가 지정한 메소드 (ex. nextInt() ) 에서 리턴해주는 타입에 맞춰서 내부적으로 처리를 해줘서 리턴해준다.


File 클래스

  • 파일의 정보, 또는 디렉토리의 정보를 저장할 수 있는 객체

  • 해당 경로에 대한 파일에 대해 읽고, 쓰는 작업은 못하지만 해당 경로에 있는 파일(또는 디렉토리) 에 대한 정보를 얻어올 수 있다.

File file1 = new File("C:\\temp\\file.txt");

메소드

  • exists() : 파일 객체에 지정해준 경로가 실제로 존재하는지를 판단

  • mkdirs() : 새 디렉토리를 생성

  • createNewFile() : 새로운 파일을 생성

  • getName() : 파일의 이름을 리턴.

    • 파일에는 전체 경로가 있을텐데, 앞의 경로 부분을 다 짤라버리고 현재 디렉토리 기준으로 그냥 파일 이름만 리턴
      ex) "C:\temp\file.txt" 에서 "file.txt" 을 리턴
  • getPath() : 전체 경로를 리턴
    ex) "C:\temp\file.txt" 를 리턴

  • isDirectory() : 디렉토리인지 여부를 리턴

  • isFile() : 파일인지 여부를 리턴

  • list() : 디렉토리에 포함된 파일 과 디렉토리 목록 전부를 String 배열로 리턴

    • A 라는 폴더안에 B,C 폴더와 D,E 파일에 있는 경우 이게 폴더인지 파일인지 구분하지 않고 이 4개에 대한 정보를 모두 리턴
  • listFiles() : list() 와 유사. But 차이점은 리턴 결과가 각각의 결과를 각각을 다 File 객체화 시켜서 File 객체 배열로 넘겨준다.

profile
블로그 이전 : https://haon.blog

0개의 댓글