ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바 채팅 프로그래밍 1장
    네트워크 2019. 9. 5. 22:45

    OutputStream 클래스

    추상 클래스로서 모든 출력 스트림 클래스들의 최상위 클래스

    FileOutputStream 및 TelnetOutputStream와 같은 하위 클래스들이 메모리에 있는 바이트 데이터를 파일이나 다른 컴퓨터로 전송

    - 반드시 예외처리를 해주어야 함

     

    1. public abstract void write(int b) throws IOException

    OutputStream 클래스의 가장 기본적인 메소드

    인수 b는 32비트의 크기지만, 전송되는 데이터는 가장 낮은 8비트의 데이터만 전송

    부호가 없는 양의 정수 값으로 인식(자바에선 unsigned byte 자료형이 없어서)

    예제 1.1 DisplayCharacter.java

    import java.io.*;
    class DisplayCharacter {
    	public static void main(String[] args) throws java.io.InvalidObjectException {
    		for(int i=32; i<127; i++) { // 
    			System.out.write(i); // 32부터 127까지의 정수 값을 화면에 출력한다.
    			if(i%8==7)
    				System.out.write('\n'); // 8개의 문자를 출력하고 줄을 이동한다.
    			else
    				System.out.write('\t'); // 하나의 문자를 출력하고 탭을 출력한다.
    		}
    		System.out.write('\n');
    	}
    
    }
    

     실행결과

    모니터에 데이터를 출력하기 위해서는 객체를 생성할 필요없이 System.out 객체를 사용하면 된다.

     

    2. public void wrtie(byte[] data) throws IOException

    write(int b)는 한 번에 한 바이트씩만 전송하여 비효율적. -> 전송효율 높이기 위해 배열로 저장된 여러 바이트 데이터를 한 번에 전송할 수 있는 메소드 (배열에 저장된 내용은 0~255의 부호 없는 바이트 데이터)

     

    예제 1.2 DisplayCharacterBlock.java

    import java.io.*;
    class DisplayCharacterBlock {
    	public static void main(String[] args) throws java.io.IOException {
    		byte[] b=new byte[(127-31)*2]; // 바이트 기억공간을 할당한다.
    		int index=0;
    		for(int i=32; i<127 ;i++) {
    		// 배열에 32부터 126까지의 바이트 데이터 및 '\t' 데이터를 저장한다.
    			b[index++]=(byte) i; // 정수를 바이트(0에서 255)값으로 캐스트한다.
    			if(i%8==7)
    				b[index++]=(byte)'\n'; // 8개의 데이터 다음에는 newline을 삽입한다.
    			else
    				b[index++]=(byte)'\t';
    		}
    		b[index++]=(byte)'\n';
    		System.out.write(b);
    	}
    }
    

     실행결과

    배열 b에 32, '\t', 33, '\t' ....126, \n 으로 저장

    마지막 줄 write(b) 메소드는 배열에 저장된 모든 내용을 콘솔에 출력

     

    예제 1.3 DisplayString.java

    import java.io.*;
    class DisplayString {
    	public static void main(String[] args) throws java.io.IOException {
    		byte[] buffer;
    		for(int i=0; i<args.length;i++) {
    			buffer=args[i].getBytes(); // 문자열을 바이트 데이터로 변환한다.
    			System.out.write(buffer);
    			System.out.write('\n'); // 다음 문자열은 새로운 줄에 출력한다.
    		}
    	}
    }

    실행결과

    출력할 문자열들을 명령어 라인에서 입력받아 args[i]에 저장

    getBytes() 메소르를 사용하여 문자 데이터(4바이트)를 바이트 데이터로 변환

     

    3. public void write(byte[] data, int offset, int length) throws IOException

    offset 위치부터 length개의 바이트를 한 번에 전송

     

    4. public ovid flush() throsw IOException

    BufferedOutputStream 및 BufferedWrite 클래스는 지정한 크기의 버퍼가 채워졌을 때 전송하지만, flush() 메소드를 사용하면 버퍼가 차지 않아도 강제적으로 전송

     

    5. public void close() throws IOException

    close() 메소드는 현재 실행중인 스트림이 사용하는 파일 핸들 또는 포트와 같은 자원을 해지하는 기능을 수행

    실행중인 출력 스트림을 닫고, 닫혀진 스트림에 전송하면 IOException 예외 발생

     

    InputStream 클래스

     

    추상클래스로서 모든 입력 스트림 클래스들의 최상위 클래스

    FileInputStream 및 TelnetInputStream와 같은 하위 클래스 들이 파일이나 다른 컴퓨터로부터 바이트 데이터를 읽어서 메모리로 저장하는 기능을 제공

    - 반드시 예외처리를 해주어야 함

     

    1. public abstract int read() thorws IOException

    InputStream클래스의 가장 기몬적인 메소드

    스트림으로부터 바이트 데이터를 읽어서 상위 24비트는 0으로 채워진 4바이트 정수 반환

    읽혀진 바이트 데이터는 10진수(0~255)

    1바이트 양의 정수 값을 읽어서 4바이트의 정수 값으로 반환

    - 입력 스트림의 끝을 만나는 경우에는 -1을 반환 -> 모든 바이트 데이터를 읽었는지 확인하려면 데이터가 -1인지 체크

     

    예제 1.4 ReadCharacters.java

    import java.io.*;
    class ReadCharacters {
    	public static void main(String[] args) throws java.io.IOException {
    		int data;
    		while((data=System.in.read())>=0)
    		// 엔터키까지 입력한 문자들을 하나씩 읽으며 CTRL-Z는 -을 반환
    			System.out.write(data);
    	}
    }

    실행결과

    CTRL + Z로 종료

    키보드로부터 입력되 눔자를 읽어고기 위해선 System.in 객체를 사용

    한 문자씩 읽어서 4바이트 정수 값으로 반환하고 출력

     

    2. public int read(byte[] data) throws IOException

    여러 바이트 데이터를 읽어서 data 바이트 배열에 저장

    외부 디바이스로부터 읽어서 바이트 배열에 저장된 바이트의 수를 반환, 스트림의 마지막 경우 -1 반환

     

    예제 1.5 ReadCharactersBlock.java

    import java.io.*;
    class ReadCharactersBlock {
    	public static void main(String[] args) throws java.io.IOException {
    		byte[] buffer = new byte[80];
    		int numberRead; // 읽어서 배열에 저장한 바이트 데이터수를 저장한다.
    		while((numberRead=System.in.read(buffer))>=0)
    		// 키보드에서 enter키 까지 입력한 문자들을 읽어서 buffer 배열에 저장하고
    		// 읽은 문자 데이터 수를 반환하여 numberRead 정수변수에 저장한다.
    			System.out.write(buffer,0,numberRead);
    		// buffer에 있는 데이터를 처음부터 numberREad 개수 만큼 화면에 출력한다.
    	}
    }
    

     while 문의 System.in.read(buffer) 수행문은 최대 80바이트까지 읽어서 배열에 저장 바이트 수를 numberREad 정수변수에 저장

    80개 이상의 문자를 입력해도 나머지 데이터를 다음번에 읽으므로 enter까지 입력된 모든 문자열을 출력

     

    3. public int read(byte[] data, int offset, int length) thorws IOException

     

    스트림으로부터 length개의 데이터를 읽어서 data 배열의 offset 위치부터 차례로 저장

    읽은 데이터 수 반환, 스트림 마지막 경우 -1반환

    이 메소드를 사용하면 enter 키로 구분된 다수의 문장을 버퍼에 저장 할 수 있다.

     

    예제 1.6 ReadCharactersOffset.java

    import java.io.*;
    class ReadCharactersOffset {
    	public static void main(String[] args) throws java.io.IOException {
    		try {
    			int bufferSize=80; // 버퍼의 크기
    			int size=0; // 버퍼에 저장된 데이터의 수를 저장함
    			int dataRead; // 스트림으로부터 읽혀진 데이터의 수
    			byte buffer[]=new byte[bufferSize];
    			while((dataRead=System.in.read(buffer,size,bufferSize-size))>=0) {
    			// buffer 배열에 enter 키까지 입력된 데이터를 차례로 저장함
    				size+=dataRead;
    			}
    			System.out.write(buffer,0,size); // buffer의 내용을 출력함
    		}catch(IOException e) {
    			System.err.println("스트림으로부터 데이터를 읽을 수 없습니다.");
    		}
    	}
    }
    

    실행결과

    CTRL + Z 를 눌러 종료

    while 문에서 enter 로 구분된 다수의 문장을 읽어서 배열에 저장

     

    예제 1.7 ReadCharactersIncr.java

    import java.io.*;
    class ReadCharactersIncr {
    	static int size =0;
    	static int bufferSize=80;
    	static byte buffer[] = new byte[bufferSize];
    	public static void main(String[] args) throws java.io.IOException {
    		try {
    			int dataRead;
    			while((dataRead=System.in.read(buffer,size,bufferSize-size))>=0) {
    				size+=dataRead;
    				if(size==bufferSize)
    					increaseBufferSize();
    			}
    			System.out.write(buffer,0,size);
    		}catch(IOException e) {
    			System.err.println("스트림으로부터 데이터를 읽을 수 없습니다.");
    		}
    	}
    	static void increaseBufferSize() {
    		bufferSize+=80;
    		byte[] newBuffer=new byte[bufferSize];
    		System.arraycopy(buffer, 0, newBuffer, 0, size);
    		buffer = newBuffer; // buffer 배열이 크기가 80개 늘어난다.
    	}
    }
    

     버퍼가 꽉 차면 자동으로 버퍼의 크기를 80 바이트 만큼 늘려서 저장하므로 어떠한 크기의 데이터도 읽을 수 있다. (예제 1.6 보완)

     

    4. public int available() throws IOException

    입력 스트림으로부터 블록킹없이 읽어올 수 있는 데이터의 수 반환

    읽기 가능한 데이터가 없는 경우 0을 반환

     

    ex) 읽기 가능한 데이터의 수만큼 배열의 크기를 설정

    try{
    	byte[] data = new byte[System.in.available()];
        	System.in.read(data);
    }catch(IOException e){System.err.println("데이터를 읽을 수 없습니다.");

    5. public long skip(long n) throws IOException

    n 바이트 수만큼을 읽지 않고 스킵하는 기능

    실제로 스킵한 바이트 수를 반환, 스트림의 끝을 만나면 -1 반환

    ex) 80바이트 스킵하기

    try{
    	long bytesSkipped=0;
        	long bytesToSkip=80;
        	while(bytesSkipped < bytesToSkip){
        		long n=in.skip(bytesToSkip - bytesSkipped);
            	if(n==-1) break;
            	bytesSkipped += n;
        	}
    }catch(IOException e){System.err.println(e);

    6. public void close() thorws IOException

    실행중인 스트림이 사용하는 파일 핸들 또는 포트와 같은 자원을 해지하는 기능

    System.in은 보통 닫을 필요가 없다. 실행중인 입력 스트림을 닫았을 때, 닫혀진 스트림을 통하여 읽는다면 IOException 예외가 발생.

    try {
    		URL u = new URL("http://www.ssc.ac.kr/");
    		InputStream in =u.openStream();
    		// 스트림으로부터 데이터를 읽어오기...
    		in.close(); // 입력 스트림을 닫는다.
    	}catch(IOException e) {
    		System.err.println(e);
    	}

    7,8은 같이 사용

    7. public synchronized void mark(int readlimit)

    8. public synchronized void reset() throws IOException

    데이터를 읽고 있을 때, 읽고 있는 데이터에 마킹을 하고 계속해서 후의 데이터를 읽는 도중에 마킹을 리셋하면 이전에 마킹한 데이터부터 다시 데이터를 읽는 기능이 필요한 경우 사용

    mark(int readlimit) 메소드는 현재 읽고 있는 데이터를 마크하고 데이터를 읽는 중에 reset() 메소드를 수행하면 이전에 마크한 위치의 데이터부터 다시 읽는 기능을 수행

    readlimit 인수가 지정한 수보다 많은 데이터를 읽었다면 IOException 예외가 발생

     

    9. public boolean markSupported()

    마킹 기능의 지원유무를 알려준다. ture -> 마킹을 지원 false -> 미지원

    마킹을 지원하지 않는 스트팀에 마킹과 리셋 기능을 구현하면, mark() 아무 일도 안 하고 reset()는 IOException 예외 발생

    예제 1.8 StreamCopier.java

    import java.io.*;
    class StreamCopier {
    	public static void main(String[] args) {
    		try {
    			copy(System.in,System.out);
    			// System.in은 키보드, System.out은 모니터를 의미함
    		}catch(IOException e) {
    			System.err.println("스트림으로부터 데이터를 읽을 수 없습니다.");
    		}
    	}
    
    	public static void copy(InputStream in, PrintStream out) throws IOException {
    		int bytesRead;
    		byte[] buffer = new byte[256];
    		synchronized(in) {
    			synchronized(out) {
    				while((bytesRead=in.read(buffer))>=0) {
    					out.write(buffer,0,bytesRead);
    				}
    			}
    		}
    	}
    }
    

    실행결과

    copy() 메소드는 키보드에서 입력한 데이터를 모두 읽어 모니터로 출력한다. CTRL-Z키를 누르면 탈출한다.

     

    FileOutputStream 클래스

     

    OutputStream 클래스이 하위 클래스

    프로그램과 파일사이에 스트림을 연결하여 메모리의 내용을 바이트 단위로 읽어서 파일로 저장

    기존의 파일 지정을 해야한다. 인수들은 특정한 파일을 지정한다.

     

    1. 생성자의 인수 직접 인수로 폴더 및 파일이름

    2. File 및 FileDescriptor 객체를 사용하여 파일을 지정

     

    호출한 객체의 FileDescriptor 객체를 반환하는 getFd() 메소드를 지원

    pulic final FileDescriptor getFD() throws IOException

    예제 1.9 WriteToFile.java

    키보드로 입력된 문자를 지정한 파일에 저장하는 클래스

    import java.io.*;
    class WriteToFile {
    	static FileOutputStream fout;
    	public static void main(String[] args) {
    		try {
    			int bytesRead;
    			byte[] buffer = new byte[256];
    			fout=new FileOutputStream("example1_9.txt");
    			while((bytesRead=System.in.read(buffer))>=0) {
    				fout.write(buffer,0,bytesRead);
    				//키보드로부터 데이터 입력 -> 메모리 저장 -> 파일로 저장
    			}
    		}catch(IOException e) {
    			System.err.println("스트림으로부터 데이터를 읽을 수 없습니다.");
    		}finally{
    			try {
    				if(fout!=null) fout.close();
    			}catch(IOException e) {}
    		}
    	}
    }
    

     

     

    키보드로부터 데이터를 읽어서 파일로 저장하는 클래스는 없기 때문에, while문을 사용하여 데이터를 읽음.

     

    예제 1.10 WriteToFileEvent.java

    첫 번째 텍스트필드에 입력된 파일에 두 번째 텍스트필드 내용을 저장하는 클래스

    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    class WriteToFileEvent extends Frame implements ActionListener {
    	Label lfile,ldata;
    	TextField tfile,tdata;
    	Button save;
    	String filename, data;
    	byte buffer[]=new byte[80];
    	
    	public WriteToFileEvent(String str) {
    		super(str);
    		setLayout(new FlowLayout());
    		lfile=new Label("파일이름을 입력하세요");
    		add(lfile);
    		tfile=new TextField(20); // 파일이름을 입력하는 텍스트 필드
    		add(tfile);
    		ldata=new Label("저장할 데이터를 입력하세요");
    		add(ldata);
    		tdata=new TextField(20); // 저장할 데이터를 입력하는 텍스트 필드
    		add(tdata);
    		Button save = new Button("저장하기");
    		save.addActionListener(this); // 이벤트 등록
    		add(save);
    		addWindowListener(new WinListener());
    	}
    	public static void main(String[] args) {
    		WriteToFileEvent text = new WriteToFileEvent("파일저장");
    		text.setSize(270,150);
    		text.setVisible(true);
    	}
    	public void actionPerformed(ActionEvent ae) { // 엔터 키를 입력하면 실행
    		filename=tfile.getText(); // 파일이름을 읽음
    		data=tdata.getText(); // 저장할 데이터를 읽음
    		buffer = data.getBytes(); // 바이트 데이터를 변환함
    		try {
    			FileOutputStream fout=new FileOutputStream(filename);
    			fout.write(buffer); // 메모리의 내용을 파일에 저장 getBytes() 확인해볼것
    		}catch(IOException e) {
    			System.out.println(e.toString());
    		}
    	}
    	class WinListener extends WindowAdapter { // 콘솔의 X창 클릭시 종료하게 해주는 클래스
    		public void windowClosing(WindowEvent we) {
    			System.exit(0);
    		}
    	}
    }
    

     FileOutputStream 클래스는 바이트 단위로 데이터를 전송하므로 텍스트 필드에 저장된 문자를 getBytes() 메소드를 사용하여 바이트 데이터로 변환시켜야 한다.

    실행결과

     

    FileInputStream 클래스

     

    InputStream 클래스의 하위 클래스

    read() 메소드를 사용해서 특정한 파일의 내용을 읽어서 메모리에 저장하는 기능

     

    예제 1.11 ReadFromFile.java example1_9.txt 파일의 내용을 화면에 출력하는 클래스

    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    class ReadFromFile  {
    	public static void main(String[] args) {
    		int bytesRead;
    		byte[] buffer=new byte[256];
    		FileInputStream fin = null;
    		try {
    			fin =new FileInputStream("example1_9.txt");
    			while((bytesRead=fin.read(buffer))>=0) { // 파일 -> 메모리
    				System.out.write(buffer,0,bytesRead); // 메모리 -> 화면출력
    				// 파일의 데이터를 읽음 -> 메모리 저장 -> 화면에 출력 순서
    			}
    		}catch(IOException e) {
    			System.err.println("스트림으로부터 데이터를 읽을 수 없습니다.");
    		}finally {
    			try {
    				if(fin!=null) fin.close();
    			}catch(IOException e) {}
    		}
    	}
    }
    

    실행결과

     파일의 내용을 읽어서 화면에 출력하는 기능을 하는 클래스는 없기 때문에, 메모리에 저장하고 출력해야 한다.

    while문은 파일의 내용을 한 줄씩 읽어서 메모리에 저장 후 출력한다.

     

    예제 1.12 ReadFromFileEvent.java example1_10.txt 파일을 읽어서 Textarea에 출력하는 클래스

    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    class ReadFromFileEvent extends Frame implements ActionListener {
    	Label lfile;
    	TextField tfile;
    	TextArea tadata;
    	String filename;
    	
    	public ReadFromFileEvent(String str) {
    		super(str);
    		setLayout(new FlowLayout());
    		lfile=new Label("파일이름을 입력하세요");
    		add(lfile);
    		tfile=new TextField(20);
    		tfile.addActionListener(this);
    		add(tfile);
    		tadata=new TextArea(3,35); // 읽은 파일을 보여줌
    		add(tadata);
    		addWindowListener(new WinListener());
    	}
    	public static void main(String[] args) {
    		ReadFromFileEvent text = new ReadFromFileEvent("파일읽기");
    		text.setSize(270,150);
    		text.setVisible(true);
    	}
    	public void actionPerformed(ActionEvent ae) { // 엔터 키를 입력하면 실행
    		byte buffer[]=new byte[100];
    		filename=tfile.getText();
    		try {
    			FileInputStream fin=new FileInputStream(filename);
    			fin.read(buffer); // 파일의 내용을 읽는다.
    			String data=new String(buffer); // 배열의 내용을 문자열로 변환
    			tadata.setText(data+"\n"); // 읽은 내용을 텍스트 에리어에 출력한다.
    		}catch(IOException e) {
    			System.out.println(e.toString());
    		}
    	}
    	class WinListener extends WindowAdapter { // 콘솔의 X창 클릭시 종료하게 해주는 클래스
    		public void windowClosing(WindowEvent we) {
    			System.exit(0);
    		}
    	}
    }
    

     실행결과

    파일이름을 입력하고 엔터를 누르면 ActionEvent 이벤트가 발생하여 이벤트 처리 함수를 자동으로 실행

    buffer 바이트 배열에 저장된 데이터는 문자열로 바꿔야 한다.

     

    예제 1.13 FileCopier.java example1_9.txt라는 파일의 내용을 example1_13.txt라는 파일로 복사하는 클래스

    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    class FileCopier{
    	
    	public static void main(String[] args) {
    		int bytesRead;
    		byte[] buffer=new byte[256];
    		FileInputStream fin=null;
    		FileOutputStream fout=null;
    		try {
    			fin=new FileInputStream("example1_9.txt");
    			fout=new FileOutputStream("example1_13.txt");
    			while((bytesRead=fin.read(buffer))>=0) { // 소스파일 -> 메모리
    				fout.write(buffer,0,bytesRead); // 메모리 -> 목적지파일
    			}
    		}catch(IOException e) {
    			System.err.println("스트림으로부터 데이터를 읽을 수 없습니다.");
    		}finally {
    			try {
    				if(fin!=null) fin.close();
    				if(fout!=null) fout.close();
    			}catch(IOException e) {}
    		}
    	}
    	
    }
    

     실행결과

    파일의 내용을 읽어서 바로 다른 파일에 저장시키는 기능을 가진 클래스는 없으므로, 메모리라는 중간 매체를 이용해서 옮겨야 한다.

    댓글

© 2018 TISTORY. All rights reserved.