Development

[JAVA] 입출력스트림의 모든 것, 예제 - InputStream, OutputStream, InputStreamReader, OutputStreamWriter , BufferedReader, BufferedWriter, FIle, FileInputStream, FileOutputStream, FileReader, FileWriter 본문

Languages/JAVA

[JAVA] 입출력스트림의 모든 것, 예제 - InputStream, OutputStream, InputStreamReader, OutputStreamWriter , BufferedReader, BufferedWriter, FIle, FileInputStream, FileOutputStream, FileReader, FileWriter

yo~og 2021. 11. 11. 09:35
반응형

컴퓨터의 키보드, 파일, 네트워크 등으로 입력을 하여 컴퓨터의 메모리에 저장되면 콘솔, 파일, 네트워크 등을 통해 출력됩니다.

데이터들을 2진수로 이루어진 바이트로 전달됩니다.

이러한 입출력을 자바에서 실행시키기 위해서 Stream이 사용됩니다.


 

자바의 기본적인 데이터 입출력은 Java.io 패키지에서 제공합니다. 

InputStream / OutputStream - 바이트 단위 입출력을 위한 최상위 입출력 스트림 클래스
InputStreamReader / OutputStreamWriter - 문자 단위 입출력을 위한 하위 스트림 클래스
BufferedReader / BufferedWriter - 바이트 단위 입출력을 위한 하위 스트림 클래스
FileInputStream / FileOutputStream - 바이트 단위 입출력을 위한 스트림 클래스
FileReader / FileWriter - 문자 단위 입출력을 위한 하위 스트림 클래스

 

이때 바이트 단위는 그림, 문자 등 모든 종류의 데이터를 주고 받을 수 있고 문자 단위는 문자만 주고 받을 수 있습니다.

 


InputStream 예제

//키보드와 연결된 InputStream type 의 참조값을 kbd 라는 지역변수에 담기
//InputStream 객체는 1byte단위 처리 스트림이다.
//영문자 대소문자, 숫자, 특수문자만 처리할 수 있다.
//한글처리불가
InputStream kbd = System.in;
System.out.print("입력:");
try {
	//입력한 키의 코드값 읽어오기
	int code = kbd.read();
	System.out.println(code);
	//코드값에 대응되는 문자 얻어내기
	char ch = (char)code;
	System.out.println("char:"+ch);
} catch (IOException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}
System.out.println("main 메소드가 종료됩니다.");

InputStream 객체는 1byte 단위 처리 스트림입니다. 문자 중에서는 한글은 처리 불가하고 영문자, 대소문자, 숫자, 특수문자를 처리할 수 있습니다.

위 예제는 InputStream으로 문자 하나를 입력받아서 입력한 키의 코드값을 읽어오는 예제입니다. 

a를 입력받으면 .read() 를 사용하여 코드값을 읽어옵니다.


InputStreamReader 예제

