toggle menu

JAVA 정리 - File Input/Output

2012.08.01 09:09 JAVA
데이터의 흐름을 Stream이라고 표현!
단방향 - 읽기/쓰기 클래스가 각각 존재함!!

File 객체
byte 단위(I/O)
문자단위(Reader, Writer)

 flush() : 버퍼의 내용을 강제로 출력하여 비움. close()하면 auto-flush 발생!


Byte 단위
InputStream -> FileInputStream -> BufferedInputStream
Output

문자단위
Reader -> FileReader -> BuffredReader
Writer




간단한 파일 입출력 - FileInputStream
import java.io.FileInputStream;

public class FileInputStreamExam
{
	public static void main(String[] args)
	{
		// 바이트 단위로 파일읽기
		String filePath = "src/ex0801/io/FileExam.java"; // 대상 파일
		FileInputStream fileStream = null; // 파일 스트림
		int i = 0; //한 바이트를 담을 변수

		try
		{
			fileStream = new FileInputStream(filePath);// 파일 스트림 생성
			
			do
			{
				i = fileStream.read(); //한 바이트 읽기
				System.out.print((char) i);
			}
			while(i != -1);
			
		}
		catch (Exception e)
		{
			System.out.println("파일 입출력 에러!!" + e);
		}
		finally
		{
			try
			{
				fileStream.close();// 파일 닫기. 여기에도 try/catch가 필요하다.
			}
			catch (Exception e)
			{
				System.out.println("닫기 실패" + e);
			}
		}
	}
}


위의 예제는 파일의 내용을 출력해주지만, 한글과 같은 2Byte 문자는 정상적으로 출력되지 않는다.
읽은 내용을 Byte 배열에 담아 출력하는 새로운 방식이 있다.

FileInputStream 을 사용해 Byte 배열에 담아, String 객체로 변환하는 예제

import java.io.FileInputStream;

public class FileInputStreamExam
{
    public static void main( String[ ] args )
    {
        // 바이트 단위로 파일읽기
        String filePath = "src/ex0801/io/FileExam.java"; // 대상 파일
        FileInputStream fileStream = null; // 파일 스트림

        try
        {
            fileStream = new FileInputStream( filePath );// 파일 스트림 생성

            //파일 내용을 담을 버퍼(?) 선언
            byte[ ] readBuffer = new byte[ fileStream.available( ) ];
            while (fileStream.read( readBuffer ) != -1) //
            {
            }

            System.out.println( new String( readBuffer ) ); //출력

        }
        catch ( Exception e )
        {
            System.out.println( "파일 입출력 에러!!" + e );
        }
        finally
        {
            try
            {
                fileStream.close( );//파일 닫기. 여기에도 try/catch가 필요하다.
            }
            catch ( Exception e )
            {
                System.out.println( "닫기 실패" + e );
            }
        }
    }
}


그러나 위의 방법을 응용하여 파일 복사를 시도할 경우 정상적으로 이동이 되지 않는다.
이때는 아래와 같은 소스를 사용해서 처리할 수 있다.
그러나 Byte 배열이 1024 바이트여서인지, 1024바이트 내의 오차가 발생한다. ㅠㅠ 

파일 복사 예제 - FileInputStream, FileOutputStream

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

public class FileInputStreamExam
{
	public static void main(String[] args)
	{
		// 바이트 단위로 파일읽기
		String filePath = "src/ex0801/io/aaa.zip"; // 대상 파일
		FileInputStream inputStream = null; // 파일 읽기 스트림
		FileOutputStream outputStream = null; // 파일 쓰기 스트림

		try
		{
			inputStream = new FileInputStream(filePath);// 파일 입력 스트림 생성
			outputStream = new FileOutputStream("src/ex0801/io/bb.zip");// 파일 출력 스트림 생성

			// 파일 내용을 담을 버퍼(?) 선언
			byte[] readBuffer = new byte[1024];
			while (inputStream.read(readBuffer, 0, readBuffer.length) != -1)
			{
				//버퍼 크기만큼 읽을 때마다 출력 스트림에 써준다.
				outputStream.write(readBuffer);
			}

		}
		catch (Exception e)
		{
			System.out.println("파일 입출력 에러!!" + e);
		}
		finally
		{
			try
			{
				// 파일 닫기. 여기에도 try/catch가 필요하다.
				inputStream.close();
				outputStream.close();
			}
			catch (Exception e)
			{
				System.out.println("닫기 실패" + e);
			}
		}
	}
}


이번에는 동일한 작업을 Buffred 스트림을 사용해서 처리하는 소스를 살펴보자.
대용량 파일일수록 이점이 있다고 한다.


BufferedInputStream, BufferedOutputStream 을 사용한 파일 복사 예제

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class FileInputStreamExam
{
	public static void main(String[] args)
	{
		// 바이트 단위로 파일읽기
		String filePath = "src/ex0801/io/이클립스.zip"; // 대상 파일
		FileInputStream inputStream = null; // 파일 스트림
		FileOutputStream outputStream = null;
		BufferedInputStream bufferedInputStream = null; // 버퍼 스트림
		BufferedOutputStream bufferedOutputStream = null;

		try
		{
			inputStream = new FileInputStream(filePath);// 파일 입력 스트림 생성
			bufferedInputStream = new BufferedInputStream(inputStream);// 파일 출력 스트림 생성
			
			outputStream = new FileOutputStream("src/ex0801/io/bb.zip");
			bufferedOutputStream = new BufferedOutputStream(outputStream);

			// 파일 내용을 담을 버퍼(?) 선언
			byte[] readBuffer = new byte[1024];
			while (bufferedInputStream.read(readBuffer, 0, readBuffer.length) != -1)
			{
				//버퍼 크기만큼 읽을 때마다 출력 스트림에 써준다.
				bufferedOutputStream.write(readBuffer);
			}

		}
		catch (Exception e)
		{
			System.out.println("파일 입출력 에러!!" + e);
		}
		finally
		{
			try
			{
				// 파일 닫기. 여기에도 try/catch가 필요하다.
				// 보조스트림을 닫으면 원스트림도 닫힌다.
				bufferedInputStream.close();
				bufferedOutputStream.close();
			}
			catch (Exception e)
			{
				System.out.println("닫기 실패" + e);
			}
		}
	}
}


