티스토리 뷰

728x90
반응형

Input과 Output은 메모리를 기준으로, 메모리에서 읽어들이는 것을 input, 메모리에서 빠져나가는 것을 Output이라 한다.

데이터는 0101...의 이진수로 구성되어있다.

8bit는 1byte이고, 메모리는 이 바이트 단위로 파일의 데이터를 읽거나 출력한다.

입출력은 키보드, 파일 등 다양한 곳에서 이루어진다.

 

한글은 한글자가 2byte이다. 1byte 문자를 처리한다 가정하면, 숫자, 영문자, 특수문자만 처리 가능하다.

 

이번 게시물에서는 파일의 데이터를 메모리에서 byte 단위로 처리하는 과정에 대해 다뤄볼 예정이다.

 

 

예를 들어, 사용자가 파일을 네트워크로 보낼 때의 데이터의 흐름은 다음과 같다.

파일을 전달받은 사용자는 네트워크에서 파일을 받아, 새로운 파일을 생성한다.

 

예제를 통해 살펴보자.


"특정 파일을 byte 단위로 읽고 새로운 파일에 출력하기"

예제 1

 

1. FileInputStream으로 파일에서 byte 알갱이를 읽어들일 수 있는 객체 생성하기

(마이폴더의 kim1.png를 읽을 예정)

FileInputStream fis = new FileInputStream("c:/developer/myFolder/kim1.png");

 

예외가 발생하여 try-catch문을 작성한다.

try{
	FileInputStream fis = new FileInputStream("c:/developer/myFolder/kim1.png");
}catch(FileNotFoundException e){
	e.printStackTrace();
}

2. FileOutputStream으로 try-catch문 안에 파일에서 byte 알갱이를 출력할 수 있는 객체 생성하기

(마이폴더의 copied.png에 출력할 예정)

FileOutputStream fos = new FileOutputStream("c:/developer/myFolder/copied.png");

3-1. try-catch문에 파일에서 read()로 읽고, 읽은 데이터 파일에 write()로 출력하기

try{	
	//바이트를 10진수로 변환하여 data에 넣어주고, 읽을 byte가 없다면 -1 반환
	int data = fis.read();
	fos.write(data);
}catch(FileNotFoundException e){
	e.printStackTrace();
}catch(IOException e){
	e.printStackTrace();
}

 

.read() 메소드는 정수를 반환하는데, InputStream으로부터 byte 단위 데이터를 읽어들여 10진수로 변환하여 반환하고, 더 이상 읽을 byte가 없다면 -1을 반환한다.

read() 메소드 역시 IOException에 대해 예외처리를 해주어야 한다.


3-2. 반복문 돌며 byte 읽고 파일에 출력하고 fis와 fos 닫아주기

try{  
  while(true) {
      //파일에서 읽어들이기
      int data = fis.read();
      //만일 더이상 읽을 데이터가 없다면
      if(data ==-1) break;//반복문 탈출
      System.out.println("data: "+data);
      //읽은 데이터를 파일에 출력하기
      fos.write(data);
  }
  fis.close();
  fos.close();
}catch(FileNotFoundException e){
	e.printStackTrace();
}catch(IOException e){
	e.printStackTrace();
}

 


전체 코드 

MainClass01.java

