-
- 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
- 파일 입출력 클래스
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