- input.txt라는 텍스트 파일을 만들어서 같은 패키지 안에 저장한다. TokenFileTest라는 클래스를 만들고 input.txt 파일을 읽어서 콘솔창에 출력한다. (TokenFileTest)
-
파일 읽는 클래스는 FileInputStream, 콘솔창 출력은 print메소드를 이용한다.
-
읽어들임: read()는 int형만 읽어들이기 때문에 다양한 형식을 읽어들이기 위해 Scanner가 나왔다. (자바 5부터) 파일을 읽을때 Scanner를 써도 상관없다. 한 줄로 읽어들일때는 Scanner를 이용한다.
-
내보낼때: write()는 FileOutputStream과 함께 쓰며 파일형태로 출력한다. print()는 콘솔창에 출력한다.
-
객체 만들고 read, 객체 만들고 write, 예외처리 꼭 해주기.
-
예외처리 할때 작은 범위의 예외처리를 먼저 써줘야함. (순서를 바꾸면 오류남)
+input.txt 내용
10:20
23:5
8:7
12:67
4:9
2:6
34:23
11:22
15:16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package ioTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class TokenFileTest {
public static void main(String[] args) {
try {
//파일 경로를 정확하게 써주기
FileInputStream fis=new FileInputStream("src\\ioTest\\input.txt");
while(true) {
int i = fis.read();
if(i==-1) break;
System.out.print((char)i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
|
+만약에 파일로 내보내려면? (TokenFileTest)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package ioTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class TokenFileTest {
public static void main(String[] args) {
try {
//파일을 읽어들이는 객체 fis를 선언. 경로를 정확하게 써주기
FileInputStream fis=new FileInputStream("src\\ioTest\\input.txt");
//파일로 내보내는 객체 fos를 선언. 다음 경로에 txt파일이 만들어진다.
FileOutputStream fos=new FileOutputStream("src\\iotest\\out.txt");
while(true) {
int i = fis.read();
if(i==-1) break;
//System.out.print((char)i);
//읽어들인 파일을 내보낼때 write.
fos.write(i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
|
+파일의 내용을 한 줄씩 읽어들이고 한줄로 출력하고 싶다면? 또한 기존 파일 내용 중 10:20형태를 10 20으로 출력하려면? (TokenFileTest2)
-
한 줄을 읽어들일 수 있는 Scanner 이용. Scanner에서 파일 경로만 써주면 문자열로 인식하므로 new File을 붙여서 파일임을 표시.
-
while에는 이 객체가 있는 동안 돌린다는 뜻으로 hasNext()메소드 이용.
-
한 줄씩 읽어들이는 nextLine()메소드 이용.
-
문자열에서 쓰이는 split 함수를 이용하여 중간의 ' : '을 제거.
-
split 함수는 String 배열로 지정해야함.
-
배열이므로 for문을 돌려서 출력하기
+16진수로 출력한다면?
-
String 배열은 바로 16진수로 바꿀 수 없다.
-
parseInt로 먼저 변환한 뒤 정수형 변수에 선언하고
-
그 정수형 변수를 16진수로 출력하기
+16진수로 변환한 결과물을 파일로 내보낸다면?
-
Scanner로 한 문장씩 입력받았기에 파일로 내보낼때는 PrintStream를 이용한다.
-
ps=new printStream이렇게 객체를 하나 만들어준다.
-
write를에는 정수형이나 바이트의 배열만 할당할 수 있으므로 문자를 내보낼 수 있는 메소드 print()를 사용해야 한다.
-
객체명을 앞에 붙여준다. (ps.print() 와 같은 형식)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
package ioTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Scanner;
public class TokenFileTest2 {
public static void main(String[] args) {
/*10:20을 10 20으로 출력하기
*한줄을 읽어들일 수 있는 Scanner를 이용하기
*문자열 split 함수를 이용하여 ':'을 제거
*/
//지역변수는 초기값이 없으면 안된다.
Scanner sfis=null;
//문자를 내보낼때는 PrintStream을 많이 쓴다.
PrintStream ps=null;
try {
//new File을 안쓰면 파일이 아니라 문자열로 인식한다.
sfis = new Scanner(new File("src\\ioTest\\input.txt"));
ps = new PrintStream("src\\ioTest\\hex.txt");
while(sfis.hasNext()) { //이 객체가 있는 동안 돌린다는 뜻. hasNext()
String str = sfis.nextLine();
String[]tmp=str.split(":");
for(int i=0;i<tmp.length;i++) {
System.out.print(tmp[i]+"\t");
/*16진수로 출력
*String 배열은 바로 16진수로 바꿀 수 없다.
*parseInt로 먼저 변환한 뒤 정수형 변수에 선언하고
*그 정수형 변수를 16진수로 출력하기
*/
int v=Integer.parseInt(tmp[i]);
System.out.print(Integer.toHexString(v).toUpperCase()+"\t");
//write에는 int나 byte의 배열만 할당할 수 있다. 문자를 내보낼 수 없다.
ps.print(Integer.toHexString(v).toUpperCase()+"\t");
}
//if(i==-1) break; hasNext()에서는 없으면 false로 넘어가니까 지워도 상관없음
//System.out.print(str+"\t");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
sfis.close();
ps.close();
}
}
}
|
- StringTokenizer는 split메소드를 클래스화 시킨 것. 기본은 공백으로 쪼개기. (TokenTest)
Class StringTokenizer:StringTokenizer st = new StringTokenizer("this is a test"); while (st.hasMoreTokens()) { System.out.println(st.nextToken()); } =>출력문: 기본은 공백으로 쪼개는 것. this is a test |
-
문자열을 미리 선언한 뒤 StringTokenizer의 객체를 불러서 쪼갤 기준을 지정할 수도 있고, StringTokenizer 생성자의 인수로 문자열을 쓸 수도 있다. 그때에는 공백이 기준이 된다.
-
토큰 수는 countTokens(), 출력은 nextToken()메소드를 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package utilTest;
import java.util.StringTokenizer;
public class TokenTest {
public static void main(String[] args) {
String str="aaa@bbb@ccc@ddd.eee";
StringTokenizer stk=new StringTokenizer(str, "@."); //"@."=@로도, 점(.)으로도 쪼갠다.
while(stk.hasMoreTokens()) { //hasMoreElements랑 같은 뜻
System.out.println("토큰 수: "+stk.countTokens());
System.out.println(stk.nextToken());
}
System.out.println("=======");
StringTokenizer stk1=new StringTokenizer("1 0 14 15 3 3 19");
while(stk1.hasMoreTokens()) {
System.out.println("토큰 수: "+stk1.countTokens());
System.out.println(stk1.nextToken());
}
}
}
|
-
TokenFileTest2에서 split대신에 StringTokenizer 클래스를 이용하기 (TokenFileTest3)
-
8진수로 변환하고 octal.txt 파일로 출력하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package ioTest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Scanner;
import java.util.StringTokenizer;
public class TokenFileTest3 {
//input.txt파일을 읽어서
//8진수로 변환하여 octal.txt파일로 출력하시오
//단, StringTokenizer를 사용하기
public static void main(String[] args) {
Scanner sc=null;
PrintStream pst=null;
try {
sc=new Scanner(new File("src\\ioTest\\input.txt"));
pst=new PrintStream("src\\ioTest\\octal.txt");
while(sc.hasNext()) {
String str = sc.nextLine();
StringTokenizer st=new StringTokenizer(str,":");
while(st.hasMoreTokens()) { //Token이 있는 동안
String tok=st.nextToken(); //Token하나를 가져와서 문자열 tok에 선언
int v=Integer.parseInt(tok);
System.out.print(Integer.toOctalString(v)+"\t");
pst.print(Integer.toOctalString(v)+"\t");
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
sc.close();
pst.close();
}
}
}
|
- 친구를 등록하고 파일로 출력하여 입력된 친구의 정보를 볼 수 있도록 만들기 (Friend, FriendMain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package ioTest;
import java.io.Serializable;
public class Friend implements Serializable{
private String name;
private String birth;
private String addr;
private String tel;
//getter, setter 생성
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBirth() {
return birth;
}
public void setBirth(String birth) {
this.birth = birth;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
package ioTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Scanner;
public class FriendMain {
//f의 값들을 Arraylist를 만들어서 저장시켜준다.
//while문을 돌면 값들이 초기화가 되기 때문에 전역변수로 만들어주기 위해 맨 위에다가 쓴다.
ArrayList<Friend>arr=new ArrayList<Friend>();
File dir,file;
@SuppressWarnings("unchecked")
public FriendMain() throws IOException, ClassNotFoundException {
dir=new File("src\\ioTest");
file=new File(dir, "myFriend.txt");
if(file.exists()) {//파일이 있으면
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(file));
//Object은 반드시 캐스팅을 해줘야함
arr=(ArrayList<Friend>)ois.readObject(); //ois파일을 읽어서 arr에 저장
}else {
file.createNewFile(); //파일 생성
}
}
public void fileUse() throws FileNotFoundException, IOException {
Scanner sc=new Scanner(System.in);
while(true) {
System.out.println("1.친구등록 2.친구보기 3.종료(저장)");
int num=sc.nextInt();
sc.nextLine(); //엔터를 치면 버려주기
if(num==1) { //친구등록
System.out.println("이름>>");
String name=sc.nextLine();
System.out.println("생일>>");
String birth=sc.nextLine();
System.out.println("주소>>");
String addr=sc.nextLine();
System.out.println("전화>>");
String tel=sc.nextLine();
//setter가 생성자 역할도 한다.
//입력한 정보를 담을 때 f라는 객체를 이용한다.
Friend f=new Friend();
f.setAddr(addr);
f.setBirth(birth);
f.setName(name);
f.setTel(tel);
arr.add(f);
}else if(num==2) { //친구보기
for(Friend f:arr) {
System.out.println("이름: "+f.getName());
System.out.println("생일: "+f.getBirth());
System.out.println("주소: "+f.getAddr());
System.out.println("전화: "+f.getTel());
}
}else if(num==3) { //저장시켜놓고 종료하기
//무엇을 저장하는가?
//friend가 담긴 arraylist를 내보내야함. 객체를 어떻게 내보낼까?
ObjectOutputStream oos=
new ObjectOutputStream(new FileOutputStream(file));
//try-catch대신에 throws를 사용하기. 그 메소드를 호출하는 쪽에도 반드시 throws를 써주기
//객체를 내보내는 writeObject메소드
oos.writeObject(arr);
System.out.println("종료");
System.exit(0);
}else { //입력오류
System.out.println("입력오류");
}
}
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
FriendMain fm=new FriendMain();
//생성자가 제일 먼저 실행되므로 ArrayList의 값들을 생성자에 저장시켜줘야한다.
fm.fileUse();
}
}
|
- 파일 복사하기 (FileCopyTest)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package ioTest;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopyTest {
public static void main(String[] args) {
long millisecond=0;
try{
FileInputStream fis=new FileInputStream("src\\utilTest\\CapitalApp.java");
FileOutputStream fos=new FileOutputStream("copy.txt");
//파일 복사를 시작하기 전 시간
millisecond=System.currentTimeMillis();
int i;
while((i=fis.read())!=-1) {
fos.write(i);
}
//파일을 복사하는데 걸리는 시간 계산
millisecond=System.currentTimeMillis()-millisecond;
}catch(IOException e) {
e.printStackTrace();
}
System.out.println("파일 복사하는 데: "+millisecond+" milliseconds 소요되었습니다.");
}
}
|
출처: Do it 자바 프로그래밍 입문 (544p-파일복사하기)
-
직렬화 테스트하기 (SerializationTest)
-
serial.out이라는 파일을 하나 만들어준다.
-
FriendMain에서는 ArrayList를 이용하여 한꺼번에 출력하였는데 여기서는 writeObject의 인수로 객체 하나씩 출력한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package ioTest;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Person implements Serializable {
private static final long serialVersionUID=-1503252402544036183L;
String name;
//transient는 직렬화 시키지 말라는 뜻. transient를 쓰면 대표이사가 null이라 나옴
//transient String job;
String job;
public Person() {}
public Person(String name, String job) {
this.name=name;
this.job=job;
}
public String toString() {
return name+","+job;
}
}
public class SerializationTest {
public static void main(String[] args) throws ClassNotFoundException {
Person personAhn=new Person("안재용", "대표이사");
Person personKim=new Person("김철수", "상무이사");
try{
FileOutputStream fos=new FileOutputStream("serial.out");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(personAhn);
oos.writeObject(personKim);
}catch(IOException e) {
e.printStackTrace();
}
try{
FileInputStream fis=new FileInputStream("serial.out");
ObjectInputStream ois=new ObjectInputStream(fis);
Person p1=(Person)ois.readObject();
Person p2=(Person)ois.readObject();
System.out.println(p1);
System.out.println(p2);
}catch(IOException e) {
e.printStackTrace();
}
}
}
|
출처: Do it 자바 프로그래밍 입문 (550p-직렬화 테스트하기)
-
File과 관련된 예제 (FileExam)
-
폴더를 만들고 텍스트 파일도 하나 만들어서 저장한다.
-
listFiles()는 파일을 배열형태로 돌려준다. 배열이므로 for문을 써서 File f에 대입한다.
-
lastModified()는 마지막에 수정한 날짜를 long형태로 알려준다.
-
long형태가 아닌 알아보기 쉬운 형태로 바꾸기 위해 prinf()메소드를 이용한다. prinf는 출력하는 형태를 지정할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package ioTest;
import java.io.File;
public class FileExam {
public static void main(String[] args) {
File f1=new File("c:\\windows\\system.ini");
//getPath()는 경로, getParent()는 부모 경로, getName()은 파일의 이름
System.out.println(f1.getPath()+"="+f1.getParent()+"="+f1.getName());
String res="";
if(f1.isFile()) res="파일";
else if(f1.isDirectory()) res="디렉토리";
System.out.println(f1.getPath()+"은 "+res+" 입니다.");
File f2=new File("folder");
if(f2.isFile()) res="파일";
else if(f2.isDirectory()) res="디렉토리";
System.out.println(f2.getPath()+"은 "+res+" 입니다.");
if(!f2.exists()) {
System.out.println("파일없음");
}
System.out.println("----서브 리스트----");
File[]subFiles=f2.listFiles(); //파일을 배열형태로 알려준다.
for(int i=0;i<subFiles.length;i++) {
File f=subFiles[i];
long t=f.lastModified(); //마지막에 수정한 날짜를 long형태로 알려준다.
//long형태가 아닌 알아보기 쉬운 날짜 형태로 바꾸기 위해 printf로 출력하는 형태를 지정
System.out.println(f.getName());
System.out.println("파일 크기: "+f.length());
System.out.printf("수정한 시간: %ty년 %tb %td %ta %tT\n", t,t,t,t,t);
//20년 6월 09 화 15:00:50
}
}
}
|
-
꼭 Object형태로 내보내지 않아도 된다. File형태로 내보내도 된다. (CapitalApp2)
-
utilTest패키지에 CapitalApp이 저장되어 있다는 가정하에 ioTest패키지에 CapitalApp2 클래스를 생성한다.
-
CapitalApp.showMenu()를 선언하면 오류가 발생한다. utilTest패키지에 있는 showMenu의 접근제어자를 default(생략)가 아닌 public으로 바꿔준다. CapitalApp클래스도 마찬가지로 public으로 바꿔준다.
-
나라와 수도를 입력한 해쉬맵을 파일에 저장하고 종료하는 메소드인 save()를 생성한다.
-
FileWriter로 file형태로 내보낸다.
-
중복을 허용하지 않는 Set의 <String>형태로 나라만 가져오고, iterator로 나라를 방문한다. 나라와 수도를 key와 value변수를 선언하여 가져오고 write를 이용하여 나라와 수도를 출력한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
package ioTest;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
import utilTest.CapitalApp;
public class CapitalApp2 {
private HashMap<String, String>map=new HashMap<String, String>();
File dir,file;
public CapitalApp2(){
dir=new File("src\\ioTest");
file=new File(dir,"myCapital.txt");
map.clear();
try {
if(!file.exists()) { //파일 없음
file.createNewFile(); //파일생성
return;
}
//파일로부터 읽어오기 위해 만드는 스캐너
Scanner scanner=new Scanner(file);
while(scanner.hasNext()) {
String country=scanner.next(); //나라
String capital=scanner.next(); //수도
map.put(country, capital);
}
scanner.close();
}catch (IOException e) {
e.printStackTrace();
}
}
private void input() {
System.out.println("현재"+map.size()+" 개 나라와 수도 입력");
while(true) {
System.out.println("나라와 수도 입력(종료는 x)>>");
String cont=CapitalApp.sc.next(); //나라
if(cont.toUpperCase().equals("X")) break;
if(map.containsKey(cont)==true) {
System.out.println("이미 입력한 나라입니다.");
continue;
}
String cap=CapitalApp.sc.next();
map.put(cont,cap);
}
}
private void quiz() {
//Set: 중복을 허용하지 않는 자료구조
Set<String> set=map.keySet();
Object[]arr=set.toArray(); //toArray()를 이용하여 set을 배열형태로 변환
while(true) {
int n=(int)(Math.random()*map.size());
//if(map.size()==0) return;
//if(map.isEmpty()) return;
//아무런 값도 입력하지 않은 상태에서 퀴즈풀기를 시도하면 오류가 뜬다.
//try-catch문에 예외처리를 적어준다.
String city="";
try {
city=(String)arr[n];
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("map 이 비어 있습니다.");
return;
}
String dosi=map.get(city);
System.out.println(city+" 의 수도는? 종료는 x>>");
String dap=CapitalApp.sc.next();
if(dap.toLowerCase().equals("x")) {
System.out.println("종료합니다.");
break;
}
if(dap.equals(dosi)) {
System.out.println("정답입니다.");
}
else {
System.out.println("틀렸습니다.");
}
}
}
//해쉬맵을 파일에 저장하고 종료하는 메소드
private void save() {
FileWriter fw=null;
try {
fw=new FileWriter(file);
Set<String> set=map.keySet(); //나라만 가져옴
Iterator<String> it=set.iterator(); //나라를 방문하기 위해
while(it.hasNext()) {
String key=it.next(); //나라 가져옴
String value=map.get(key); //수도를 가져옴
fw.write(key+" "); //나라 출력
fw.write(value+"\n"); //수도 출력
}
fw.close();
System.out.println("종료");
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
System.out.println("파일저장 오류");
}
}
public static void main(String[] args) {
CapitalApp2 ca2=new CapitalApp2();
while(true) {
CapitalApp.showMenu();
int choice=CapitalApp.sc.nextInt();
switch(choice) {
case 1 : ca2.input(); break;
case 2 : ca2.quiz(); break;
case 3 : ca2.save(); break;
default: System.out.println("입력오류");
}
}
}
}
|