#1 Stream
Stream(스트림)은 데이터를 읽고 기록 하기 위한 중간 매개체입니다.
프로그래머가 사용할 코드를 만들 때, 장치와 관련된 스트림을 생성해서 쓰기만 하면됩니다. 간단하네요이해하기가 쉽네요^^.
▨ 입출력 계열의 스트림은 read와 write 메서드를 포함하고 있습니다.
read계열의 메서드를 사용하면 데이터를 읽어들이고,
write계열의 메서드를 사용하면 데이터를 기록(출력)합니다.
read() 메서드 | write() 메서드 |
바이트 단위 int read() int read(byte cbuf[]) int read(byte cbuf[], int offset, int length) |
바이트 단위 int write(int c) int write(byte cbuf[]) int write(byte cbuf[], int offset, int length) |
문자 단위 int read() int read(char cbuf[]) int read(char cbuf[], int offset, int length) |
문자 단위 int write(int c) int write(char cbuf[]) int write(char int offset, int length) |
▨ 자바의 스트림은 입력 스트림과 출력 스트림으로 분리해서 생각해야하고, 바이트 스트림과 문자 스트림으로 나눌 수 있습니다. (실제는 아래보다 더 많습니다.)
(모든 스트림은 바이트 단위로 핸들 합니다. 문자(8바이트), 텍스트, 사진, zip, jar..모두 다.. 그런데, 사용할 수 있는 건 스트림에서 알아서 다 처리해주기 때문입니다.)
바이트 스트림 구성도 |
문자 스트림 구성도 |
▨ 예를 들면,
FileInputStream fis = new FileInputStream(파일);
fis.read() 를 이용해서 데이터 읽기
FileOutputStream fos = new FileOutputStream(파일);
fos.write() 를 이용해서 데이터 쓰기
#2 System.in
package java.lang; //java.lang 패키지 안에 스태틱으로 선언 되있으므로, 그냥 가따 쓰기만 하면 됩니다.
public class System{
public static PrintStream out;
public static InputStream in;
public static PrintStream err;
}
[참고]
public static void main(String[] args) throws IOException{ //입력을 할땐 IOException 예외처리가 필요 하다
//얼마전.. 코딩할때 try, catch로 했었는데.. 더편한방법이..
System.out.print("엔터를 누르세요");
int i = System.in.read(); //스트림 read를 사용하여 읽는다.
System.out.println(i); //13 : '\r' 이 출력
i = System.in.read();
System.out.println(i); //10 : '\n' 이 출력
}
#3 File 클래스
: 다른 언어에서는 File 변수를 하나 만들어서 거기서 입출력까지 다했었던거같은데.. JAVA에서는 File클래스와 입출력 스트림이 따로 놀아야 됩니다.
import java.io.*; import java.net.*; import java.util.*; public class FileMain { public static void main(String[] args) throws MalformedURLException{ File f = new File("FileMain.java"); PrintStream out = System.out; //스트림을 따로만든다. out.println("isFile(): " + f.isFile()); //파일? out.println("isDirectory(): " + f.isDirectory()); out.println("isHidden(): " + f.isHidden()); //숨김파일? out.println("lastModified(): " + f.lastModified()); out.println("canRead(): " + f.canRead()); //읽기 속성? out.println("canWrite(): " + f.canWrite()); //쓰기 속성? out.println("getPath(): " + f.getPath()); //상대 경로 out.println("getAbsolutePath(): "+ f.getAbsolutePath()); //절대 경로 out.println("getName(): " + f.getName()); //파일이름 out.println("toURL(): " + f.toURL()); //URL형식의 경로 out.println("exists(): " + f.exists()); //파일 존재여부 out.println("length(): " + f.length()); //파일 길이 File[] fs = f.listFiles(); //디렉토리 목록가져오기 for(int i=0; i<fs.length; i++){ System.out.println(fs[i].getName()); } } } |
--------------------출력화면 isFile(): true isDirectory(): false isHidden(): false lastModified(): 1087998966206 canRead(): true canWrite(): true getPath(): FileMain.java getAbsolutePath(): C:\javasrc\chap09\FileMain.java getName(): FileMain.java toURL(): file:/C:/javasrc/chap09/FileMain.java exists(): true length(): 1253 bootfont.bin CONFIG.SYS Documents and Settings ... ... |
생성 | 삭제 | 이름변경 |
File f = new File("디렉토리명"); if(!f.exist()){ f.mkdir(); } |
File f = new File("파일명"); if(f.exist()){ f.delete(); } |
File f = new File("원본파일명"); File t = new File("변경할파일명"); if(f.exists()){ f.renameTo(t); } |
#3-1 File 스트림
: FileInputStream, FileOutputStream, FileReader, FileWriter
위에 #1에서 바이트 단위, 문자단위로 write, read 메서드가 어떻게 생겼는지 봤습니다. 사용해보기로 하죠.
public class FileStreamMain3{ public static void main(String[] args) throws IOException{ File f = new File("a.dat"); if(f.exists()){ FileOutputStream fos = new FileOutputStream("a.dat", true); //덮어쓰기false, 이어쓰기:true byte[] b = new byte[]{72, 101, 108, 108, 111}; fos.write(b); fos.write(101); fos.close(); } } } |
public class FileStreamMain6{ public static void main(String[] args) throws IOException{ File f = new File("FileStreamMain6.java"); int fileSize = (int)f.length(); System.out.println("size :" + fileSize); byte[] b = new byte[fileSize]; FileInputStream fis = new FileInputStream("FileStreamMain6.java"); int pos = 0, size = 10, temp; //10byte씩 읽기 while( (size=fis.read(b, pos, size)) > 0 ){ pos += size; temp = b.length - pos; if(temp < 10) size = temp; } fis.close(); System.out.println("read size:" + pos); FileOutputStream fos = new FileOutputStream("test.txt"); //한번에 파일에 쓰기 fos.write(b); fos.close(); } } //처음 size와 다 읽었을 때 size가 같으면 정확히 쓴 것 |
public class FileWriterMain2{ public static void main(String[] args) throws IOException{ char[] content = new char[]{72, 101, 108, 108, 111}; String str = new String("Hello World!"); FileWriter fos = new FileWriter("writer2.dat"); fos.write(content); fos.write(str); fos.close(); } } |
public class FileReaderMain{ public static void main(String[] args) throws IOException{ FileReader fr = new FileReader("writer.dat"); int i; while( (i=fr.read()) != -1 ){ System.out.print((char)i); } fr.close(); } } |
public class BufferedFileCopy {
//ex) java BufferedFileCopy s.exe t.exe
public static void main(String[] args) throws IOException{
int i, len=0;
FileInputStream fis = new FileInputStream(args[0]); //아래 Buffered스트림을 안써도되지만, 그럼 더느리다.
FileOutputStream fos = new FileOutputStream(args[1]);
BufferedInputStream bis = new BufferedInputStream(fis); //Buffered스트림을 사용한 복사가 빨르다.
BufferedOutputStream bos = new BufferedOutputStream(fos); //Buffered스트림 없이도 복사가 가능하다
long psecond = System.currentTimeMillis();
while((i=bis.read()) != -1) {
bos.write(i);
len++;
}
bis.close();
bos.close();
psecond = System.currentTimeMillis() - psecond;
System.out.println(len + " bytes " + psecond +" miliseconds");
}
}
#3-2 RandomAccessFile 클래스
: 임의 접근, 파일의 아무 곳에서 부터 읽고 쓸수 있다
RandomAccessFile rf = new RandomAccessFile("파일명", "모드"); //모드: r, rw..
rf.seek(10);
//offset이 10인 위치로 이동해서 수정하면된다.
#4 Memory 스트림, 2차 스트림
스트림을 한번 쭉.. 보니.. 사용법이 다 같네요. 사용하기도 쉽고.. 역시 자바가 프로그래밍을 하기 쉬운 언어인거 같긴하네요ㅎ
Memory 스트림들 ByteArrayInputStream ByteArrayOutputStream CharArrayInputStream CharArrayOutputStream StringReader StringWriter |
대표적인 1차 스트림들 InputStream, OutputStream FileInputStream, FileOutputStream FileReader, FileWriter ByteArrayInputStream, ByteArrayOutputStream CharArrayReader, CharArrayWriter StringReader, StringWriter |
대표적인 2차 스트림들 InputStreamReader, OutputStreamWriter DataInputStream, DataOutputStream BufferedInputStream, BufferedOutputStream BufferedReader, BufferedWriter ObjectInputStream, ObjectOutputStream |
스트림들을 구분해서 설명해보겠습니다.
▨ Memory 스트림에는 바이트배열과 문자배열(문자열)이 있습니다. 이 스트림을 쓰면, 한정된 배열의 크기를 정하지 않고도 동적으로 메모리를 할당해서 사용할수 있으므로 유용합니다. 출력스트림에서 기록된 모든 데이터를 배열로 얻을 수 있다는 장점이 있습니다. String은 문자열이 진화한 것이죠.
사용:
byte[] arr = {'j', 'a', 'b', 'o', 'o', 'k'};
byte[] result = out.toByteArray(); // 모든 데이터를 배열로 받아내기 (타 스트림 : .toCharArray() / .toString() .getBuffer())
System.out.print((char)result[3]); // read할때 int형으로 저장되므로 char로 변형
▨ 1차 스트림은 목표지점까지 직접 연결된다는 것입니다. 즉, 한번만 가공된다는 겁니다.
▨ 2차 스트림은 1차 스트림에서 원하는 대로 2차스트림으로 한번더 가공한다는 것입니다. 예를 들면, FileInputStream을 버퍼링이 지원되는 BufferedInputStream로 변형하면 데이터 읽고 쓰는 속도가 더 빠릅니다.
사용:
1. FileInputStream fis = new FileInputStream("파일명");
InputStreamReader isr = new InputStreamReader(fis); //파일에서 읽어올때, 문자로 가져온다.
2. InputStreamReader isr = new InputStreamReader(System.in); //System.in은 InputStream이다.
System.out.println("종료하기 위해서는 '끝'을 입력하시오");
System.out.println("출력할 데이터를 입력하시오? ");
while((i = isr.read()) != '끝') { //핸들을 바이트에서 문자로 바꿔서 인식해 한글을 구분한다.
System.out.print((char)i);
}
3. FileOutputStream fos = new FileOutputStream("data.dat");
DataOutputStream dos = new DataOutputStream(fos);
dos.writeFloat(3.14f); //4바이트를 float형식으로 쓰기
FileInputStream fis = new FileInputStream("data.dat");
DataInputStream dis = new DataInputStream(fis);
float f = dis.readFloat();
3. FileOutputStream fos = new FileOutputStream("serial.dat"); //직렬화(Serialization)
ObjectOutputStream oos = new ObjectOutputStream(fos);
SampleData s1 = new SampleData("홍길동", 1004);
oos.writeObject(s1); //객체의 멤버변수값들을 직렬화해서 저장한다.
FileInputStream fis = new FileInputStream("serial.dat"); //역직렬화(Deserialization)
ObjectInputStream ois = new ObjectInputStream(fis);
SampleData sd1 = (SampleData)ois.readObject(); //저장된 멤버변수값들을 역직렬화해서 가져온다.
System.out.println(sd1 + ":" + sd1.getSampleData());
ps. 스트림.. 다른 센션보다 좀더 볼게 많았던거 같은데, 결국 스트림이름만 다르고, 사용방법은 모두 같네요.