스트림이란? (뇌를 자극하는 Java 프로그래밍 中)

  프로그래밍에서 말하는 스트림은 일차원적인 데이터의 흐름을 말합니다. 자바프로그램에서는 입력되고 출력되는 모든 데이터를 스트림 형태로 주고 받습니다. 스트림을 흘러가는 방향에 따라 프로그램으로 들어오는 스트림을 입력스트림, 프로그램에서 밖으로 나가는 스트림을 출력스트림이라고 합니다. 또 데이터 형태에 따라 문자로 구성된 스트림을 문자스트림, 사람이 알수있는 형태는 아니지만 프로그램에서 사용할 수 있는 데이터로 구성된 스트림을 바이트 스트림이라고 합니다.

 

java.io 패키지의 클래스 중
문자데이터 : FileReader, FileWriter
바이트데이터 : FileInputStream, FileOutputStream

 

poem.txt파일을 불러들여서 출력하는 프로그램 ReaderEx1.java

import java.io.*;

class ReaderEx1 {
	public static void main(String[] args) {
		FileReader reader = null; //finally블럭 안에서 reader를 실행하기 위해서 변수 선언, 초기값은 null
		try{ //파일을 여는 중 생길수 있는 에러에 대한 Exception 처리
		                reader = new FileReader("poem.txt");
		while(true){
			int data = reader.read(); //char를 읽는 값이 아스키코드값이기 때문에 int형으로 선언
			if(data==-1) break; //-1을 만나면 while문을 벗어남
			
			char ch = (char)data; //char형태로 형변환
			System.out.print(ch);
		}
		
		}
		catch(FileNotFoundException fnfe){ //파일을 찾을 수 없는 Exception
			System.out.println("파일을 찾을 수 없습니다.");
		}
		catch(IOException ioe){//기타 발생할 수 있는 IO Exception 처리
		}
		finally{
			try{
				reader.close();//오류의 유무의 상관없이 파일을 닫아줘야한다.
			}
			catch(Exception e){
				System.out.println("파일을 닫는 중에 오류가 발생했습니다.");
			}
				
		}
		
	}
}

 

poem.txt 파일은 java파일과 동일한 경로에 있어야 읽어올 수 있습니다.

Eclipse를 사용하는 경우에는 같은 프로젝트 내에 poem.txt파일이 있어야 읽어올 수 있습니다. 

 

while문안에서 if문으로 -1을 조건으로 둔 것은 FileReader클래스의 read()메소드의 특징 때문입니다.

이 메소드는 파일의 끝에 도달하여 더 이상 읽을 문자가 없으면 -1을 리턴합니다.

 

Java API

read
public int read() throws IOException 단일의 문자를 읽어들입니다.

오버라이드(override) : 클래스 Reader 내의 read
반환값 : 읽힌 문자. 스트림의 마지막에 이르렀을 경우는 -1
예외: IOException - 입출력 에러가 발생했을 경우

 

 

 

char arr[]=new char[100];
		int data=reader.read(arr);
		System.out.println(arr);

 

위의 While문을 이런 형태로 바꿔도 똑같이 출력할 수는 있습니다. 다만 미리 넉넉한 배열공간을 만들어야 가능합니다.

 

 

TEST Write!!를 output.txt에 저장하는 프로그램 WriterEx1.java

