IO 입력과 출력 (Input Output)
표준 IO
모니터와 키보드
IO (Input Output) → NIO(New Input Output)
- IO를 쉽게 쓸 수 있게 해줌
- 쉽게 쓸 수 있기 때문에 숨겨진 맥락이 있다.
- IO를 더 공부하고 싶으면 NIO 공부하면 좋다.
1. java.io.*
- 입출력은 java.io.에 모두 있다.
- java.lang에 있던 입출력은 java.io.패키지에서 가져온 것이다.
2. Stream
- 모든 입출력 구조는 Stream으로 이루어져있다.
- Stream은 시냇물이다. 시냇물의 특징은 단방향이고 순서대로 흘러간다.
1) 단방향
2) 원칙적으로 순차적
- 원칙적으로 순차적이지만 그렇지 않을 때도 있다.
3) 지연발생이 가능하다.
4) 어떤 장치를 사용하던간에 사용법은 동일하다.
3. 자바에서 구현된 Steam객체
1) ByteStream
- 흘러들어오고 흘러나옴
- 1 바이트 씩 입출력을 하겠다.
- ByteStream이 컴퓨터가 이해할 수 있는 Stream이다.
- 사람이 쓰게에는 불편하다.
java.io에 부모이면서 추상클래스인
InputStream 과 OutputStream 두 가지 클래스가 있다.
추상클래스인지 알수 있는 이유는 abstract 때문이다.
추상클래스의 특징을 다시 살펴보자.
<추상 클래스>
- 추상메서드를 1개 이상 가지고 있는 경우
- abstract 키워드 사용
abstract class 클래스명{
}
- 절대로 인스턴스를 생성할 수 없다.
인스턴스가 없다 -> 실행할 수 없다. -> 직접일을 하지 않겠다.
내가 가지고 있는 것을 자식에게 물려주는 용도로만 사용.
자식을 위해 상속을 하는 의미로만 사용
예)
도형의 공통된 속성 A : 점, 선, 면적
사각형 : A 상속
원 : A 상속
삼각형 : A 상속
InputStream
- 추상메서드이다.
- 대표메서드는 read이다.
OutputStream
- 추상메서드이다.
- 대표메서드는 write이다.
2) CharacterStream
- 한 문자씩, 2바이트씩 입출력을 하겠다.
- 사람이 쓰기에는 편하다.
- CharacterStream써도 ByteStream으로 다시 바뀐다.
- 실제 컴퓨터 안에서는 ByteStream만 존재한다.
- CharacterStream은 개발자편의적인 일종의 포장지와 같다.
<개발자들 사이의 약속>
패키지 이름은 소문자로 한다.
클래스이름은 첫글자는 대문자로 한다.
<ByteStream알아보기>
read(byte[] b) 메소드
데이터를 읽을 때 byte로 읽는다.
예제 1)
package bitestream;
import java.io.IOException;
public class ByteTest1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
byte data[] = new byte[10];
System.out.println("10개의 문자 입력 : ");
//입력은 예외처리를 반드시 해줘야한다.
try { //아래 출력문을 시도해보고
System.in.read(data);
} catch (IOException e) { //에러의 종류가 무엇인지 확인하고 잡겠다.
// IOException 입출력 에러를 확인한다
e.printStackTrace(); //어디에서 에러가 났는지 추적해주겠다.
}
System.out.println("입력된 값 : ");
/*
for(int i = 0; i<data.length; i++) {
System.out.print((char)data[i]);
}
*/
//향상된 for문으로 써보기
for(byte b: data) {
System.out.println((char)b);
}
}
}
※ 결과값
10개의 문자 입력 :
sfasfasdfasdfafaf
입력된 값 :
sfasfasdfa
예제 2)
package bytestream;
import java.io.IOException;
public class ByteTest2 {
public static void main(String[] args) throws IOException {
//예외처리는 throws 로 한다.
int input = System.in.read();
//여기서 -1 은 키보드에서 ctrl + z를 누르면
//종료되는 약속된 값이다. java뿐만 아니라 다른 언어에서도 쓰인다. (주로 윈도우에서 가능)
while(input != -1) { // -1과 같으면 멈춘다.
System.out.print((char)input);
input = System.in.read();
}
}
}
※ 결과값
sadfsadfasdfasdfadsf
sadfsadfasdfasdfadsf
adsfsadfafasdfasfsdaafds
adsfsadfafasdfasfsdaafds
이렇게 코드스타일을 바꿀 수도 있다.
package bytestream;
import java.io.IOException;
public class ByteTest2 {
public static void main(String[] args) throws IOException {
/*
//예외처리는 throws 로 한다.
int input = System.in.read();
//여기서 -1 은 키보드에서 ctrl + z를 누르면
//종료되는 약속된 값이다. java뿐만 아니라 다른 언어에서도 쓰인다. (주로 윈도우에서 가능)
while(input != -1) { // -1과 같으면 멈춘다.
System.out.print((char)input);
input = System.in.read();
*/
int input = 0;
while(true) {
input = System.in.read();
if(input == -1) {
break;
}
System.out.print((char)input);
}
}
}
※ 결과값
kljhgfdskjlhdfskl;sdfh
kljhgfdskjlhdfskl;sdfh
sdfgkjhgadkljlkdhj
sdfgkjhgadkljlkdhj
svkxjhkljdh;kasdfjh
svkxjhkljdh;kasdfjh
또 이렇게도 코드스타일을 바꿀 수 있다.
package bytestream;
import java.io.IOException;
public class ByteTest2 {
public static void main(String[] args) throws IOException {
/*
//예외처리는 throws 로 한다.
int input = System.in.read();
//여기서 -1 은 키보드에서 ctrl + z를 누르면
//종료되는 약속된 값이다. java뿐만 아니라 다른 언어에서도 쓰인다. (주로 윈도우에서 가능)
while(input != -1) { // -1과 같으면 멈춘다.
System.out.print((char)input);
input = System.in.read();
*/
/*
int input = 0;
while(true) {
input = System.in.read();
if(input == -1) {
break;
}
System.out.print((char)input);
}
*/
int input=0;
while((input = System.in.read()) != -1){
System.out.print(((char)input));
}
}//main end
}//class end
※ 결과값
dafafdadgfafasdf
dafafdadgfafasdf
asfsadfsadfaf
asfsadfsadfaf
asdfasdfafadfafsafasfd
asdfasdfafadfafsafasfd
Java 입력장치의 가장 부모클래스는 InputStream이다.
InputStream은 추상클래스이며, 자식에게 참조하기 위해 있다.
다른 예제를 해보자
package bytestream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ByteTest2 {
//부모클래스이자 추상클래스인 InputStream이 참조변수 in을 받는다.
static void StreamTest(InputStream in, OutputStream out) throws IOException {
//예외처리는 throws 로 한다.
int input = System.in.read();
//여기서 -1 은 키보드에서 ctrl + z를 누르면
//종료되는 약속된 값이다. java뿐만 아니라 다른 언어에서도 쓰인다. (주로 윈도우에서 가능)
while(input != -1) { // -1과 같으면 멈춘다.
//outputstrim에는 출력하기 위한 메서드로 print가 없고 write가 있다.
//write메서드는 한글코드를 맞춰서 출력이 잘 된다.
//print, println은 간이용 출력이고, 출력전문은 write메서드이다.
out.write((char)input);
System.out.print((char)input);
input = System.in.read();
}
}
public static void main(String[] args) throws IOException {
//InputStream에게 in의 주소를 받기 위한 참조변수를 준다.
//in은 키보드 장치를 가리키는 참조변수이자 주소값이다.
//out은 모니터 장치를 가리키는 참조변수이자 주소값이다.
StreamTest(System.in, System.out);
/*
int input = 0;
while(true) {
input = System.in.read();
if(input == -1) {
break;
}
System.out.print((char)input);
}
int input=0;
while((input = System.in.read()) != -1){
System.out.print(((char)input));
}
*/
}//main end
}//class end
※ 결과값
ㄴㅁㅇㅁㄴㅇㅁ
ㄲ뇬¤ㄲ눙±ㄲ뉠·ㄲ눙±ㄲ뇬¤ㄲ뉠·ㄲ눙±
sdfdsafasdf
ssddffddssaaffaassddff
자바 IO 입출력의 특성상
파일로 출력해도 사용법은 똑같다.
파일로 입력받아 콘솔로 출력하는 예제를 해보자.
우선 test라는 파일을 만들고 위치를 적어보자.
나는 D:\\Dropbox\\workspaces\\MultiCampus\test.txt
에 만든 txt파일을 활용해보겠다.
package bytestream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
public class FileTest1 {
public static void main(String[] args) throws IOException {
// TODO 파일로부터 입력을 받아 콘솔로 출력
//파일명의 위치를 적는다.
//파일입력을 받는 인스턴스를 생성한다. 인자값에 입력받을 파일 이름을 넣는다.
//보조기억장치에 있던 text/txt 파일을 로딩하여 메모리에 저장공간을 만든다.
//test.txt 앞에 컴퓨터가 탭키 \t 로 인식하지 않도록 \를 하나 더 넣는다.
FileInputStream fin = new FileInputStream("D:\\Dropbox\\workspaces\\MultiCampus\\test.txt");
int input = 0;
while(input != -1) { //-1은 파일의 마지막을 뜻함
input = fin.read();
//print메서드는 아무런 준비없이 쓸 수 있다.
//System.out.print((char)input);
OutputStream out = System.out;
//write 버퍼로 출력
out.write((char)input);
//아직 다 차지않은 버퍼를 방출해준다.
out.flush();
}
//파일을 불러왔을 때 닫아주는 메서드이다.
//가까운 시일내에 가비지 컬렉션에서 인스턴스가 정리된다.
fin.close();
}
}
※결과값
우후후후후후우후우후우후우후우후우후우후
ADADADADADADADADADADADADADADADADADADADAD?
키보드로부터 입력받아 파일로 출력받는 예제를 해보자.
참고로 입력은 파일이 없으면 에러가 나지만 출력은 파일이 없으면 새로 만들어준다.
test2.txt 파일을 새로 만들어서 해보자.
package bytestream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileTest2 {
public static void main(String[] args) throws IOException {
// TODO 키보드로부터 입력받아 파일로 출력
//입력은 파일이 없으면 에러가 나지만 출력은 파일이 없으면 새로 만들어준다.
//새로운 내용을 입력받아 기존 내용을 지울 때는 false
//기존의 내용 뒤에 새로운 내용을 추가할 때는 true
FileOutputStream fout =
new FileOutputStream("D:\\Dropbox\\workspaces\\MultiCampus\\test2.txt", true);
int input = 0;
while(input != -1) { //ctrl + z 는 실행 중지.
input =System.in.read();
if(input == -1)
break;
fout.write((char)input);
fout.flush();
}
fout.close();
}
}
※ 결과값
gf,jndasflknasfdlknsdafk,lnsdafk,ln
lamdnlkdfn,lsfdnlksfdn
afdgsdfgsdfgsdfgsdfgsdfg
sfdgfsdgfdsgdsfgsdgffdsgs
sfdgsdfgsdfgsfgsfgsfg
D:\\Dropbox\\workspaces\\MultiCampus\\test2.txt
로 가면 이미 있는 파일 내용 뒤에 새로운 내용이 또 입력됨을 볼 수 있다.
test3.txt 파일을 새로 만들어서 아래 예제를 해보자.
package bytestream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileTest3 {
public static void main(String[] args) throws IOException {
FileOutputStream fout = new FileOutputStream("D:\\Dropbox\\workspaces\\MultiCampus\\test3.txt");
for(int i=1; i<10; i++) {
// \n은 줄바꿈이다.
// \r linfeed로 첫번째 위치로 옮겨놓는 것이다.
String data = i + "번째 줄입니다.\r\n";
System.out.println(data);
//문자열을 출력하려면 write는 bite로 쪼개서 넘겨야한다.
//String 메서드 중 getByte()를 이용한다.
fout.write(data.getBytes());
}
}
}
※ 결과값
1번째 줄입니다.
2번째 줄입니다.
3번째 줄입니다.
4번째 줄입니다.
5번째 줄입니다.
6번째 줄입니다.
7번째 줄입니다.
8번째 줄입니다.
9번째 줄입니다.
test3.txt 메모장에도 그대로 쓰인 것을 볼 수 있다.
<래퍼클래스와 필터클래스>
레퍼클래스는 비객체를 객체로 만들어 주는 클래스이다.
필터클래스는 객체를 더 확장 시켜서 더 많은 기능의 객체로 만들어준다.
필터클래스는 상속개념과 비슷하다. 실제 코드를 실시간으로 확장해서 쓰게 해준다.
java.io.FilterInputStream
java.io.DataInputStream
이 둘은 클래스의 기능을 바꾸어주는
필터클래스의 성향을 가진 클래스이다.
<ByteStream>
ByteStream은 Byte단위로 저장하기 때문에
자식클래스들이 등장해서 도와준다.
package bytestream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataTest {
public static void main(String[] args) throws IOException {
// TODO DataInputStream, DataOUtputStream
//DataInputStream, DataOUtputStream은 각각의 데이터타입의 맞게끔 기본데이터타입을 묶어서 처리해준다.
FileOutputStream fout = new FileOutputStream("D:\\Dropbox\\workspaces\\MultiCampus\\test4.txt");
//파일저장기능과 글자저장기능을 함께 쓴다.
DataOutputStream dout = new DataOutputStream(fout);
//글자를 저장해보자
dout.writeChar('가');
dout.writeInt(100);
dout.writeDouble(3.14);
dout.writeBoolean(true);
dout.close();
fout.close();
//test4.txt 파일을 열어보면 컴퓨터가 알아들을 수 있는 모양으로 저장되어 있다.
DataInputStream din =
new DataInputStream(
new FileInputStream("D:\\Dropbox\\workspaces\\MultiCampus\\test4.txt"));
//stream의 특성상 저장된 순서대로 호출해야한다.
System.out.println(din.readChar());
System.out.println(din.readInt());
System.out.println(din.readDouble());
System.out.println(din.readBoolean());
}
}
<RandomAccessFile>
IO의 특성상 순서대로 입출력이 되는데,
특이하게 임의대로 입력할 수 있는 클래스가 있다.
바로 Class RandomAccessFile 클래스이다.
이 클래스는 java.lang.Object를 상속받아 저장된 데이터를 임의로 접근해서 가져온다.
메모리 주소값을 이용해 접근한다.
package bytestream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) throws IOException {
int data[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
//다른 입출력 파일과는 다르게 RandomAccessFile로 저장 해야한다.
//"r"은 읽기전용, "rw"은 읽기쓰기이다.
RandomAccessFile raf =
new RandomAccessFile("D:\\Dropbox\\workspaces\\MultiCampus\\test5.txt","rw");
for(int i=0; i<data.length; i++) {
raf.writeInt(data[i]);
}
//파일을 실행시키면 test5.txt가 원하는 위치에 컴퓨터가 보기쉬운 값으로 저장되어있다.
//seek메서드는 원하는 위치를 찾아준다.
//실제 인덱스값이 아니라 메모리에 있는 포인터의 주소값이다.
//데이터가 정수형이라 4바이트임으로 바이트를 쪼개서 계산한다.
raf.seek(0);
System.out.println(raf.readInt());
raf.seek(8);
System.out.println(raf.readInt());
//4바이트 포인트의 3번째 방 = 40
//항상 메모리 주소값을 이용하여 접근한다.
raf.seek(4*3);
System.out.println(raf.readInt());
}
}
2. CharacterSteam
- 문자스트림은 실제하지 않는다.
- ByteStream을 편하게 하기 위한 일종의 포장지이다.
- ByteStream에 비해 편하게 쓸 수 있지만 성능이 떨어진다.
- 이름끝에 Reader라고 쓰여있으면 문자스트림이다.
reader 메서드 : 읽는다.
writer 메서드 : 쓴다.
문자스트림의 약점을 보완하기 위해 사용하는 클래스가 BufferedReader 이다.
package bytestream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
public class FileTest1 {
public static void main(String[] args) throws IOException {
// TODO 파일로부터 입력을 받아 콘솔로 출력
//파일명의 위치를 적는다.
//파일입력을 받는 인스턴스를 생성한다. 인자값에 입력받을 파일 이름을 넣는다.
//보조기억장치에 있던 text/txt 파일을 로딩하여 메모리에 저장공간을 만든다.
FileInputStream fin = new FileInputStream("D:\\Dropbox\\workspaces\\MultiCampus\\test.txt");
int input = 0;
while(input != -1) { //-1은 파일의 마지막을 뜻함
input = fin.read();
//print메서드는 아무런 준비없이 쓸 수 있다.
//System.out.print((char)input);
OutputStream out = System.out;
//write 버퍼로 출력
out.write((char)input);
//아직 다 차지않은 버퍼를 방출해준다.
out.flush();
}
//파일을 불러왔을 때 닫아주는 메서드이다.
//가까운 시일내에 가비지 컬렉션에서 인스턴스가 정리된다.
fin.close();
}
}
package charstream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileTest1 {
public static void main(String[] args) throws IOException {
// TODO 파일로부터 입력을 받아 콘솔로 출력
//null은 주소값을 저장하고 있지 않다는 표시이다.
//예외처리를 위해 변수를 밖으로 빼준다.
FileReader fin = null;
BufferedReader br = null;
//파일명의 위치를 적는다.
//파일입력을 받는 인스턴스를 생성한다. 인자값에 입력받을 파일 이름을 넣는다.
//보조기억장치에 있던 text/txt 파일을 로딩하여 메모리에 저장공간을 만든다.
try {
br = new BufferedReader(
new FileReader("D:\\Dropbox\\workspaces\\MultiCampus\\test.txt"));
String input = null;
while((input=br.readLine()) != null) {
//print로 해도 문자클래스가 깨지지 않는다.
System.out.println(input);
}
}
catch(FileNotFoundException err) {
//개발 중이라면 어디서 오류가 났는지 알도록 참조변수도 같이 출력한다.
System.out.println("파일을 찾을 수 없다." + err);
}
catch(IOException err) {err.printStackTrace();}
finally {
try {br.close();}
catch(Exception err) {}
}
}
}
※ 결과값
안녕 안녕 안녕 안녕 안녕 안녕 안녕 안녕
Hello Hello Hello Hello Hello Hello Hello
안녕 안녕 안녕 안녕 안녕 안녕 안녕 안녕
Hello Hello Hello Hello Hello Hello Hello
<IO에서 중요한 것>
Data Persistance 데이터 지속성
파일처리 : 데이터를 오랫동안 지속적으로 보관
DB = 파일을 안전하게 보관 할 수 있는 방법
<java 파일을 exe 실행파일 패키지로 만드는 방법>
JSmooth 프로그램을 이용하면 바로 만들 수 있다.
(구글링을 해보자!)
계속하여 charstream 이용하여 파일 입력 예제를 해보자.
package charstream;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
public class FileTest2 {
public static void main(String[] args) throws IOException {
// TODO 키보드로부터 입력받아 파일로 출력
//입력은 파일이 없으면 에러가 나지만 출력은 파일이 없으면 새로 만들어준다.
//새로운 내용을 입력받아 기존 내용을 지울 때는 false
//기존의 내용 뒤에 새로운 내용을 추가할 때는 true
FileWriter fout =
new FileWriter("D:\\Dropbox\\workspaces\\MultiCampus\\test2.txt", true);
//바이트클래스를 문자클래스로 바꿔주는 필터클래스이다.
//in(키보드입력)이라는 바이트스트림을 바꿔준다.
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String input = null;
while(true) { //ctrl + z 는 실행 중지.
input = br.readLine();
if(input == null)
break;
fout.write(input);
fout.flush();
}
fout.close();
isr.close();
br.close();
}
}
※ 아래 내용이 txt 파일에 입력된다.
ㅇㅀㅇㅎㄹㄴㅇㅀㄴㅇㅀ
package charstream;
import java.io.FileWriter;
import java.io.IOException;
public class FileTest3 {
public static void main(String[] args) throws IOException {
//파일로 저장하기 위한 문자 클래스이기 때문에 바꿔준다.
FileWriter fout = new FileWriter("D:\\Dropbox\\workspaces\\MultiCampus\\test3.txt");
for(int i=1; i<10; i++) {
// \n은 줄바꿈이다.
// \r linfeed로 첫번째 위치로 옮겨놓는 것이다.
String data = i + "번째 줄입니다.\r\n";
System.out.println(data);
//문자열을 출력하려면 write는 bite로 쪼개서 넘겨야한다.
//하지만 바이트 스트림이 아니기 때문에 .getBytes()을 쓸 필요가 없다.
fout.write(data);
}
fout.close();
}
}
※아래 내용이 txt 파일에 입력된다.
1번째 줄입니다.
2번째 줄입니다.
3번째 줄입니다.
4번째 줄입니다.
5번째 줄입니다.
6번째 줄입니다.
7번째 줄입니다.
8번째 줄입니다.
9번째 줄입니다.
3. PrintWriter
- Writer 문자스트림을 기반으로 출력을 좀 더 쉽게 하기 위한 클래스
PrintWriter는 println(줄바꿈) printf(포맷 : 형식을 지정한다.) 등의 다양한 기능을 지정한다.
package charstream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class FileTest3 {
public static void main(String[] args) throws IOException {
//파일로 저장하기 위한 문자 클래스이기 때문에 바꿔준다.
PrintWriter pw = new PrintWriter("D:\\Dropbox\\workspaces\\MultiCampus\\test3.txt");
for(int i=1; i<10; i++) {
// \n은 줄바꿈이다.
// \r linfeed로 첫번째 위치로 옮겨놓는 것이다.
String data = i + "번째 줄입니다.\r\n";
System.out.println(data);
//문자열을 출력하려면 write는 bite로 쪼개서 넘겨야한다.
//하지만 바이트 스트림이 아니기 때문에 .getBytes()을 쓸 필요가 없다.
//fout.write(data);
pw.print(data);
}
//fout.close();
pw.close();
}
}
※ 결과값
1번째 줄입니다.
2번째 줄입니다.
3번째 줄입니다.
4번째 줄입니다.
5번째 줄입니다.
6번째 줄입니다.
7번째 줄입니다.
8번째 줄입니다.
9번째 줄입니다.
<printf 메서드>
printf는 형식을 자유롭게 변경 할 수 있다.
printf의 첫번째 인자는 내가 원하는 데이터의 형식을 지정해준다.
pw.printf("%3s : %-5d %5d %5.1f", "홍길동", 98, 67,(float)((98+67)/2));
%는 데이터를 표시될 곳이라는 위치를 나타내는 기호이다.
%다음에 나오는 숫자는 칸의 갯수, 자리를 예약했음을 의미한다.
숫자 다음에 나오는 영어 s는 string 이다.
d는 decimal 정수형이다.
f는 float이다.
%n은 줄바꿈을 하겠다는 뚯이다.
데이터는 순서대로 들어간다.
문자는 왼쪽부터, 숫자는 오른쪽부터 채워진다.
숫자를 왼쪽 부터 지정하고 싶으면 음수로 만들면 된다.
이런식으로 출력할 때 데이터 형식을 지정할 수 있다.
이와같은 형식은 파일이나 콘솔에 사용된다.
package charstream;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class FileTest4 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//파일을 저장할 수 있도록 준비
PrintWriter pw =
new PrintWriter(
//성능을 개선하기 위한 목적으로 BufferedWriter로 한 번 더 포장
new BufferedWriter(
//자유로운 포맷(형식)변경을 위해 printf를 사용하기 위한 목적으로 PrintWriter로 한 번 더 포장
new FileWriter("D:\\Dropbox\\workspaces\\MultiCampus\\sungjuk.txt")));
pw.println("*******************************성적표************************************");
pw.println("------------------------------------------------------------------------");
//printf는 형식을 자유롭게 변경 할 수 있다.
//printf의 첫번째 인자는 내가 원하는 데이터의 형식을 지정해준다.
//%는 데이터를 표시될 곳이라는 위치를 나타내는 기호이다.
//%다음에 나오는 숫자는 칸의 갯수, 자리를 예약했음을 의미한다.
//숫자 다음에 나오는 영어 s는 string 이다.
//d는 decimal 정수형이다.
//f는 float이다.
//데이터는 순서대로 들어간다.
//문자는 왼쪽부터, 숫자는 오른쪽부터 채워진다.
//숫자를 왼쪽 부터 지정하고 싶으면 음수로 만들면 된다.
//이런식으로 출력할 때 데이터 형식을 지정할 수 있다.
//%n은 줄바꿈을 하겠다는 뚯이다.
//이와같은 형식은 파일이나 콘솔에 사용된다.
pw.printf("%3s : %-5d %5d %5.1f",
"홍길동", 98, 67, (float)((98+67)/2));
pw.printf("%3s : %-5d %5d %5.1f, %n", "임꺽정", 98, 67, (float)((98+67)/2));
pw.printf("%3s : %-5d %5d %5.1f, %n", "신돌석", 98, 67, (float)((98+67)/2));
pw.printf("%3s : %-5d %5d %5.1f %n", "유비", 98, 67, (float)((98+67)/2));
//출력은 close(); 해야 버퍼가 마무리 한다.
pw.close();
}
}
※ 입력된 값
*******************************성적표************************************
------------------------------------------------------------------------
홍길동 : 98 67 82.0임꺽정 : 98 67 82.0,
신돌석 : 98 67 82.0,
유비 : 98 67 82.0
위 코드는 아래와 같이 바꿀 수도 있다.
package charstream;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class FileTest4 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//PrintWriter는 저장준비와 성능개선, 자유로운 포맷변경이 모두 포함되어 있다.
PrintWriter pw = new PrintWriter("D:\\Dropbox\\workspaces\\MultiCampus\\sungjuk.txt");
pw.println("*******************************성적표************************************");
pw.println("------------------------------------------------------------------------");
pw.printf("%3s : %-5d %5d %5.1f",
"홍길동", 98, 67, (float)((98+67)/2));
//출력은 close(); 해야 버퍼가 마무리 한다.
pw.printf("%3s : %-5d %5d %5.1f, %n", "임꺽정", 98, 67, (float)((98+67)/2));
pw.printf("%3s : %-5d %5d %5.1f, %n", "신돌석", 98, 67, (float)((98+67)/2));
pw.printf("%3s : %-5d %5d %5.1f %n", "유비", 98, 67, (float)((98+67)/2));
pw.close();
}
}
※ 입력된 값
*******************************성적표************************************
------------------------------------------------------------------------
홍길동 : 98 67 82.0임꺽정 : 98 67 82.0,
신돌석 : 98 67 82.0,
유비 : 98 67 82.0
4. Serializable (직렬화)
병렬 : 동시에 신호를 많이 보낼 경우 (예: 프린트)
직렬 : 신호를 적게 보낼 경우 (예 : 마우스)
직렬화(Serializable) : 직렬로 바꿔주는 상태
IO 에서의 직렬화는 무엇일까?
A장치가 B에게 복잡한 데이터를 보낼 때
복잡한 데이터를 단순화 시켜서 보내면
병렬로 보내는 것보다 안전하다.
이처럼,
복잡한 데이터를 단순화 시켜서 보내는 작업을 직렬화라고 한다.
자바에서는 직렬화 기능이 시스템 내부에 있다.
직렬화를 할 때는 Serializable 이 붙어있는 인터페이스는
시스템이 직렬화 과정을 거치도록 표시해준다.
예제를 살펴보자
package bytestreamtest;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class ObjectTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Employee[] emp = new Employee[3];
emp[0] = new Employee(1, "홍길동", "영업", 110, 1.4);
emp[1] = new Employee(2, "임꺽정", "기술", 111, 1.5);
emp[2] = new Employee(3, "신돌석", "개발", 112, 1.7);
//System.out.println(emp[0]);
//데이터를 묶은 객체단위로 파일에 저장하려면 어떻게 해야할까?
//객체단위 저장은 objct의 writeObject(Object obj) 밖에 없다.
//인스턴스를 만들어 메모리의 공간을 생성하고 emp.dat 파일을 만들어 연다.
ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream("D:\\Dropbox\\workspaces\\MultiCampus\\emp.dat"));
//emp.dat 파일에 배열의 정보를 쓴다.
oos.writeObject(emp[0]);
oos.writeObject(emp[1]);
oos.writeObject(emp[2]);
//항상 파일을 불러왔으면 닫아줘야한다..
oos.close();
System.out.println("******사원정보*******");
System.out.println("사번\t이름\t업무\t부서번호\t인사점수");
System.out.println("-----------------------------------------");
//인스턴스를 만들어 메모리의 공간을 생성하고 emp.dat 파일의 정보를 불러온다.
ObjectInput ois =
new ObjectInputStream (new FileInputStream("D:\\\\Dropbox\\\\workspaces\\\\MultiCampus\\\\emp.dat"));
//emp.dat 의 정보를 차례로 이클립스 내에서 볼 수 있게끔 프린트 해준다.
for(int i=0; i<3; i++) {
Employee e = (Employee)ois.readObject();
System.out.println(e);
}
ois.close();
}
}
※ 결과값
******사원정보*******
사번 이름 업무 부서번호 인사점수
-----------------------------------------
1 홍길동 영업 110 1.4
2 임꺽정 기술 111 1.5
3 신돌석 개발 112 1.7
package FileTest;
import java.io.File;
import java.util.Date;
public class FileTest {
public static void main(String[] args) {
File f = new File("D:\\Dropbox\\workspaces\\MultiCampus\\emp.dat");
if(f.exists()) {
System.out.println("파일의 이름 : " + f.getName());
System.out.println("상대경로 : " + f.getPath());
System.out.println("절대경로 : " + f.getAbsolutePath());
System.out.println("크기 : " + f.length() + "byte");
//.lastModified는 현재날짜를 정수형으로 변환하기 때문에 Date메서드로 현재 날짜로 다시 변환한다.
System.out.println("마지막 수정일자 : " + new Date(f.lastModified()));
}else {
System.out.println("파일이 존재하지 않는다.");
}
//파일을 삭제한다.
f.delete();
}
}
※ 결과값
파일의 이름 : emp.dat
상대경로 : D:\Dropbox\workspaces\MultiCampus\emp.dat
절대경로 : D:\Dropbox\workspaces\MultiCampus\emp.dat
크기 : 226byte
마지막 수정일자 : Wed Nov 01 13:35:50 KST 2017