ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 입출력(I/O)
    Java 2021. 11. 29. 09:51

     

    - Input인지 Reader인지에 따라 몇바이트를 입력받는지 판단

    (그동안은 Scanner를 통해 콘솔에서만 입출력 받음)

     

     

     

    <콘솔에서 문자를 입력받아 출력하기>

     

    - InputStream : byte단위로 입력받음 / return값이 아스키코드의 int값

                        -> 1byte씩 읽기때문에 한글을 입력하고 char변환해도 이상하게 반환됨

     

    - InputStreamReader : 글자단위로 인식. 한글은 2byte 영어나 숫자는 1byte로 알아서 인식함

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    
    public class InputStreamTest {
    	public InputStreamTest() {
    		
    		// io exception처리
    		
    		try {
    			// 콘솔(InputStream)에서 1byte씩 읽어온다 (반환값이 int형임)
    			InputStream is = System.in;
    			while(true) {
    				int data = is.read();
    				// 읽은 byte가 없을때는 -1 리턴
    				if(data==-1) break;
    				System.out.println(data);  // (char)data로 해도 한글은 인지못함 - 1byte씩 읽기때문에
    			}
    			
    			// 문자단위로 읽어오기
    			InputStreamReader isr = new InputStreamReader(System.in);
    			while(true) {
    				int readerData = isr.read();
    				if(readerData==-1) break;
    				System.out.println(readerData);
    			} // 13, 10은 엔터를 의미
    			
    		}catch(IOException ie) {
    			System.out.println("byte입력 예외발생->" + ie.getMessage());
    		}		
    	}
    	public static void main(String[] args) {
    		new InputStreamTest();
    	}	
    }

     

    InputStream 과 InputStreamReader 는 한 글자단위씩 읽어들이는 반면

    Buffer에 담으면 엔터(1줄)단위로 읽어들임

     

    - BufferedReader :  버퍼에서 한줄의 문자열을 읽을 수 있는 메소드를 제공 (엔터칠때까지)

                              문자 기반 처리

                              BufferedReader를 만들려면 InputStreamReader가 필요함

     

    - BufferedInputStream :  byte단위로 데이터 처리

     

    //Buffer
    
    import java.io.BufferedInputStream;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class BufferedReaderTest {
    	public BufferedReaderTest() { // BufferedReader를 만들려면 InputStreamReader가 필요함
    		
    		InputStreamReader isr = new InputStreamReader(System.in);
    		// 버퍼에서 한줄의 문자열을 읽을 수 있는 메소드를 제공 (엔터칠때까지)
    		BufferedReader br = new BufferedReader(isr);
    		
    		try {
    			String inData = br.readLine(); // 입력값이 없으면 null반환
    			System.out.println(inData);
    		}catch(IOException ie){
    			ie.printStackTrace();			
    		}
    		
    		
    		try {
    			BufferedInputStream bis = new BufferedInputStream(System.in);
    			byte[] data = new byte[50];  // 입력한 정보가 담김 --> byte배열을 다시 문자열로 바꾸어 출력
    			// 입력byte 수
    			int size = bis.read(data);
    					
    			// byte배열을 문자열로 변환
    			String str = new String(data, 0, size-2);
    			System.out.println(str);
    			
    		}catch(IOException ie){
    			ie.printStackTrace();			
    		}		
    	}
    
    	public static void main(String[] args) {
    		new BufferedReaderTest();
    	}
    }

     

    < buffer에 관한 추가 내용 - 성능 향상 보조 스트림 >

     프로그램의 성능은 입출력이 가장 늦은 장치를 따라감

    => CPU와 메모리가 좋다고 하더라도 하드 디스크의 입출력이 늦어지면 프로그램의 실행 성능은 하드 디스크 처리속도에 맞춰감. 네트워크도 느린 네트워크 환경이면 컴퓨터 성능이 좋아도 메신저나 게임의 속도가 느려짐.

    => 완전한 해결책 X / 프로그램이 입출력 소스와 직접 작업하는 대신 중간에 메모리 버퍼와 작업함으로써 실행 성능 향상 가능.

    바이트 기반 성능 향상 보조 스트림 : BufferedInputStream / BufferedOutputStream

    문자 기반 성능 향상 보조 스트림 :  BufferedReader / BufferedWriter

     

    https://rimkongs.tistory.com/2904

     

    [Java] BufferedInputStream 와 BufferedReader

    프로그램의 실행 성능은 입출력이 가장 늦은 장치를 따라간다. CPU와 메모리가 아무리 뛰어나도 하드 디스크의 입출력이 늦어지면 프로그램의 실행 성능은 하드 디스크의 처리 속도에 맞춰진다.

    rimkongs.tistory.com

     

    • 파일 입출력 클래스

    C:\javaSrc\Test.java   FileInputStream / FileReader 를 통해 파일 입력받기

    new File(드라이브명/경로/파일명/확장자)  // 절대주소로 입력, 파일명은 꼭 없어도 됨

     

    - 자바에서 모든 파일 생성, 삭제 제어하기

    import java.io.File;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    
    public class FileTest {
    	// File클래스 : 드라이브명, 경로명, 파일명으로 객체를 생성
    	// 			  경로는 반드시 절대주소 (내가 있는 위치는 상관 없음. 드라이브 위치부터 지정)
    
    	public FileTest() {
    		File f1 = new File("C://test");
    		// 파일 또는 경로가 있는지 확인 - 있으면 true 없으면 false
    		if(f1.exists()) {
    			System.out.println("폴더가 존재");
    		}else {
    			System.out.println("폴더가 존재하지 않음");
    			f1.mkdir(); // mkdirs : 하위경로까지 모두 만들어줌
    		}
    		File f2 = new File("c://javaSrc/Test.java");
    		File f3 = new File(f1, "sample.txt");
    		
    		/*
    		 파일경로, 파일명 출력 
    		 getPath() : 파일경로 + 파일명 
    		 getName() : 파일명 
    		 getAsolutePath() : 파일경로 + 파일명 
    		 getParent : 파일경로
    		 */
    		System.out.println("getPath->" + f1.getPath());
    		System.out.println("getName->" + f1.getName());
    		System.out.println("getParent->" + f1.getParent());
    		
    		System.out.println("==================");
    		
    		// 파일의 마지막 수정일 출력
    		long date = f2.lastModified();
    		System.out.println("date-> " + date); // 출력형태 변환 필요
    		
    		Calendar nowDate = Calendar.getInstance();
    		nowDate.setTimeInMillis(date);
    		SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd a hh:mm:ss");
    		String lastEditDate = fmt.format(nowDate.getTime());
    		System.out.println("lastEditDate-> " + lastEditDate);
    		
    		System.out.println("==================");
    		
    		// c드라이브의 폴더와 파일목록 얻어오기
    		File f4 = new File("c://");
    		File list[] = f4.listFiles();
    		
    		for(File f:list) {
    			String pathName = f.getPath();
    			if(f.isDirectory()) { // 폴더
    				if(f.isHidden()) { // 숨김
    					System.out.println(pathName + "[숨김폴더]");
    				}else {
    					System.out.println(pathName + "[폴더]");
    				}
    				
    			}else { // 파일
    				if(f.isHidden()) { 
    					System.out.println(pathName+"[숨김파일]");
    				}else {
    					System.out.println(pathName+"[파일]");
    				}
    			}
    		}
    		System.out.println("==================");
    		// 현재 시스템의 하드정보 가져오기
    		File[] root = File.listRoots();
    		for(File f : root) {
    			System.out.println("시스템 하드정보->" + f.getPath());
    		}
    		
    		// 파일크기
    		long byteSize = f2.length();
    		System.out.println("파일크기->" + byteSize);
    		
    		// 파일생성
    		try {	
    			f3.createNewFile();			
    		}catch(Exception e) {}
    		
    		// 파일삭제
    		f3.delete();
    	}
    
    	public static void main(String[] args) {
    		new FileTest();
    	}
    }

     

     

    < 파일을 입력받아 파일로 쓰기 / 콘솔로 쓰기 >

     

    1) 파일을 읽어서 콘솔에 출력

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class FileReaderTest {
    	// 파일을 읽어서 콘솔에 출력
    	public FileReaderTest() {
    		File file = new File("C://javaSrc/Lotto.java"); // 파일객체 생성
    		
    		try {
    			FileReader fr = new FileReader(file); // 파일객체를 문자열로 읽어들이기
    			BufferedReader br = new BufferedReader(fr);
    			
    			// 1. buffer에 담아서 한줄씩 읽기
    			while(true) {
    				String str = br.readLine();
    				System.out.println(str);
    				if(str==null)break;
    			}
    			
    			
    			// 2. 배열에 담아 출력하기
    			// 굳이 buffer를 만들지 않아도 출력가능 but 작업단위가 한줄씩인 경우는 buffer활용
    			long size = file.length();
    			char data[] = new char[(int)size];
    			int readSize = fr.read(data, 0, (int)size); // 몇 byte읽었는지 
    			// char배열을 string으로 변환
    			String s1 = new String(data);      // s1과 s2는 동일
    			String s2 = String.valueOf(data);
    			
    			System.out.println(s1);
    			System.out.println(s2);
    			
    		}catch(FileNotFoundException fnfe) {
    			System.out.println("파일이없습니다ㅠㅡㅠ");
    		}catch(IOException ie) {
    			System.out.println("파일읽기 예외발생...");
    		}
    		
    	}
    
    	public static void main(String[] args) {
    		new FileReaderTest();
    	}
    
    }

     

    2)  이미지파일 읽어서 다른 폴더에 복사하기

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class FileCopy {
    	public FileCopy(){
    		// 파일복사
    		File oriFile = new File("C://javaSrc//gobchang.jfif");
    		File tarFile = new File("C://test/gobchangCopy.jfif");
    		
    		try {
    			FileInputStream fis = new FileInputStream(oriFile);
    			FileOutputStream fos = new FileOutputStream(tarFile);
    			
    			// fis에서 byte를 읽어 fos로 쓰기
    			while(true) {
    				int inData = fis.read();
    				if(inData==-1) break;
    				fos.write(inData);
    			}
    			System.out.println("파일이 복사되었습니다.");
    		}catch(FileNotFoundException fnfe) {
    			System.out.println("파일이 없습니다.");
    		}catch(IOException i) {
    			System.out.println("입출력 예외발생");	
    		}
    	}
    
    	public static void main(String[] args) {
    		new FileCopy();
    
    	}
    }

     

    예제)  콘솔에서 라인별로 텍스트를 입력받아 Memo.txt파일로 생성하기

     

    /*
     첫번째줄: _____
     두번째줄: _____
     ..
     다섯번째줄: _____
     입력받아
     c://javaSrc/Memo.txt로 저장
     
     */

     

    - FileWriter 활용

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    
    public class FileWriterTest {
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	
    	// 한줄씩 입력받아야 하므로 buffer필요 -> buffer는 inputstream이 필요함
    	public FileWriterTest() {
    
    	}
    	
    	public void start() {
    
    		try {
    			// 파일 객체를 먼저 생성
    			File f = new File("c://javaSrc/memo.txt");
    			FileWriter fw = new FileWriter(f);
    			
    			for(int i=1; i<=5; i++) {
    				String data = console(String.valueOf(i));
    				fw.write(data +"\n");
    			}
    			fw.close();
    			
    		}catch(IOException ie) {
    			ie.printStackTrace();
    		}
    	}
    	
    	// 콘솔에서 입력받은 메시지를 출력하고, 입력으로 받기
    	public String console(String msg) {
    		String inData=null;
    		try {
    			System.out.print(msg + "번째 줄: ");
    			inData = br.readLine();
    		}catch(Exception e) {
    			System.out.println("콘솔입력에러");
    		}
    		return inData;			
    	}
    	
    	
    	public static void main(String[] args) {
    		new FileWriterTest().start();
    	}
    
    }

     

     

     

    <바이트단위로 >

     FileInputStream, FileOutputStream 은 바이트 단위로 데이터를 읽어들이는 클래스이다.

     

     

    * FileOutputStream

    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    
    public class DataOutputStreamTest {
    	public DataOutputStreamTest() {
    		
    		// 기본데이터형인 byte, short, int, long, float, double, char, boolean의
    		// 메모리 크기만큼 공간을 확보하여 값1을 파일로 쓰기한다.
    		
    		int intData = 123456;
    		double dblData = 2562.3421;
    		char charData = '홍';
    		boolean booData = true;
    		
    		try {
    			File f = new File("c://javaSrc", "data.txt");
    			FileOutputStream fos = new FileOutputStream(f);
    			DataOutputStream dos = new DataOutputStream(fos);
    			
    			dos.writeInt(intData);      // 4바이트를 확보해서 정수 받아들임
    			dos.writeDouble(dblData);   // 8바이트 확보해서 double형 데이터 받아들임
    			dos.writeChar(charData);
    			dos.writeBoolean(booData);
    			dos.writeChars("세종대왕");    // 메모장결과: 글자가 깨져서 나옴 --> byte단위로 바꿔서 입력
    			
    			// byte배열로 변경하여 파일에 쓰기를 한다
    			String txt = "이순신장군";
    			dos.write(txt.getBytes());   // writeChars(txt) 는 불가
    										 // byte단위로 데이터를 처리하기 때문에
    			dos.close();
    						
    		}catch(Exception e) {
    			System.out.println("예외발생->" + e.getMessage());
    		}
    		System.out.println("파일쓰기완료");
    
    	}
    
    	public static void main(String[] args) {
    		new DataOutputStreamTest();
    	}
    
    }

    메모장은 1바이트를 데이터로 받아들이기때문에 FileOutputStream으로 데이터를 내보내면 글자가 깨져서 나옴

     

     

    * FileInputStream

    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    
    public class DataInputStreamTest {
    	
    	public DataInputStreamTest() {
    		
    		try {
    			// 파일에서 데이터형으로 읽어오기
    			File f = new File("c://javaSrc/data.txt");
    			FileInputStream fis = new FileInputStream(f);
    			DataInputStream dis = new DataInputStream(fis);
    			
    			int intData = dis.readInt();        // 4byte
    			double dblData = dis.readDouble();  // 8byte
    			char charData = dis.readChar();
    			boolean booData = dis.readBoolean();
    			
    			// byte단위로 처리
    			byte[] byteData = new byte[100];
    			int cnt = dis.read(byteData);
    			String strData = new String(byteData);
    			
    			System.out.println("int->" + intData);
    			System.out.println("double->" + dblData);
    			System.out.println("char->" + charData);
    			System.out.println("boolean->" + booData);
    			System.out.println("str->" + strData);
    			
    		}catch(Exception e) {
    			e.printStackTrace();
    		}		
    			
    	}
    	
    
    	public static void main(String[] args) {
    		new DataInputStreamTest();
    	}
    }

     

    * ObjectOutputStream

    - 파일 자체에다가 쓰고, 읽기

    // getter, setter 클래스 생성
    
    import java.io.Serializable;
    import java.util.Calendar;
    import java.util.List;
    
    public class DataVO implements Serializable {
    	private Calendar now;
    	private String username;
    	private List<String> names;
    	private int num;
    	
    	
    	// getter, setter 자동 생성
    	public Calendar getNow() {
    		return now;
    	}
    	public void setNow(Calendar now) {
    		this.now = now;
    	}
    	public String getUsername() {
    		return username;
    	}
    	public void setUsername(String username) {
    		this.username = username;
    	}
    	public List<String> getNames() {
    		return names;
    	}
    	public void setNames(List<String> names) {
    		this.names = names;
    	}
    	public int getNum() {
    		return num;
    	}
    	public void setNum(int num) {
    		this.num = num;
    	}
    
    }

     

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.ObjectOutputStream;
    import java.util.ArrayList;
    import java.util.Calendar;
    import java.util.List;
    
    public class ObjectOutputStreamTest {  // 파일에다 쓰고 읽기
    	public ObjectOutputStreamTest() {
    		try {
    			File f = new File("C://javaSrc/object.txt");
    			FileOutputStream fos = new FileOutputStream(f);
    			ObjectOutputStream oos = new ObjectOutputStream(fos);
    			
    			DataVO vo = new DataVO();
    			vo.setUsername("손흥민");
    			vo.setNum(19);
    			// 날짜를 바꿔서 담기
    			Calendar now = Calendar.getInstance();
    			now.set(2025,9,12);
    			vo.setNow(now);
    			
    			List<String> lst = new ArrayList<String>();
    			lst.add("박태환"); lst.add("김연아"); lst.add("김연아");
    			lst.add("박지성");
    			vo.setNames(lst);
    			
    			// vo객체를 oos에 쓰고 저장 -> object.txt에 까지 저장됨
    			oos.writeObject(vo);
    			oos.close();
    			System.out.println("파일쓰기완료");
    			
    		}catch(Exception e) {
    			e.printStackTrace();
    		}
    		
    	}
    
    	public static void main(String[] args) {
    		new ObjectOutputStreamTest();
    
    	}
    }

     

    * ObjectInputStream

    - 파일에 있는 내용을 객체로 읽어오기

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.ObjectInputStream;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    
    public class ObjectInputStreamTest {
    	
    	public ObjectInputStreamTest() {
    		try {
    			File f = new File("c://javaSrc/object.txt");
    			FileInputStream fis = new FileInputStream(f);
    			ObjectInputStream ois = new ObjectInputStream(fis);
    			
    			DataVO vo = (DataVO)ois.readObject();
    			System.out.println("userName->" + vo.getUsername());
    			System.out.println("num->" + vo.getNum());
    			
    			Calendar date = vo.getNow();
    			SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
    			String dateStr = fmt.format(date.getTime());
    			System.out.println("date->" + dateStr);
    			
    			for(String n : vo.getNames()) {
    				System.out.println(n);
    			}
    			
    		}catch(Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	public static void main(String[] args) {
    		new ObjectInputStreamTest();
    	}
    
    }

     

     

     

    <RandomAccessFile>

     

    그동안은 입력과 출력을 각기 다른 클래스로 실행

    -> RandomAccessFile 클래스는 입력과 출력을 동시에 할수 있는 기능을 가지고 있음

     

    - seek(index) 메소드

    : 특정위치로 포인트를 옮겨놓고 글자를 쓸 수 있음

     

    import java.io.File;
    import java.io.RandomAccessFile;
    
    public class RandomAccessFileTest {
    	
    	public RandomAccessFileTest() {
    		try {
    			// RandomAccessFile: 입력과 출력을 같이 할 수 있는 객체
    			File f = new File("C://javaSrc/access.txt");
    			// mode: w (쓰기전용), r(읽기전용), rw(읽기쓰기가능)
    			RandomAccessFile raf = new RandomAccessFile(f,"rw");
    			
    //			// 문자열쓰기
    //			String txt = "Java inputoutputStream Test";
    //			raf.writeBytes(txt);
    //			
    //			// 특정 위치에 문자열 쓰기
    //			raf.seek(5); // index 5로 시작점 옮기기
    //			raf.writeBytes("RandomAccessFile");
    //			
    //			
    //			// 문자열 마지막에 int형 데이터 쓰기
    //			// 파일크기는 byte로 저장되있으므로 f.size이용
    //			raf.seek(f.length());
    //			raf.writeInt(12456);
    //			
    //			raf.close();
    //			System.out.println("쓰기완료..");
    			
    			
    			// 파일 읽기
    			byte[] inData = new byte[(int)f.length()];
    			raf.seek(0);
    			int cnt = raf.read(inData);
    			System.out.println("inData->" + new String(inData));
    			
    			// 맨끝에 숫자를 읽어오려면 커서를 움직여야함
    			raf.seek(27);
    			int intData = raf.readInt();
    			System.out.println(intData);
    			
    			raf.close();
    			System.out.println("읽기완료...");
    			
    		
    		}catch(Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	public static void main(String[] args) {
    		new RandomAccessFileTest();
    
    	}
    }

     

     

    'Java' 카테고리의 다른 글

    쓰레드(Thread)  (0) 2021.12.01
    객체지향프로그래밍 (한화인턴교육)  (0) 2021.11.29
    상속 과제물  (0) 2021.11.25
    Collection  (0) 2021.11.25
    예외처리  (0) 2021.11.25

    댓글

Designed by Tistory.