import java.io.*; class WriterEx1 { public static void main(String[] args) { FileWriter writer=null; try{ writer=new FileWriter("output.txt", true); //뒤에 true값을 추면 덮어쓰기가 아닌 추가형태의 파일쓰기가 실행됩니다. char arr[] = {'T','E','S','T',' ','W','r','i','t','e','!','!'}; for(int cnt=0;cnt<arr.length;cnt++){ writer.write(arr[cnt]); } } catch(IOException ioe){ System.out.println("파일로 출력할 수 없습니다."); } finally{ try{ writer.close(); }catch(Exception e){ } } } }

문자 형태이기 때문에 char로 선언한 배열에 값을 넣어서, for문으로 입력합니다.

FileWriter안에 true값 → txt파일을 덮어쓰는 형태로 파일을 쓰는 것이 아닌, 주어진 text를 추가하는 형태로 파일쓰기가 실행됩니다.

 

 

import java.io.*;
class OutputEx1 {
	public static void main(String[] args) {
		FileOutputStream out = null;
		try{
			out = new FileOutputStream("output1.dat");
			byte arr[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
			for(int cnt=0;cnt<arr.length;cnt++){
				out.write(arr[cnt]);
			}
		}catch(IOException ioe){
			
		}finally{
			try{
				out.close();
			}catch(Exception e){
				
			}
			
		}
	}

}

 

0부터 16까지의 숫자가 저장되어있는 byte 형태의 arr 배열을 선언 후 for문을 이용하여 입력합니다.

내용은 output1.dat에 저장합니다.

나머지 Exception 처리는 위의 내용과 동일합니다.

이 파일을 실행시키면, output1.dat이라는 파일이 생성됩니다.

이 파일은 텍스트 에디터로 봐도 깨진상태로 보이기 때문에 제대로 만들어졌는지는 다른방법으로 확인해보겠습니다.

output1.dat을 마우스 오른쪽 버튼 클릭후 속성을 클릭합니다.

 

 

0부터 16까지 총 17바이트의 내용이 저장된 것을 확인 할 수 있습니다.

 

 

만든 output1.dat파일을 읽어오는 프로그램 InputEx1.java

import java.io.*;
class InputEx1 {
	public static void main(String[] args) {
		FileInputStream in = null;
		try{
			in=new FileInputStream("output1.dat");
			byte arr[] = new byte[17]; //17크기의 배열 생성
			
			while(true){
				int num = in.read(arr);
				if(num==-1) break; //더이상 읽을 문자가 없으면 while문을 빠져나감
				for(int cnt=0;cnt<arr.length;cnt++){
					System.out.print(arr[cnt]);
					
				}
			}
		}catch(FileNotFoundException fnfe){
			System.out.println("파일을 찾을 수 없습니다.");
		}catch(IOException ioe){
			
		}
		finally{
			try{
				in.close();
			}catch(Exception e){
				
			}
			
		}
	}
}

 

배열의 크기를 17보다 크게 해도 상관은 없습니다.

배열공간을 20으로 해서 실행한 결과 동일한 결과값이 나왔고, 17개까지 배열에 저장 후 더이상 읽어올 문자가 없자 -1을 리턴합니다. if조건문에 의해서 while문을 빠져나가게 됩니다.

 

 

파일명을 입력해서 출력하는 프로그램 InputEx2.java

import java.io.*;
class InputEx2 {
	public static void main(String[] args) {
                  if(args.length<1){    // 입력받은 파라미터가 없을경우 에러메세지를 출력하는 조건문
			System.out.println("Have to input file name!");
			return;
		}
		FileInputStream in = null;
		try{
			in=new FileInputStream(args[0]);  // 입력받은 파라미터로 불러옴
			byte arr[] = new byte[5]; //5 byte 배열 선언
                                                //파일에서 5byte씩 끊어서 읽기 위한 작업
			while(true){
				int num = in.read(arr); //5byte를 읽어옴
				if(num==-1) break; //read메소드는 더이상 읽어올 문자가 없을 때 -1이 리턴됨. while문을 빠져나가는 조건문
				for(int cnt=0;cnt<num;cnt++){
					System.out.print(arr[cnt]);					
				}
			}
			
		}catch(FileNotFoundException fnfe){
			System.out.println("파일을 찾을 수 없습니다.");
		}catch(IOException ioe){
			
		}
		finally{
			try{
				in.close();
			}catch(Exception e){
				
			}
			
		}
	}
}

InputEx1파일과 다른점은, 입력받은 파라미터값으로 파일을 풀러와서 읽는다는 것 뿐입니다.

관련되서, 처음 if문은 입력된 파라미터 값이 없을 때 출력하는 에러메세지, 10라인의 args[0]은 첫번째 입력받는 파라미터 값입니다.