[자바/JAVA/SCJP]자바 IO (입출력)
자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP
바이트의 연속을 스트림(stream)이라고 한다. 자바에서는 스트림을 이용해서 입출력을 한다.
입력을 하는 스트림을 입력스트림(input stream)이라고 하고, 출력하는 스트림을 출력 스트림(output stream)이라고 한다.
입출력 스트림은 java.io 패키지에 만들어져 있다.
화면에 출력하고, 키보드로 부터 입력을 받아들이기 위해서는 System 클래스의
out 과 in 을 사용했다. System 클래스의 out은 PrintStream 타입의 멤버 필드이고,
in은 InputStream 타입의 멤버 필드이다. 자바에서 입력 스트림 클래스들은
InputStream 클래스로부터 상속된 클래스이다. 출력 스트림 클래스들은 OutputStream
클래스로부터 상속된 클래스이다.
9.2.1 InputStream 클래스
System 클래스의 in 멤버필드는 대표적인 InputStream 타입이다. InputStream은 입력을
위해 다음과 같은 메소드들을 이용할 수 있다.
int read()
int read(byte[])
int read(byte[], int, int)
read() 메소드를 이용하는 경우에 바이트 값을 읽어오거나 파일의 끝인 경우에는
-1을 리턴한다. read(byte[]) 메소드는 읽은 내용을 바이트 배열에 채우고, 읽은 바이트의
수를 리턴한다. read(byte[], int, int) 메소드는 바이트 배열에서 시작 위치와 끝 위치를
지정한 뒤에 내용을 읽어오고, 읽은 바이트의 수를 리턴한다.
inOut.java 파일
1 import java.io.*;
2
3 class inOut {
4 public static void main (String args[]) throws IOException {
5 int b, count = 0;
6 while ((b = System.in.read()) != -1) {
7 count++;
8 System.out.print((char)b);
9 }
10 System.out.println();
11 System.err.println("total bytes = " + count);
12 }
13 }
결과
% java inOut
Hello
Hello
한글
??±?
^D
total bytes = 11
설명
6 while ((b = System.in.read()) != -1) {
System.in.read() 메소드를 이용해서 키보드로부터 입력을 받는다. read() 메소드는
바이트 입력을 리턴하고, 입력이 종료되면(Cntl-D) -1을 리턴한다.
8 System.out.print((char)b);
System.out.print() 메소드를 이용해서 읽어온 바이트를 문자 타입으로 변환해서
출력한다.
11 System.err.println("total bytes = " + count);
System 클래스의 err 멤버 필드를 이용해서 출력하였다. err 멤버필드는 표준 에러
출력을 위해 사용된다.
total bytes = 11
유닉스 시스템에서 테스트 하였기 때문에 영어 문자당 1개의 바이트와 한글에 2바이트
가 사용되었다. 따라서, 영어 5개 문자(5 바이트), 한글 2개 문자(4 바이트), 리턴값
(1 바이트 x 2), 총 11 바이트가 된다.
9.2.2 InputStreamReader 클래스
JDK 1.0의 입출력 스트림은 JDK 1.1에서 Reader 와 Writer 클래스로 대체되었다.
입력을 위해서는 Reader 클래스를 이용하고, 출력을 위해서는 Writer 클래스를
이용할 수 있다. Reader 클래스는 입력을 위해 다음과 같은 메소드들을 이용할 수 있다.
int read()
int read(char[])
int read(char[], int, int)
InputStreamReader 클래스는 InputStream 을 아규먼트로 만들어진다.
InputStreamReader 클래스의 getEncoding() 메소드는 스트림에서 사용된 인코딩 이름을 리턴한다.
BufferedReader 클래스는 Reader 클래스를 아규먼트로 만들 수 있다. BufferedReader 클래스
는 다음과 같은 메소드를 이용해서 입력을 받을 수 있다.
int read()
String readLine()
read() 메소드는 한문자를 읽어서 리턴하는 메소드이고, readLine() 메소드는 한 줄을
읽어서 문자열을 리턴하는 메소드이다.
CharInput.java 파일
1 import java.io.*;
2
3 public class CharInput {
4
5 public static void main(String args[]) {
6 String s;
7 BufferedReader in;
8 in = new BufferedReader(new InputStreamReader(System.in));
9
10 try {
11 System.out.print("Put characters:");
12 while((s = in.readLine()) != null) {
13 System.out.println("\tCharacters from console :" + s);
14 System.out.print("Put characters:");
15 }
16 } catch (IOException ex) { }
17 }
18 }
결과
% java CharInput
Put characters:Hello ?
Characters from console :Hello ?
Put characters:안녕하세요 ?
Characters from console :안녕하세요 ?
Put characters:^D
설명
8 in = new BufferedReader(new InputStreamReader(System.in));
키보드로 부터 입력을 받는 BufferedReader 클래스를 만들기 위해, InputStreamReader
클래스와 System.in 을 이용했다.
12 while((s = in.readLine()) != null) {
BufferedReader 클래스의 readLine() 메소드를 이용해서 한줄을 읽어들였다.
9.2.3 FileOutputStream 클래스
FileOut.java 파일
1 import java.io.*;
2
3 public class FileOut {
4 private FileOutputStream fout;
5 private byte msg[];
6 private int len;
7
8 FileOut(String fname) throws IOException {
9 msg = new byte[1024];
10 len = 0;
11 fout = new FileOutputStream(fname);
12 int b =0;
13
14 System.out.print("Put characters:");
15 b = System.in.read();
16 while(b != 10) {
17 msg[len++] = (byte)b;
18 b = System.in.read();
19 }
20 write(msg);
21 System.out.println("Total "+ len + " bytes.");
22 }
23
24 public void write(byte[] m) throws IOException{
25 for(int i=0; i < len; i++) {
26 fout.write(m[i]);
27 }
28 }
29
30 public void close() {
31 try {
32 fout.close();
33 } catch(IOException ex) { }
34 }
35
36
37 public static void main(String[] args) throws IOException{
38 FileOut o = new FileOut("temp");
39 o.close();
40 }
41
42 }
결과
% java FileOut
Put characters:Hello ? 안녕하세요 ?
Total 20 bytes.
% more temp
Hello ? 안녕하세요 ?
설명
11 fout = new FileOutputStream(fname);
파일 이름을 아규먼트로 갖고 FileOutputStream 클래스를 만든다.
15 b = System.in.read();
키보드로부터 입력을 받아들인다.
26 fout.write(m[i]);
FileOutputStream 클래스를 이용해서 파일에 기록한다.
32 fout.close();
close() 메소드를 이용해서 파일을 닫는다.
9.2.4 RandomAccessFile 클래스
RandomAccessFile 클래스는 seek() 메소드를 이용해서 입출력 포인터의 위치를
이동할 수 있다. 포인터를 이동시킨뒤에 파일에 기록하거나 내용을 읽을 수 있다.
RandomAccessFile 클래스는 다음과 같은 생성자를 이용해서 만들 수 있다.
RandomAccessFile(String filename, String openmode)
첫번째 아규먼트는 파일의 이름을 의미하고, 두번째 아규먼트는 파일을 오픈할 때
읽기 전용인가 아니면 읽기/쓰기 가능한지를 나타낸다. 두번째 아규먼트는 읽기
전용인 경우에는 "r", 읽기/쓰기 인 경우에는 "rw" 이다.
RandomAccessFile 클래스는 파일의 길이를 알아볼 수 있는 length() 메소드, 각 자료
타입을 읽을 수 있는 readBoolean(), readByte(), readChar(), readDouble(), readFloat(),
readInt(), readLong(), readShort() 등의 메소드들이 있다. 마찬가지로 각 자료 타입을
기록할 수 있는 writeBoolean(boolean), writeByte(int), writeBytes(String), writeChar(int),
writeChars(String), writeDouble(double), writeFloat(float), writeInt(int), writeLong(long),
writeShort(int) 등의 메소드들이 있다.
EmployeeDB.java 파일 예제는 자바에서 C 언어에서 레코드를 어떻게 사용하는가를 보여준다.
자바는 레코드가 없기 때문에 클래스를 레코드로 사용한다. Record 클래스는 레코드를 표현하기
위해 사용된 클래스이다. Table 클래스는 레코드를 처리하기 위해 사용된 클래스이다.
Table 클래스에서 레코드를 읽거나 기록하기 위한 루틴들을 포함하고 있다. EmployeeDB 클래스는
주로 GUI를 위한 코드가 들어 있다.
EmployeeDB.java 파일
1 import java.awt.*;
2 import java.awt.event.*;
3 import java.io.*;
4
5
6 public class EmployeeDB extends Frame implements ActionListener {
7 static final int NONE = 0;
8 static final int ADD = 1;
9 static final int TOTAL = 2;
10 static final int SEARCH = 3;
11 static final int REMOVE = 4;
12 static final int ESC = 5;
13 Panel left, bottom;
14 LabeledTextField name, number, dept, phone;
15 TextArea display;
16 Button addB, totalB, searchB, removeB, escB, exitB;
17 Table table;
18 int action;
19
20
21 public EmployeeDB() {
22 setLayout(new BorderLayout());
23 action = NONE;
24 left = new Panel();
25 bottom = new Panel();
26 display = new TextArea();
27 display.setEditable(false);
28 name = new LabeledTextField("이 름");
29 name.setEditable(false);
30 number = new LabeledTextField("사 번");
31 number.setEditable(false);
32 dept = new LabeledTextField("부 서");
33 dept.setEditable(false);
34 phone = new LabeledTextField("전 화");
35 phone.setEditable(false);
36 left.setLayout(new GridLayout(4,1));
37 left.setSize(400, 300);
38 left.add(name);
39 left.add(number);
40 left.add(dept);
41 left.add(phone);
42
43 addB = new Button("추 가");
44 addB.addActionListener(this);
45 addB.setActionCommand("add");
46 totalB = new Button("전체 보기");
47 totalB.addActionListener(this);
48 totalB.setActionCommand("total");
49 searchB = new Button("검 색");
50 searchB.addActionListener(this);
51 searchB.setActionCommand("search");
52 removeB = new Button("삭 제");
53 removeB.addActionListener(this);
54 removeB.setActionCommand("remove");
55 escB = new Button("취 소");
56 escB.addActionListener(this);
57 escB.setActionCommand("esc");
58 exitB = new Button("종 료");
59 exitB.addActionListener(this);
60 exitB.setActionCommand("exit");
61 exitB.setBackground(Color.red);
62 bottom.setLayout(new GridLayout(1,6));
63 bottom.add(addB);
64 bottom.add(totalB);
65 bottom.add(searchB);
66 bottom.add(removeB);
67 bottom.add(escB);
68 bottom.add(exitB);
69
70 add("Center", display);
71 add("West", left);
72 add("South", bottom);
73
74 table = new Table();
75 }
76
77 public void initialize() {
78 action = NONE;
79 addB.enable();
80 totalB.enable();
81 searchB.enable();
82 removeB.enable();
83 name.setText("");
84 number.setText("");
85 dept.setText("");
86 phone.setText("");
87 name.setEditable(false);
88 number.setEditable(false);
89 dept.setEditable(false);
90 phone.setEditable(false);
91 }
92
93 public void actionPerformed(ActionEvent e) {
94 int index = 0;
95 String cmd = e.getActionCommand();
96 String nameString, num, part, tel;
97 boolean found = false;
98 String msg = "";
99
100 if(cmd.equals("add")) {
101 if(action != ADD) {
102 action = ADD;
103 name.setEditable(true);
104 number.setEditable(true);
105 dept.setEditable(true);
106 phone.setEditable(true);
107 totalB.disable();
108 searchB.disable();
109 removeB.disable();
110 return;
111 }
112 nameString = name.getText().trim();
113 if(nameString == null || nameString.length() == 0)
114 return;
115 num = number.getText().trim();
116 if(num == null || num.length() == 0)
117 return;
118 part = dept.getText().trim();
119 if(part == null || part.length() == 0)
120 return;
121 tel = phone.getText().trim();
122
123 display.setText(nameString + num + part + tel);
124 table.add(nameString, num, part, tel);
125 display.appendText("\n 등록을 성공적으로 마쳤습니다.");
126 initialize();
127 } else if(cmd.equals("total")) {
128 action = TOTAL;
129 initialize();
130 index = table.getIndex();
131 display.setText("\n 검색 건수 : 총 " + Integer.toString(index+1)+ " 건\n");
132 display.appendText("\n============================================");
133 display.appendText("\n 순번 \t성명 \t사번 \t부서명 \t전화번호 ");
134 display.appendText("\n--------------------------------------------\n\n");
135 if(index < 0) {
136 display.appendText(" 등록된 자료가 없습니다. \n");
137 return;
138 }
139 for(int i = 0; i <= index; i++) {
140 Record rec = table.readRec(i);
141 msg = " " + Integer.toString(i+1) + " \t ";
142 msg += rec.getName() + " \t";
143 msg += Integer.toString(rec.getNum()) + " \t";
144 msg += rec.getPart() + " \t";
145 msg += rec.getTel() + "\n";
146 display.appendText(msg);
147 }
148 } else if(cmd.equals("search")) {
149 if(action != SEARCH) {
150 action = SEARCH;
151 name.setEditable(true);
152 addB.disable();
153 totalB.disable();
154 removeB.disable();
155 return;
156 }
157 Record rec;
158 index = table.getIndex();
159 nameString = name.getText().trim();
160 if(nameString == null || nameString.length() == 0)
161 return;
162 display.setText("\n ## 개인 조회 ###########\n");
163 display.appendText("\n============================================");
164 display.appendText("\n 순번 \t성명 \t사번 \t부서명 \t전화번호 ");
165 display.appendText("\n--------------------------------------------\n\n");
166 for(int i = 0; i <= index; i++) {
167 rec = table.readRec(i);
168 if(nameString.equals(table.readName(i, nameString.length()))) {
169 found = true;
170 }
171 if(found) {
172 msg = " " + Integer.toString(i+1) + " \t ";
173 msg += rec.getName() + " \t";
174 msg += Integer.toString(rec.getNum()) + " \t";
175 msg += rec.getPart() + " \t";
176 msg += rec.getTel() + "\n";
177 display.appendText(msg);
178 msg = "";
179 break;
180 }
181 }
182 if (!found) {
183 display.setText(" 조회하신 성명이나 사번의 직원이 없습니다...");
184 }
185 initialize();
186 } else if(cmd.equals("remove")) {
187 if(action != REMOVE) {
188 action = REMOVE;
189 name.setEditable(true);
190 addB.disable();
191 totalB.disable();
192 searchB.disable();
193 return;
194 }
195 index = table.getIndex();
196 nameString = name.getText().trim();
197 if(nameString == null || nameString.length() == 0)
198 return;
199 display.setText("\n ## 삭제 ###########\n");
200 display.appendText("\n============================================");
201 display.appendText("\n 순번 \t성명 \t사번 \t부서명 \t전화번호 ");
202 display.appendText("\n--------------------------------------------\n\n");
203 for(int i = 0; i <= index; i++) {
204 Record rec = table.readRec(i);
205 if(nameString.equals(table.readName(i, nameString.length()))) {
206 found = true;
207 }
208 if(found) {
209 msg = rec.getName();
210 msg += Integer.toString(rec.getNum());
211 msg += rec.getPart();
212 msg += rec.getTel();
213 display.appendText(msg);
214 msg = "";
215 found = true;
216 display.appendText("\n 위의 자료를 삭제하였습니다....");
217 for(int j=i+1; j <= index; j++) {
218 rec = table.readRec(j);
219 table.writeRec(rec.getName(),rec.getNum(),rec.getPart(),rec.getTel(),j-1);
220 }
221 table.remove(--index);
222 break;
223 }
224 }
225 if(!found) {
226 display.appendText("조회하신 성명의 직원이 없습니다...");
227 }
228 initialize();
229 } else if(cmd.equals("esc")) {
230 action = NONE;
231 initialize();
232 } else if(cmd.equals("exit")) {
233 table.close();
234 setVisible(false);
235 dispose();
236 System.exit(0);
237 }
238 }
239
240
241
242 class Table {
243 private RandomAccessFile myRAFile;
244 private int recordCount;
245 private int recordLength = 50;
246 private int recordOffset = 4;
247
248 public Table() {
249 try {
250 myRAFile = new RandomAccessFile("employee.db", "rw");
251 if(myRAFile.length() ==0) {
252 recordCount = -1;
253 } else {
254 recordCount = myRAFile.readInt();
255 }
256 } catch(IOException e) {
257 System.out.println("Can't access employee.dat");
258 }
259 }
260
261
262 public int getIndex() {
263 return recordCount;
264 }
265
266 public void add(String name, String num, String part, String tel) {
267 writeRec(name, Integer.parseInt(num), part, tel, ++recordCount);
268 }
269
270 public void close() {
271 try {
272 myRAFile.close();
273 } catch(IOException ioe) {
274 System.out.println("IOException during close file");
275 }
276 }
277
278 public Record readRec(int index) {
279 String name="", part="", tel="" ;
280 int num = -1 ;
281
282 try {
283 myRAFile.seek(index * recordLength + recordOffset);
284 for(int i = 0; i < 5;i++) {
285 name += myRAFile.readChar();
286 }
287 num = myRAFile.readInt();
288 for(int i = 0; i < 6;i++) {
289 part += myRAFile.readChar();
290 }
291 for(int i = 0; i < 8;i++) {
292 tel += myRAFile.readChar();
293 }
294
295 } catch(IOException ioe) {
296 System.out.println("IOException during read file..");
297 }
298 return (new Record(name, num, part, tel));
299 }
300
301 public String readName(int index, int len) {
302 String name="";
303 try {
304 myRAFile.seek(index * recordLength + recordOffset);
305 for(int i = 0; i < len;i++) {
306 name += myRAFile.readChar();
307 }
308 } catch (IOException ioe) {
309 System.out.println("IOException :"+ioe.toString());
310 }
311 return (name);
312 }
313
314
315 public void remove(int i) {
316 recordCount = i;
317 }
318
319
320 public void writeRec(String name, int num, String part, String tel, int index) {
321 int len = 0;
322
323 try {
324 myRAFile.seek(index * recordLength + recordOffset);
325 len = name.length();
326 for(int i =0;i < 5;i++) {
327 myRAFile.writeChar((i < len ? name.charAt(i) : ' '));
328 }
329 myRAFile.writeInt(num);
330
331 len = part.length();
332 for(int i =0;i < 6;i++) {
333 myRAFile.writeChar((i < len ? part.charAt(i) : ' '));
334 }
335
336 len = tel.length();
337 for(int i =0;i < 8;i++) {
338 myRAFile.writeChar((i < len ? tel.charAt(i) : ' '));
339 }
340 myRAFile.seek(0);
341 myRAFile.writeInt(recordCount);
342 } catch(IOException ioe) {
343 System.out.println("IOException while writing..");
344 }
345 }
346
347 }
348
349
350 class Record {
351 private String name;
352 private int num;
353 private String part;
354 private String tel;
355
356 public Record(String na, int n, String p, String t) {
357 name = na;
358 num = n;
359 part = p;
360 tel = t;
361 }
362
363 public String getName() {
364 return(name);
365 }
366
367 public int getNum() {
368 return(num);
369 }
370
371 public String getPart() {
372 return(part);
373 }
374
375 public String getTel() {
376 return(tel);
377 }
378 }
379
380 public static void main(String agrs[]) {
381 EmployeeDB db = new EmployeeDB();
382 db.setSize(550, 300);
383 db.setVisible(true);
384 }
385 }
LabeledTextField.java 파일
1 import java.awt.*;
2
3 public class LabeledTextField extends Panel{
4 private Label label;
5 private TextField field;
6 private String labelPosition;
7 private String fieldPosition;
8
9 public LabeledTextField(String labelString) {
10 this(labelString, "1%, 5%, 25%, 95%", "27%, 5%, 98%, 95%");
11 }
12
13
14 public LabeledTextField(String labelString, String labelPosition, String fieldPosition) {
15 super();
16 setLayout(new PositionLayout());
17 this.labelPosition = labelPosition;
18 this.fieldPosition = fieldPosition;
19 label = new Label(labelString);
20 field = new TextField(20);
21 add(labelPosition, label);
22 add(fieldPosition, field);
23 }
24
25 public String getText() {
26 return field.getText();
27 }
28
29 public void setText(String m) {
30 field.setText(m);
31 }
32
33 public void setEditable(boolean t) {
34 boolean able = field.isEditable();
35 if(t != able)
36 field.setEditable(t);
37 }
38
39 public static void main(String args[]) {
40 Frame f = new Frame();
41 LabeledTextField lt = new LabeledTextField("Name:");
42 f.add("South", lt);
43 f.setSize(400, 200);
44 f.setVisible(true);
45 }
46 }
결과
% java EmployeeDB
설명
250 myRAFile = new RandomAccessFile("employee.db", "rw");
employee.db 파일을 읽기/쓰기로 오픈한다.
251 if(myRAFile.length() ==0) {
파일의 길이가 0 이면, 즉 파일에 내용이 없으면..
254 recordCount = myRAFile.readInt();
파일로부터 정수를 하나 읽어온다.
283 myRAFile.seek(index * recordLength + recordOffset);
입출력 포인터를 특정 위치로 이동 시킨다.
327 myRAFile.writeChar((i < len ? name.charAt(i) : ' '));
문자를 파일에 기록한다.
출처:
http://www.it-bank.or.kr/prom/java_main.htm
자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP 자바/JAVA/SCJP