파일다루기 1 데이터는이곳에서저곳으로흘러간다. - 즉, 데이터는스트림 (stream) 이되어서일렬로이곳에서저곳으로이동한다. - 자바프로그램에서입출력되는모든데이터는스트림형태로주고받는다. 키보드에서입력되는데이터나모니터로출력되는데이터, 파일로부터읽은데이터, 파일로출력하는데이터들도모두스트림형태이다. - 스트림은흐르는방향에따라입력스트림 (input stream) 과출력스트림 (output stream) 으로나뉜다. 입력스트림 : 프로그램내부로입력되는스트림 출력스트림 : 프로그램에서외부로출력되는스트림 - 스트림은흐르는데이터의형태에따라문자스트림 (character stream) 과바이트스트림 (byte stream) 으로나뉜다. 문자스트림 : 사람이이해할수있는문자로구성된스트림 바이트스트림 : 컴퓨터가이해할수있는데이터로구성된스트림 - 자바에는모든종류의스트림을다룰수있는클래스들이준비되어있다. 이들클래스들은처리하는스트림의종류에따라이름이붙여져있다. FileInputStream 클래스 : 파일로부터입력되는스트림을처리하는클래스 FileOutputStream 클래스 : 파일로스트림을출력하는스트림을처리하는클래스 FileReader 클래스 : 파일로부터문자스트림을입력받는클래스 FileWriter 클래스 : 파일로문자스트림을출력하는클래스 - 위의 4개의클래스사용법만알면파일로부터문자나이진수데이터를모두읽고쓸수있다. 이들클래스는 java.io 패키지에포함되어있으므로, 파일을다루는프로그램을작성하려면 java.io 패키지를 import 해야한다. - 그런데, 위의 4개클래스들은파일입출력에필요한최소한의기능만을가지고있기때문에여러종류의데이터를다양한방법으로입출력하기에는부족한면이많다. - java.io 패키지에는입출력의기능과성능을향상시키는클래스들이있으며, 이클래스와위의 4개의클래스를함께사용해서좀더편리하게파일입출력기능을구현할수있다. 입출력기능과성능을향상시키는클래스들중에는버퍼 ( 작은기억장소 ) 를사용해서입출력의성능을향상시키는클래스도있고, 복잡한구조의데이터를스트림으로만들어서출력하는기능의클래스와데이터를사람이보기좋은형태로출력하는기능의클래스등이있다. - java.io 패키지에는파일의입출력을다루는클래스뿐만아니라, 파일자체를다루는클래스들도있다. 즉, 파일의최종수정일시을알아내는기능, 파일을삭제하는기능, 파일의이름을알아내는기능등을다룰수있다. 이러한기능의클래스가 File 클래스이다. 파일로입출력하기 I 파일을이용한작업처리는파일로부터읽는작업, 파일로출력하는작업이있다. 파일로부터읽는작업순서 1. 파일을연다. 2. 파일로부터자료를읽는다. 3. 파일을닫는다. - 1 -
파일로출력하는작업순서 1. 파일을연다. 2. 파일로자료를쓴다. 3. 파일을닫는다. 파일입출력에사용되는클래스들. FileInputStream, FileOutputStream, FileReader, FileWriter 문자단위로입출력하기 사람이읽을수있는문자로만구성된파일을읽기위해서 FileReader 클래스를사용한다. FileReader reader = new FileReader(" 파일이름.txt");// 단계 1 : 파일을연다. 예 : ( c:\\tmp\\test.txt ) while(true) { int data = reader.read();// 한문자씩읽는다. if (data < 0) break;// 읽을문자가없으면반복종료 char ch = (char) data; System.out.println(ch);// 단계 2 : 파일로부터자료를읽는다. reader.close();// 단계 3 : 파일을닫는다. 위의 read() 메서드의리턴값의형태는 int 이다. 이메서드가 char 형태의표현범위를벗어난정보도리턴하므로 리턴값의형태는 int 이어야한다. 파일을끝까지읽어서더이상읽을문자가없으면 1 을리턴한다. 정상적으로작동할것으로예상했으나, 오류가발생한다. 파일을통해서입출력작업은다양한컴퓨터의자원 ( 메모리나입출력장치등을의미 ) 을사용하므로, 작업도중에다양한원인에의한예외발생이가능하다. 따라서, 파일을통한입출력작업에는반드시예외처리를해야프로그램이작동을한다. 그러므로, 위의프로그램에예외처리를해야프로그램이정상적으로동작을한다. public class FileIOTest { FileReader reader = null; reader = new FileReader("test.txt"); while(true) { int data = reader.read();// 한문자씩읽는다. if (data < 0) break;// 읽을문자가없으면반복종료 - 2 -
char ch = (char) data; System.out.println(ch);// 단계 2 : 파일로부터자료를읽는다. catch(filenotfoundexception e) { System.out.println(" 파일이존재하지않습니다."); catch(ioexception e) { System.out.println(" 파일을읽을수없습니다."); finally { reader.close(); catch(exception e) { public class FileIOTest2 { FileWriter writer = null; // 이미존재하는파일에덧붙여쓰려면, new FileWriter("testout.txt", true); 라고한다. writer = new FileWriter("testout.txt"); char arr[] = {' 사 ', ' 랑 ', ' 합 ', ' 니 ', ' 다 '; for(int c = 0; c < arr.length; c++) writer.write(arr[c]); // 한꺼번에출력하려면 for문을삭제하고 writer.write(arr); 문장을삽입하면된다. catch(ioexception e) { System.out.println(" 파일로출력할수없습니다."); finally { writer.close(); catch(exception e) { - 3 -
문자형태가아닌데이터를파일에쓸때는 FileOutputStream 클래스를사용한다. public class FileOutputStreamTest { FileOutputStream fos = null; fos = new FileOutputStream("output.dat"); byte arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9; for(int i = 0; i < arr.length; i++) fos.write(arr[i]); catch(ioexception e) { System.out.println(" 파일로출력할수없습니다. ); finally { fos.close(); catch(exception e) { - 4 -
public class FileInputStreamTest { FileInputStream fis = null; fis = new FileInputStream("output.dat"); byte arr[] = new byte[16]; while(true) { int num = fis.read(arr);// 파일로부터 16바이트를읽는다. if(num < 0) break;// 더이상읽을내용이없으면반복종료 for(int i = 0; i < arr.length; i++) System.out.print(arr[i]);// 읽은내용을화면에출력 System.out.println();// 모든내용이출력되면줄을바꾼다. catch(ioexception e) { System.out.println(" 파일을읽을수없습니다. ); finally { fis.close(); catch(exception e) { - 5 -
입출력기능과성능을향상시키는클래스 FileReader, FileWriter, FileInputStream, FileOutputStream 클래스는파일에데이터를읽고쓰는데필요한최소한 의기능만갖춘클래스들이다. 다양한방법으로입출력을하려면이클래스들만으로는부족하다. 클래스이름 DataInputStream DataOutputStream ObjectInputStream ObjectOutputStream BufferedReader BufferedInputStream BufferedWriter BufferedOutputStream LineNumberReader 설명기본형의데이터를입출력하는메소드기본형의데이터와객체형태의데이터를입출력하는메소드데이터를한꺼번에읽어서버퍼에저장해두는클래스데이터를버퍼에저장해두었다가한꺼번에출력하는클래스텍스트파일의각행에번호를붙여가면서읽는클래스 char 형이나 byte 형이아닌기본형값의데이터를파일에읽고쓰기위해서 DataInputStream, DataOutputStream 클래스를사용한다. 기본형의데이터를파일로출력하기 DataInputStream 클래스는기본형의데이터를바이트스트림으로출력하는기능을한다. 그러나, 이클래스에는파 일에데이터를쓰는기능은없기때문에 FileOutputStream 클래스와함께사용해야한다. FileOutputStream fos = new FileOutputStream("output.dat"); DataOutputStream dis = new DataOutputStream(fos); DataOutputStream 객체에서사용할수있는메소드들 메소드이름 void writebyte(int v) void writeshort(int v) void writechar(int v) void writeint(int v) void writelong(long v) void writefloat(float v) void writedouble(double v) void writeboolean(boolean v) 설명매개변수로주어진 int 형 v값의 1 바이트를출력매개변수로주어진 int 형 v값의 2 바이트를출력매개변수로주어진 int 형의 v값의 2 바이트를출력매개변수로주어진 int 형의 v값을출력매개변수로주어진 long 형의 v값을출력매개변수로주어진 float 형의 v값을출력매개변수로주어진 double 형의 v값을출력매개변수로주어진 boolean 형의 v값을출력 - 6 -
DataOutputStream 클래스의사용예 ) public class DataOutputStreamTest { DataOutputStream dos = null; dos = new DataOutputStream(new FileOutputStream("output.dat")); int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9; for(int i = 0; i < arr.length; i++) dos.writeint(arr[i]); catch(ioexception e) { System.out.println(" 파일로출력할수없습니다."); finally { dos.close(); catch(exception e) { DataInputStream 객체에서사용할수있는메소드들 메소드이름 byte readbyte() short readshort() char readchar() int readint() long readlong() float readfloat() double readdouble() boolean readboolean() 설명 1 바이트를읽어서 byte 형으로리턴 2 바이트를읽어서 short 형으로리턴 2 바이트를읽어서 char 형으로리턴 4 바이트를읽어서 int 형으로리턴 8 바이트를읽어서 long 형으로리턴 4 바이트를읽어서 float 형으로리턴 8 바이트를읽어서 double 형으로리턴 1 바이트를읽어서 0이면 false, 아니면 true를리턴 - 7 -
DataInputStream 클래스의사용예 ) public class DataInputStreamTest { DataInputStream dis = null; dis = new DataInputStream(new FileInputStream("output.dat")); while(true) { int data = dis.readint(); System.out.println(data); catch(filenotfoundexception e) { System.out.println(" 파일이존재하지않습니다."); catch(eofexception e) { System.out.println(" 파일로출력할수없습니다."); catch(ioexception e) { System.out.println(" 다읽었슴."); finally { dis.close(); catch(exception e) { - 8 -
객체를파일로읽고쓰기 객체를파일로입출력하기위해사용하는클래스는 ObjectInputStream과 ObjectOutputStream이다. 객체를파일로입출력하기위해서는객체가직렬화 (Serialization) 되어있어야한다. 객체가직렬화되어있는지의여부는객체가생성하는데사용한클래스에의해결정된다. 즉, 클래스가 java.io.serializable 인터페이스를구현한클래스이면직렬화가가능하고, 그렇지않으면직렬화가가능하지않다. 클래스가 Serializable 인터페이스를구현했는지의여부는자바라이브러리에서확인할수있다. 객체를파일로출력하는예 ) GregorianCalendar 클래스의객체를파일로저장하는프로그램 참고 GregorianCalendar 클래스는날짜를그레고리형태로다루는작업을한다. public class ObjectOutputStreamTest { public static viod main(string[] args) { ObjectOutputStream oos = null; oos = new ObjectOutputStream(new FileOutputStream("output.dat"); oos.writeobject(new GregorianCalendar(2010, 11, 1));// 월은 0부터 11까지임 oos.writeobject(new GregorianCalendar(2010, 11, 2)); oos.writeobject(new GregorianCalendar(2010, 11, 3)); catch(ioexception e) { System.out.println(" 파일로출력할수없습니다."); ) finally { oos.close(); catch(exception e) { - 9 -
GregorianCalendar 클래스의객체가저장된파일을읽어서화면에출력하는프로그램 public class ObjectInputStreamTest { public static void main(string[] args){ ObjectInputStream ois = null; ois = new ObjectInputStream(new FileInputStream("output.dat")); while(true) { GregorianCalendar calendar = (GregorianCalendar) ois.readobject(); int year = calendar.get(calendar.year); int month = calendar.get(calendar.month) + 1;// 달은 0부터시작 int date = calendar.get(calendar.date); System.out.printnl(year + ";" + month + ";" + date); catch(filenotfoundexception e) { System.out.println(" 파일이존재하지않습니다."); catch(eofexception e) { System.out.println(" 다읽었슴."); catch(ioexception e) { System.out.println(" 파일을읽을수없습니다."); catch(clasnotfoundexception e) { System.out.println(" 해당클래스가존재하지않습니다."); ) finally { ois.close(); catch(exception e) { - 10 -
버퍼를이용해서입출력의성능을향상시키는클래스 지금까지사용했던 FileReader, FileWriter, FileInputStream, FileOutputStream 클래스는 read, write 메소드를사용할때마다파일로부터직접데이터를읽거나쓰기때문에빈번한작업으로인해서성능이저하될가능성이높다. 필요한데이터를한꺼번에읽어두거나, 출력할데이터를모아서한꺼번에출력하면훨씬성능이높아지게된다. 이를위해사용하는클래스가버퍼를이용한클래스이다. 버퍼라는임시기억장소를이용해서한꺼번에읽고, 쓰는작업을하기때문에효율이높아진다. 클래스이름 설명 BufferedInputStream 바이트입력스트림을버퍼에저장한다. BufferedOutputStream 바이트출력스트림을버퍼에저장한다. BufferedReader 문자입력스트림을버퍼에저장한다. BufferedWriter 문자출력스트림을버퍼에저장한다. BuferedReader 클래스는 FileReader 클래스와함께사용할수있다. BufferedWriter 클래스는 FileWriter 클래스와함께사용할수있다. BufferedInputStream 클래스는 FileInputStream 클래스와함께사용할수있다. BufferedOutputStream 클래스는 FileOutputStream 클래스와함께사용할수있다. - 11 -
BufferedInputStream 클래스를사용한예 ) 프로그램실행시입력한파일을읽어화면에출력 public class BufferedInputStreamTest { if(args.length < 1) { System.out.println(" 프로그램시작시에파일이름을입력해야합니다."); return; BufferedInputStream bis = null; bis = new BufferedInputStream(new FileInputStream(args[0])); byte arr[] = new byte[16]; while(true) { int num = bis.read(arr); if(num < 0) break; for(int i = 0; i < num; i++) { System.out.print(arr[i]); System.out.println(); catch(filenotfoundexception e) { System.out.println(args[0] + " 파일이존재하지않습니다."); catch(ioexception e) { System.out.println(args[0] + " 파일을읽을수없습니다."); finally { bis.close(); catch(exception e) { - 12 -
BufferedWriter 클래스를이용한예 ) BuferedWriter 를사용하는것만제외하면기존의 FileWriter 를사용한예와비슷하다. public class BufferedWriterTest { BufferedWriter writer = null; // 이미존재하는파일에덧붙여쓰려면, new FileWriter("testout.txt", true); 라고한다. writer = new BufferedWriter(FileWriter("testout.txt")); char arr[] = {' 사 ', ' 랑 ', ' 합 ', ' 니 ', ' 다 '; for(int c = 0; c < arr.length; c++) writer.write(arr[c]); // 한꺼번에출력하려면 for문을삭제하고 writer.write(arr); 문장을삽입하면된다. catch(ioexception e) { System.out.println(" 파일로출력할수없습니다."); finally { writer.close(); catch(exception e) { - 13 -
텍스트파일에행번호를붙이면서읽는예 ) public class LineNumberTest { public static void main(string[] args){ LineNumberReader reader = null reader = new LineNumberReader(new FileReader("data.txt")); while(true) { String str = reader.readline();// 한줄씩읽는다. if(str == null) break; int lineno = reader.getlinenumber();// 줄의행번호를알려준다. System.out.println(lineNo + ": " + str); catch(filenotfoundexception e) { System.out.println(args[0] + " 파일이존재하지않습니다."); catch(ioexception e) { System.out.println(args[0] + " 파일을읽을수없습니다."); finally { reader.close(); catch(exception e) { - 14 -