파일 복사 이외의 경우에 위의 방법을 많이 사용하므로 사용 방법을 간단히 정리해 보았다.

BufferedInputStream 의 가장 기초적인 폼
BufferedInputStream bs = null;

try
{
	bs = new BufferedInputStream(new FileInputStream(경로));
	byte [] b = new byte [bs.available()]; //임시로 읽는데 쓰는 공간
	System.out.println(b.length);
	while( bs.read(b) != -1) {}
	
	System.out.println(new String(b)); //필요에 따라 스트링객체로 변환
	
}
catch (Exception e)
{
	System.out.println(e);
}
finally
{
	try
	{
		bs.close(); //반드시 닫는다.
	}
	catch (Exception e)
	{
		System.out.println(e);
	}
}


BufferedOutputStream 의 가장 기초적인 폼 
BufferedOutputStream bs = null;

try
{
	bs = new BufferedOutputStream(new FileOutputStream(경로));
	bs.write(text.getText().getBytes()); //Byte형으로만 넣을 수 있음
}
catch (Exception e)
{
	System.out.println(e);
}
finally
{
	try
	{
		bs.close(); //반드시 닫는다.
	}
	catch (Exception e)
	{
		System.out.println(e);
	}
}




이번에는 Byte 단위가 아니라 Char 단위로 읽어들이는 Reader/Writer를 살펴보자.
import java.io.FileReader;

public class ReaderWriter
{
	public static void main(String[] args)
	{
		FileReader fileReader = null;

		try
		{
			fileReader = new FileReader("src/ex0801/io/FileExam.java");

			int i = 0;
			while (i != -1)
			{
				i = fileReader.read();
				System.out.print((char) i);
			}
		}
		catch (Exception e)
		{
			System.out.println("오류" + e);
		}
		finally
		{
			try
			{
				fileReader.close();
			}
			catch (Exception e)
			{
				System.out.println("파일 닫기 오류" + e);
			}
		}
	}
}


그런데, 이런 Reader에도 Buffered 가 존재한다.
BufferedReader에는 한줄씩 읽는 메소드도 있는데, 아래와 같이 활용할 수 있다.
import java.io.BufferedReader;
import java.io.FileReader;

public class BufferedReaderWriter
{
	public static void main(String[] args)
	{
		FileReader fileReader = null;
		BufferedReader bufferedReader = null;

		try
		{
			fileReader = new FileReader("src/ex0801/io/FileExam.java");
			bufferedReader = new BufferedReader(fileReader);

			String string = new String(); //임시 변수
			
			do
			{
				//한줄씩 읽기
				string = bufferedReader.readLine();
				System.out.println(string);
			}
			while(string != null); //파일 끝이면 null을 반환한다.
		}
		catch (Exception e)
		{
			System.out.println("오류" + e);
		}
		finally
		{
			try
			{
				bufferedReader.close();
			}
			catch (Exception e)
			{
				System.out.println("파일 닫기 오류" + e);
			}
		}
	}
}




BufferedReader와 BufferedWriter를 사용해서 문자단위로 읽어 복사하는 소스를 살펴보자.
마찬가지로 거의 비슷한 처리 과정을 거치지만, 사용되는 클래스와 메소드가 조금 다르다.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;

public class BufferedReaderWriter
{
	public static void main(String[] args)
	{
		FileReader fileReader = null;
		BufferedReader bufferedReader = null;
		BufferedWriter bufferedWriter = null;

		try
		{
			fileReader = new FileReader("src/ex0801/io/FileExam.java");
			bufferedReader = new BufferedReader(fileReader);
			//bufferedWriter = new BufferedWriter(new FileWriter("src/ex0801/io/aaa.txt"));
			//true를 두번째 인수를 넣으면 이어서 저장됨.
			//또 특별히 FileWriter 객체를 따로 생성하지 않고 바로 생성하여 파라메터로 넣어줌.
			bufferedWriter = new BufferedWriter(new FileWriter("/aaa.txt", true));

			String string = new String(); //임시 변수
			
			do
			{
				//한줄씩 읽기
				string = bufferedReader.readLine();
				
				//끝이 아닌경우, 새 파일에 내용 복사하여 쓰기
				if(string != null)
				{
					bufferedWriter.write(string);
					bufferedWriter.newLine(); //한줄 개행
					System.out.println(string);
				}
			}
			while(string != null); //파일 끝이면 null을 반환한다.
		}
		catch (Exception e)
		{
			System.out.println("오류" + e);
		}
		finally
		{
			try
			{
				bufferedReader.close();
				bufferedWriter.close();
			}
			catch (Exception e)
			{
				System.out.println("파일 닫기 오류" + e);
			}
		}
	}
}










JAVA 관련 포스팅 더보기