package test.main;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class MainClass01 {
	public static void main(String[] args) {
		
		
		try {
			int count = 0;
			//파일에서 byte 알갱이를 읽어들일 수 있는 객체 생성
			FileInputStream fis = new FileInputStream("c:/developer/myFolder/kim1.png");
			//파일에서 byte 알갱이를 출력할 수 있는 객체 생성
			FileOutputStream fos = new FileOutputStream("c:/developer/myFolder/copied.png");
			//반복문 돌면서 byte를 읽어들인다.
			while(true) {
				//파일에서 읽어들이기
				int data = fis.read();
				//만일 더이상 읽을 데이터가 없다면
				if(data ==-1) break;//반복문 탈출
				count++;
				System.out.println("count:"+count+" data: "+data);
				//읽은 데이터를 파일에 출력하기
				fos.write(data);
				
			}
			fis.close();
			fos.close();
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}

"특정 파일이나 폴더를 제어, 생성할 파일 객체 생성하기"

".list() 메소드로 파일/폴더 이름 출력하기" 

 

 

※특정 파일이나 폴더를 제어, 혹은 생성하고 싶다면 해당 파일 혹은 폴더를 제어, 생성할 파일 객체를 생성해야 한다.

new File("새로 만들거나 제어하고 싶은 파일이나 폴더의 경로")

 

예제 2

C드라이브의 목록을 출력해보자.


 

1. C 드라이브에 관한 작업을 수행할 수 있는 할 파일 객체 생성하기

File f = new File("c:/");

 

2. C 드라이브 내의 디렉토리, 파일들을 String 배열 객체에 저장하기 

String [] names = f.list();

 

3. 배열에 있는 내용을 반복문 돌며 콘솔창에 모두 출력하기

for(String tmp:names) {
	System.out.println(tmp);
}
try {
	f.createNewFile();
} catch (IOException e) {
	e.printStackTrace();
}

전체 코드

MainClass07.java

package test.main;

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

public class MainClass07 {
	public static void main(String[] args) {
		//new File("새로 만들거나 제어하고 싶은 파일이나 폴더의 경로")
		File f = new File("c:/");
		String [] names = f.list();
		//배열에 있는 내용을 반복문 돌면서 콘솔창에 모두 출력하기
		for(String tmp:names) {
			System.out.println(tmp);
		}
		try {
			f.createNewFile();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

"listFiles() 메소드로 각각의 파일/폴더를 제어할 수 있는 객체의 참조값 얻어내기"

 

예제 3

 

C드라이브 내의 파일과 디렉토리에 대하여, 디렉토리이면 "<DIR> 디렉토리명"을 출력하고, 파일이면 "파일명"을 출력하도록 프로그래밍 해보자.

 

 

1. C드라이브에 관한 작업을 수행할 수 있는 파일 객체 생성하기

File cDrive = new File("c:/");

 

2. C드라이브에 각각의 폴더나 파일을 제어할 수 있는 객체의 참조값을 배열로 얻어내기

File[] files = cDrive.listFiles();

 

3. 반복문 돌며 디렉토리이면 "<DIR> 디렉토리명"을 출력하고, 파일이면 "파일명"을 출력하기

for(File tmp:files) {
	if(tmp.isDirectory()) {//만일 디렉토리라면 <DIR> 출력
		System.out.println("<DIR>\t"+tmp.getName());
	}
	else {
		System.out.println("\t"+tmp.getName());
	}
}

전체 코드

MainClass08.java

package test.main;

import java.io.File;

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

"특정 위치에 파일 생성하고 FileWriter를 이용해 해당 파일에 문자열 쓰기" 

 

예제 4

memo 텍스트 파일을 myFolder에 생성하고, 다음의 문자열을 memo 파일에 써보자.

 

 

1. 문자열을 저장할 파일을 만들기 위한 File 객체 생성하기

File memoFile = new File("C:/developer/myFolder/memo.txt.");

2. 파일이 이미 존재하는지 존재 여부를 확인하고 파일이 없다면 파일 만들어주기 

//파일이 이미 만들어졌는지 여부
boolean isExist = memoFile.exists();
if(!isExist) {
	//파일이 없으면 파일 만들어주기
	memoFile.createNewFile();
	System.out.println("memo.txt 파일을 만들었습니다.");
}

.exists( ) 메소드는 파일의 존재 여부를 확인하고 boolean 타입을 리턴한다.

createNewFile( ) 메소드는 해당 경로에 파일명으로 빈 파일을 생성한다. 


3. 파일에 문자열을 출력할 수 있는 객체 생성하고 문자열 쓰기

FileWriter fw = new FileWriter(memoFile);
fw.write("김구라\n");
fw.write("\t해골\n");
fw.write("\t\t원숭이");
fw.flush();//방출하기 
fw.close();//닫아주기(마무리)
System.out.println("파일에 문자열을 저장했습니다.");

 

flush( )로 방출하고 close( )를 해주어야 한다.

FileWriter( ) 객체는 파일 타입의 객체의 참조값을 넘겨받는다.

FileWriter( )의 write( ) 메소드로 문자열을 파일에 쓸 수 있다.


전체 코드

MainClass09.java

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("김구라\n");
			fw.write("\t해골\n");
			fw.write("\t\t원숭이");
			fw.flush();//방출하기 
			fw.close();//닫아주기(마무리)
			System.out.println("파일에 문자열을 저장했습니다.");
		}catch (IOException ie) {
				ie.printStackTrace();
		}
			
	}

}

"FileReader를 이용해 텍스트 파일의 문자열을 한글자씩 읽고 콘솔에 출력하기"

예제 5

memo 텍스트 파일의 내용을 한 글자씩 읽어 콘솔에 출력해보자.

 

MainClass10.java

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(ch);
				
			}
			
		} catch(IOException ie) {
			ie.printStackTrace();
		}
	}

}

 

FileReader의 read( ) 메소드는 한 글자씩 읽어온다.

code는 읽어온 한 글자의 byte를 10진수로 변환한 값이다.

만약 더이상 글자가 없다면 read( ) 메소드는 -1을 반환한다.

따라서, while( )문을 사용하여 -1일 때 break;를 해주었다.


"BufferedReader을 이용하여 문자열을 한 줄씩 읽어오기"

 

예제 6

memo 텍스트 파일에 저장된 문자열을 한 줄씩 읽어보자.

 