package test.main;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class MainClass02 {
	public static void main(String[] args) {
		//1 byte 처리 스트림
		InputStream is = System.in;
		//2 byte 처리 스트림
		InputStreamReader isr = new InputStreamReader(is);
		try {
			System.out.println("입력:");
			//한글의 코드값도 읽어들일 수 있다.
			int code = isr.read();
			System.out.println("code:"+code);
			//코드값에 대응되는 문자 얻어내기
			char ch = (char)code;
			System.out.println("char:"+ch);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
}

 

InputStreamReader는 InputStream보다 향상된 처리 스트림이라고 보시면 됩니다.

InputStream과 달리 InputStreamReader은 2byte를 처리할 수 있기 때문에 한글도 처리가능합니다.

한글 처리 모습을 볼 수 있습니다.


BufferedReader 예제 1

package test.main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;

public class MainClass03 {
	public static void main(String[] args) {
		//1 byte 처리스트림
		InputStream is = System.in;
		//2 byte 처리
		InputStreamReader isr = new InputStreamReader(is);
		//좀더 기능이 향상된 Reader
		BufferedReader br = new BufferedReader(isr);
		
		try {
			System.out.println("문자열 한줄 입력:");
			//문자열 한줄 입력받기
			String line = br.readLine();
			System.out.println("입력한 문자열:"+line);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

BufferedReader는 좀더 기능이 향상된 Reader라고 보시면 될 것 같습니다.

BufferedReader은 문자열을 처리 할 수 있습니다.

문자열 처리가 된 모습을 볼 수 있습니다.


BufferedReader 예제 2

package test.main;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class MainClass11 {
	public static void main(String[] args) {
		File memoFile = new File("c:/developer/myFolder/memo.txt");
		try {
			if(!memoFile.exists()) {
				System.out.println("파일이 존재하지 않습니다.");
				return; //메소드 끝내기
			}
			//파일에서 문자열을 읽어들일 객체
			FileReader fr = new FileReader(memoFile);
			//BufferedReader 객체를 활용해서 작업해 보세요.
			BufferedReader br = new BufferedReader(fr);
			//무한 루프 돌면서
			while(true) {
				//문자열을 한줄씩 읽어들인다.
				String line = br.readLine(); // 줄단위로 읽어오면서 개행기호 빼고 읽어온것 println 해주어야함
				//더이상 읽을 데이터가 업다면
				if(line==null) break; // 반복문 탈출
				System.out.println(line);
			}

			
			
		}catch(IOException ie) {
			ie.printStackTrace();
		}
	}
}

파일의 존재여부를 확인후 파일이 존재하지 않으면 메소드를 끝냅니다.

FileReader로 파일에서 문자열을 읽어들일 객체를 생성후

BufferedReader을 사용하여 한줄씩 읽어오도록합니다.

무한루프를 돌면서 .readLine()을 사용하여 한줄씩 읽어옵니다.

 

 

Scanner scan = new Scanner(System.in);
String line = scan.nextLine();

위 예제는 scan.nextLine()을 사용한 것과 동일합니다.


OutputStream 예제

package test.main;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

public class MainClass04 {
   public static void main(String[] args) {
      //System 클래스의 out 이라는 static 필드에는 콘솔창에 출력할수 있는
      //PrintStream 객체의 참조값이 들어 있다.
      PrintStream ps=System.out;
      //학습을 위해서 PrintStream  객체를 부모 type OutputStream 으로 받아보기
      //OutputStream 도 1byte 처리 스트림이다.
      OutputStream os=ps;
      
      try {
         //출력은 .flush() 까지 호출해야 출력이 된다.
         os.write(97);
         os.write(98);
         os.write(99);
         //한글 '가' 의 unicode 값이 44032 인데 한글이 출력이 될까???
         //os.write(44032); OutputStream 은 한글 출력 불가
         os.flush(); //방출하기
      } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      
   }
}

PrintStream은 OutputStream의 자식입니다. 

.write()를 통해 전달된 아스키코드의 문자열을 출력합니다.


OutputStreamWriter 예제

package test.main;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;

public class MainClass05 {
   public static void main(String[] args) {
      //System 클래스의 out 이라는 static 필드에는 콘솔창에 출력할수 있는
      //PrintStream 객체의 참조값이 들어 있다.
      PrintStream ps=System.out;
      //학습을 위해서 PrintStream  객체를 부모 type OutputStream 으로 받아보기
      //OutputStream 도 1byte 처리 스트림이다.
      OutputStream os=ps;
      //2byte 처리 스트림
      OutputStreamWriter osw=new OutputStreamWriter(os);
      
      try {
         osw.write(44032);
         osw.write("오잉???");
         osw.flush();
      } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      
   }
}

OutputStreamWriter는 OutputStream보다 향상된 처리 스트림이라고 보시면 됩니다.

OutputStream과 달리 OutputStreamWriter은 2byte를 처리할 수 있기 때문에 한글도 처리가능합니다.

.write()로 출력할 수 있습니다.

참고로 44032는 가 입니다.

출력된 모습을 볼 수 있습니다.


BufferedWriter 예제

package test.main;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;

public class MainClass06 {
   public static void main(String[] args) {
      //System 클래스의 out 이라는 static 필드에는 콘솔창에 출력할수 있는
      //PrintStream 객체의 참조값이 들어 있다.
      PrintStream ps=System.out;
      //학습을 위해서 PrintStream  객체를 부모 type OutputStream 으로 받아보기
      //OutputStream 도 1byte 처리 스트림이다.
      OutputStream os=ps;
      //2byte 처리 스트림
      OutputStreamWriter osw=new OutputStreamWriter(os);
      
      BufferedWriter bw=new BufferedWriter(osw);
      
      try {
         bw.write("하나\n");
         bw.write("두울");
         bw.newLine();//개행기호를 출력해주는 메소드가 있다.
         bw.write("세엣");
         bw.flush();
         bw.close();
      } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      
   }
}

BufferedWriter은 개행기호를 처리해줍니다.

bw.write("하나\n") 이렇게 직접 개행기호를 삽입해도되고 bw.newLine()을 사용하여도됩니다.

bw.flush()는 버퍼에 잔류하는 모든 바이트를 출력하는 메소드입니다.

bw.close()는 사용한 시스템 자원을 반납하고 출력 스트림을 닫는 메소드입니다.

 

출력된 모습을 볼 수 있습니다.


File 예제 1 

package test.main;

import java.io.File;

public class MainClass07 {
	public static void main(String[] args) {
		//new File("새로 만들거나 제어하고 싶은 파일이나 폴더의 경로")
		File f = new File("c:/");
		String[] names = f.list();
		//배열에 있는 내용을 반복문 돌면서 콘솔창에 모두 출력할 수 있을까요?

		for(int i=0;i<names.length;i++) {
			String tmp = names[i];
			System.out.println(tmp);
		}
		System.out.println("확장 for 문을 이용하면");
		for(String tmp:names) {
			System.out.println(tmp);
		}
	}
}

File은 자신의 컴퓨터의 파일을 제어해줍니다.

예제는 c드라이브를 열어주고 .list()를 이용해서 파일 이름 정보를 names배열에 넣은 것 입니다.

출력결과


File 예제 2

package test.main;

import java.io.File;

public class MainClass08 {
	public static void main(String[] args) {
		File cDrive = new File("c:/");
		//c 드라이브에 각각의 폴도나 파일을 제어 할 수 있는 객체의 참조값을 배열로 얻어내기
		File[] files = cDrive.listFiles();
		for(File tmp:files) {
			//만일 디렉토리라면
			if(tmp.isDirectory()) {
				System.out.println("<DIR>\t"+tmp.getName());
			}else {
				System.out.println("     \t"+tmp.getName());
			}
		}
		
	}
}

new File("c:/")를 사용하여 c드라이브를 참조값으로 받고 .listFiles()를 사용하여 c드라이브에 각각의 폴더나 파일을 제어 할 수 있는 객체의 참조값을 배열로 얻어냈습니다.

만약 디렉토리면 앞에 <DIR>을 출력하게 해주었고 각각의 이름을 .getName()을 사용하여 출력해주었습니다.

 

 

출력결과


FileWriter 예제 

package test.main;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class MainClass09 {
   public static void main(String[] args) {
      //문자열을 저장할 파일을 만들기 위한 File 객체
      File memoFile=new File("c:/developer/myFolder/memo.txt");
      
      try {
         
         //파일이 이미 만들어 졌는지 여부
         boolean isExist=memoFile.exists();
         if(!isExist) {
            //파일을 만들어준다.
            memoFile.createNewFile();
            System.out.println("memo.txt 파일을 만들었습니다.");
         }
         //파일에 문자열을 출력할 수 있는 객체 생성
         FileWriter fw = new FileWriter(memoFile);
         fw.write("이00\n");
         fw.write("\t김00\n");
         fw.write("\t\t박00");
         fw.flush();//방출하기
         fw.close();//닫아주기(마무리)
         System.out.println("파일에 문자열을 저장했습니다.");
      }catch(IOException ie) {
         ie.printStackTrace();
      }
      
      
   }
}

new File("c:/developer/myFolder/memo.txt")에 설정한 경로의 참조값을 들고옵니다.

memoFile.exists()을 사용하여 파일이 이미 만들어졌는지 확인하고 파일이 없으면 memoFile.createNewFile()을 사용하여 파일을 만들어 줍니다. 

FileWriter 파일에 문자열을 출력할 수 있는 객체를 생성합니다.

.write()을 사용하여 파일에 문자열을 출력하고 flush를 사용하여 문자열을 방출하고 close를 사용하여 파일을 닫아줍니다.

메모장에 잘 출력된 것을 볼 수 있습니다.


FileReader 예제

package test.main;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class MainClass10 {
	public static void main(String[] args) {
		File memoFile = new File("c:/developer/myFolder/memo.txt");
		try {
			if(!memoFile.exists()) {
				System.out.println("파일이 존재하지 않습니다.");
				return; //메소드 끝내기
			}
			//파일에서 문자열을 읽어들일 객체
			FileReader fr = new FileReader(memoFile);
			//무한 루프 돌면서
			while(true) {
				//글자의 코드값을 하나씩 읽어온다.
				int code = fr.read();
				//더이상 읽을게 없다면 반복문 탈출
				if(code==-1) break;
				//코드값에 해당하는 char 값 얻어내기
				char ch = (char) code;
				//콘솔에 한글자씩 출력하기
				System.out.print((char)code);
				
			}
			
			
		}catch(IOException ie) {
			ie.printStackTrace();
		}
	}
}

FileReader는 파일에서 문자열을 읽어옵니다.

exists()을 사용하여 파일의 존재 여부를 확인후 존재하지 않으면 메소드를 끝냅니다.

FileReader 객체를 만듭니다.

무한 루프를 돌면서  .read()로 글자의 코드값을 하나씩 읽어옵니다.

code==-1이면 파일의 끝에 도달했다는 뜻이므로 반복문을 탈출합니다.

코드는 char로 캐스팅하여 콘솔에 한글자씩 출력해줍니다.


buffer 예제

package test.main;

import java.io.FileInputStream;
import java.io.FileOutputStream;

public class MainClass13 {
   public static void main(String[] args) {
      
      //필요한 객체의 참조값을 담을 지역 변수를 미리 만든다.
      FileInputStream fis=null;
      FileOutputStream fos=null;
      
      try {
         fis=new FileInputStream("c:/developer/myFolder/kim1.png");
         fos=new FileOutputStream("c:/developer/myFolder/kimgura.png");
         //byte 알갱이를 담을 배열 객체를 미리 생성한다.
         byte[] buffer=new byte[1024]; //한번에 1kilo byte 씩 읽어낼수 있다. 
         while(true) {
            /*
             *  .read() 메소드를 호출하면서 byte[] 객체의 참조값을 전달하면
             *  메소드안에서 읽은 byte 데이터가 배열에 자동 저장된다.
             *  또한 읽은 바이트의 갯수를 메소드가 리턴해준다. 
             */
            int readedByte=fis.read(buffer);
            //탈출조건???
            if(readedByte == -1)break;
            //읽은 만큼 파일에 출력하기
            // .write(배열, 시작 인덱스, 출력할 총 갯수)
            fos.write(buffer, 0, readedByte);
         }
         System.out.println("파일을 복사 했습니다.");
         
      }catch(Exception e) {
         e.printStackTrace();
      }finally {
         try {
            if(fis!=null)fis.close();
            if(fos!=null)fos.close();
         }catch(Exception e) {}
      }
      
   }
}

 

파일을 복사하는 예제입니다.

buffer는 한번에 원하는 바이트만큼씩 읽어낼 수 있습니다. 보통 1024만큼 읽어줍니다.

byte[] buffer=new byte[1024]를 사용하여 1024바이트씩 담을 수 있는 버퍼를 만들어줍니다.

무한루프를 돌면서 .read(buffer)을 사용하여 읽은 메세지는 버퍼에 저장됩니다. 반환값은 읽은 크기인데 무한루프가 n만큼 돈다면 1~n-1까지는 버퍼의 크기를 반환하지만 마지막은 1024보다 같거나 작은 남은 수를 반환합니다. 

if(readedByte == -1)break을 사용하여 파일의 끝에 도달했다면 멈춰줍니다.

fos.write(buffer, 0, readedByte)을 사용하여 버퍼에 있는 내용을 0부터 위에서 read(buffer)의 반환값인 읽은 크기만큼의 길이를 파일에 적어줍니다.

 

반응형
Comments