입출력(I/O)
- I/O란 Input과 Output의 약자로 입력과 출력, 간단히 줄여서 입출력이라고 한다. 입출력은 컴퓨터 내부 또는 외부의 장치와 프로그램간의 데이터를 주고받는 것을 말한다.
- 입력의 근원지에서 InputStream을 거쳐 JVM에 데이터가 들어가고, JVM에서 Output Stream을 통해 출력의 목적지로 데이터를 내보낸다.
└ 입력의 근원지 : 시스템(키보드의 입력), 파일, 네트워크(net, socket)
└ 출력의 목적지 : 시스템(모니터). 파일(HDD), 네트워크
스트림(stream)
- 데이터를 전달할 두 대상을 연결하고 데이터를 전송할 수 있는 무언가가 필요한데 이것을 스트림이라고 한다. 즉, 스트림은 데이터를 운반하는데 사용되는 연결통로이다.
- 스트림은 단방향통신만 가능하기 때문에 하나의 스트림으로 입력과 출력을 동시에 처리할 수 없다. 따라서 입력과 출력을 위한 입력스트림(input stream)과 출력스트림(output stream)이 필요하다.
- 스트림은 먼저 보낸 데이터를 먼저 받게 되어있다. 큐와 같은 FIFO구조로 되어 있다.
- java.io package에서 stream을 제공한다.
- 크게 바이트기반 스트림과 문자기반 스트림으로 나뉜다.
바이트기반 스트림(InputStream, OutputStream), 8bit Stream
읽기(InputStream)
└DataInputStream
└FileInputStream
└ObjectInputStream
...
쓰기(OutputStream)
└FileOutputStream
└ObjectOutputStream
...
- 바이트단위로 데이터를 전송한다. 입출력의 단위가 1byte라는 뜻이다.
- 모든 데이터의 읽기와 쓰기가 가능하다.
- 속도가 빠르지만 한번에 움직이는 데이터의 양이 적다.
문자열 기반 스트림(Reader, Writer), 16bit Stream
읽기(Reader)
└FileReader
└BufferedReader
└InputStreamReader(8bit와 16bit연결)
...
쓰기(Writer)
└FileWriter
└BufferedWriter
...
- C언어와 달리 Java에서는 한문자를 의미하는 char형이 1byte가 아니라 2byte이기 때문에 바이트기반의 스트림으로 2byte인 문자를 처리하는 데는 어려움이 있다. 이 점을 보완하기 위해서 문자기반의 스트림이 제공된다. 문자데이터를 입출력할 때는 바이트기반 스트림 대신 문자기반 스트림을 사용해야한다.
- 속도는 느리지만 한번에 움직이는 데이터의 양이 많다.
FileInputStream
- FileInputStream(File file)
Creates a FileInputStream by opening a connection to an actual file, the file named by the File object file in the file system.
- FileInputStream(FileDescriptor fdObj)
Creates a FileInputStream by using the file descriptor fdObj, which represents an existing connection to an actual file in the file system.
- FileInputStream(String name)
Creates a FileInputStream by opening a connection to an actual file, the file named by the path name name in the file system.
- int read()
Reads a byte of data from this input stream.
데이터의 코드값이 리턴된다.(코드값 확인하기 : 이클립스 - alt를 누른 상태에서+코드값을 적은 후 손을 때면 문자가 적혀진다.)
한글은 유니코드이므로 이 값을 확인할 수 없다. 또한 위 read()는 1byte씩 읽어오는데 한글은 2byte이므로 강제로 잘려져 들어오게 된다.
[참고] "를 문자열로 나타내기 위해서는 \특수문자 형식으로 써주어야 한다. (ex. \n, \r(return : 커서를 가장 앞으로), \t, \b(backspace), \', \", \\, \f(printer new line))
-------------------------------------------------------------------
// '\'뒤에는 정의된 예약어가 들어와야하므로 에러
//System.out.println("c:\dev\test.txt");
// 따라서 '\'를 표현하기 위해서는 '\\'라고 명시해주어야 한다.
System.out.println("c:\\dev\\test.txt"); // \ window의 경로으 경로 표기 방법
System.out.println("c:/dev/test.txt"); // / unix의 경로 표기 방법
-------------------------------------------------------------------
파일의 경로를 문자열로 넣을 경우 가장 큰 문제점은 파일의 정보를 알 수가 없다. 따라서 FileNotFoundException의 예외에 대해 처리해주어야 한다. 이보다 좋은 방법은 File클래스를 이용하는 것이다. File클래스를 이용하면 파일에 대한 정보를 얻을 수 있다.
File
- File(File parent, String child)
Creates a new File instance from a parent abstract pathname and a child pathname string.
- File(String pathname)
Creates a new File instance by converting the given pathname string into an abstract pathname.
- File(String parent, String child)
Creates a new File instance from a parent pathname string and a child pathname string.
- File(URI uri)
Creates a new File instance by converting the given file: URI into an abstract pathname.
- BufferedReader(Reader in)
Creates a buffering character-input stream that uses a default-sized input buffer.
- BufferedReader(Reader in, int sz)
Creates a buffering character-input stream that uses an input buffer of the specified size.
- String readLine()
Reads a line of text.
- 문자열을 리턴한다. 읽은 내용이 없을 경우 null을 리턴한다.
InputStreamReader
- InputStreamReader(InputStream in)
Creates an InputStreamReader that uses the default charset.
- InputStreamReader(InputStream in, Charset cs)
Creates an InputStreamReader that uses the given charset.
- InputStreamReader(InputStream in, CharsetDecoder dec)
Creates an InputStreamReader that uses the given charset decoder.
- InputStreamReader(InputStream in, String charsetName)
Creates an InputStreamReader that uses the named charset.
- 8bit와 16bit를 연결해주고 charset를 변경해준다.
바이트기반 스트림과 문자열 기반 스트림을 이용하여 *.txt파일 읽어들이기
- java_read.txt파일을 읽어들이는 예제이다.
- 파일의 데이터는 바이트기반의 FileInputStream을 통해 읽어들이고 파일이 한글로 작성되었으므로 JVM은 문자열기반의 BufferedReader로 받는다. 이때 두 스트림의 비트가 달라 연결되지 않으므로 중간자 역할로 InputStreamReader로 중계해준다.
------------------------------------------------
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
[참고] 메서드 참고 참고하길
------------------------------------------------
public class TestFileRead {
public static void main(String[] args) {
// 해당 경로에 파일이 있는지 판단하고 파일의 정보를 얻기 위해서 File Class를 사용한다.
File file = new File("C:/.../java_read.txt");
if(file.exists()){ // 파일의 존재 유무 확인
// 존재하면 파일 읽기 시작
try {
//1. 파일에 스트림 연결
BufferedReader br = new BufferedReader(new FileReader(file)); // fileReader() throws FileNotFoundException
//2. 파일의 내용 읽기
//2-1. 한줄씩 읽기
/*
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine()); // 더이상 참조하는 주소가 없으면 null을 반환
*/
//2-2. 한글자 읽기
//System.out.println((char)br.read());
/*
* 주의!
* 16bit스트림이므로 한글이 잘 나오지만 8bit스트림일 경우 나오지 않는다.
* 파일과 프로그램의 인코딩셋이 맞지 않으면 깨진다.
*/
//2-3. 반복문을 이용하여 한줄씩 읽기
String line = ""; // 파일로부터 읽어온 줄을 저장하기 위한 변수
while((line = br.readLine()) != null){ // 읽어온 값이 null이 아니라면 반복한다. 즉, 파일의 끝이 아니라면
System.out.println(line.replace("이진기", "우주미남").replace("진기", "춤신춤왕"));
//replace(oldChar, newChar)을 이용하여 읽어들인 정보를 가송할 수도 있다.
/*
* 유용!
* 메서드 체인을 이용하여 한글자씩 띄어진 글자도 처리할 수 있다.
* 이런 점을 이용하여 비속어 처리를 할 수 있다.
* ex) 개놈 or 개 놈 ----(비속어처리)----> ☆ ★
* replace("개놈","☆★") or replace("개","☆").replace("놈","★")
*/
}
//3. 연결 끊기
br.close(); // close() throws IOException
} catch (FileNotFoundException e) {
/*
* 예외처리 팁!
* 1.7버전에 추가된 문법 catch (xxxxxxException | xxxxxxException 변수명)
* '|'를 사용하여 여러 exception을 묶어줄 수 있다.
* 상속의 관계가 있는 예외들을 묶으면 에러!(부모로 모두 받을 수 있으므로)
* 여기서는 IOException -> FileNotFoundException의 관계를 가진다.
*/
System.err.println("입력하신 경로에 파일이 존재하지 않습니다.");
e.printStackTrace();
} catch (IOException e) {
System.err.println("스트림에 문제 발생");
e.printStackTrace();
}
}
else
System.out.println("파일 없음. 경로를 확인해주세요.");
}
}
'예전 포스팅 모음' 카테고리의 다른 글
Web이란? (0) | 2014.10.23 |
---|---|
[tomcat] 톰캣 소개 및 설치 (0) | 2014.10.22 |
[java] Collection (0) | 2014.10.20 |
[DB] CRUD, Package, Trigger, 백업, 복구 (0) | 2014.10.10 |
[DB] pl/sql 문 예제(이메일 검증, 주민등록번호 유효성 검증) (0) | 2014.10.08 |