MainClass11.java

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);
			//BufferedTeader 객체를 활용해서 작업해보세요.
			BufferedReader br = new BufferedReader(fr);
			//무한루프 돌면서
			while(true) {
				//문자열을 한 줄씩 읽어들인다.
				String line = br.readLine();
				//더이상 읽을 데이터가 없다면 반복문 탈출
				if(line==null) break;
				//콘솔에 한 줄씩 출력하기 
				System.out.println(line);
				
			}
			
		} catch(IOException ie) {
			ie.printStackTrace();
		}
	}

}

 

BufferedReader의 readLine() 메소드는 문자열을 한 줄씩 읽어들인다.

더 이상 읽을 데이터가 없다면, 즉 null이라면 반복문을 탈출한다.


"close( ) 시 발생할 수 있는 예외처리 (null)"

예제 7

 

close()를 try문에서 실행하면 에러 발생 시 제대로 close()가 되지 않으므로 finally 문에서 실행해야 한다.

finally {//예외 발생과 관계없이 반드시 실행이 보장되는 블럭
	//마무리 작업을 한다. (보통 열었던 스트림 객체를 닫는 작업을 한다.)
	try {
		//fr이나 br이 NullPointerException 발생하면 close() 안되므로 예외발생
		if(fr!=null) {
			fr.close();
		}
		if(br!=null) {
			br.close();
		}
						
	} catch (IOException e) {
		e.printStackTrace();
	}
}

 

닫고자 하는 fr 혹은 br이 null이면 NullPointerException이 발생하므로 close()가 되지 않는다.

따라서, null이 아닐 경우 close( )가 실행되도록 코드를 작성해야 한다.


전체 코드

MainClass12.java

package test.main;

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

public class MainClass12 {
	public static void main(String[] args) {
		File memoFile = new File("c:/developer/myFolder/memo.txt");
		//필요한 객체의 참조값을 담을 변수를 미리 만들어준다.
		FileReader fr=null;
		BufferedReader br=null;
		try {
			if(!memoFile.exists()) {
				System.out.println("파일이 존재하지 않습니다.");
				return;//메소드 끝내기 
			}
			//객체의 참조값을 얻어내서 미리 만들어둔 변수에 대입한다. 
			fr = new FileReader(memoFile);
			br = new BufferedReader(fr); //BufferedTeader 객체를 활용해서 작업해보기
			
			//무한루프 돌면서
			while(true) {
				//문자열을 한 줄씩 읽어들인다.
				String line = br.readLine();
				//더이상 읽을 데이터가 없다면 
				if(line==null) break;//반복문 탈출
				//콘솔에 한 줄씩 출력하기 
				System.out.println(line);
				
			}
			
		}catch(IOException ie) {
			ie.printStackTrace();
		}finally {//예외 발생과 관계없이 반드시 실행이 보장되는 블럭
			//마무리 작업을 한다. (보통 열었던 스트림 객체를 닫는 작업을 한다)
			try {
				//fr이나 br이 NullPointerException 발생하면 close() 안되므로 예외발생
				if(fr!=null) {
					fr.close();
				}
				if(br!=null) {
					br.close();
				}
						
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}

 


"여러 바이트씩 읽고 출력하기" 

 

예제 8

kim1 이미지를 복사해서 kimgura라는 이름의 파일로 붙여넣어보자.

 

while문 안에서 실행한다. 

 

1. FileInputStream과 FileOutputStream 객체 생성하기

fis = new FileInputStream("c:/developer/myFolder/kim1.png");
fos = new FileOutputStream("c:/developer/myFolder/kimgura.png");

2. byte 알갱이를 담을 객체 미리 생성하기 (방의 크기를 적당히 해야 메모리를 너무 많이 차지하지 않음)

byte[] buffer = new byte[1024];//메모리를 너무 많이 차지 하지 않도록 배열 크기를 적절하게 지정

3. read( ) 메소드로 buffer의 크기만큼의 byte씩 읽어들이고 변수 readedByte에 참조값 담기

int readedByte = fis.read(buffer);

4. 더 이상 읽어들일 것이 없으면(-1)이면 while문 탈출

if(readedByte==-1)break;

5. 읽은만큼 파일에 write( ) 메소드를 활용하여 출력하기

fos.write(buffer, 0, readedByte); //(데이터, 시작점, 읽을 바이트 갯수)

전체 코드

MainClass13.java

package test.main;

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

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];//메모리를 너무 많이 차지 하지 않도록 배열 크기를 적절하게 지정

			while(true) {
				/*
				 * .read() 메소드를 호출하면서 byte[] 객체의 참조값을 전달하면
				 * 메소드 안에서 읽은 byte 데이터가 배열에 자동 저장된다.
				 * 또한 읽은 바이트의 갯수를 메소드가 리턴해준다.
				 */
				
				int readedByte = fis.read(buffer);//한 번에 배열크기의 byte씩 읽을 수 있음 
				if(readedByte==-1)break;
				
				//읽은만큼 파일에 출력하기 		
				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) {}
		}
			
	}
}

 

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함