Professional Documents
Culture Documents
ch8 IOStreams
ch8 IOStreams
faa)
ในบทที่แปดนี้เราจะพูดถึงการอาน และเขียนขอมูลผานทาง stream หรือชองทางการสงขอมูล
เราจะดูถึงวิธีการ กระบวนการตาง ๆ ที่เกี่ยวของกับขอมูลนําเขา และการนําขอมูลออก
หลังจากจบบทนี้แลว ผูอานจะไดทราบถึง
o ความหมายของ stream
o Class ตาง ๆ ที่ Java มีใหในการประมวลผลดวย stream
o การสราง directory
o การสราง file การเปดและปด file การอานและเขียน file
o ขอแตกตางระหวาง text file และ binary file
8.1 Streams
โปรแกรมตัวอยางที่เห็นนี้เปนการแสดงขอมูลที่เกี่ยวกับไฟลที่กําหนดให
1: /**
2: Get inofrmation about file
3: */
4:
5: import java.io.*;
6: import static java.lang.System.out;
7:
8: class FileInfo {
9: public static void main(String[] args) {
10: //get path from command-line argument
11: File path = new File(args[0]);
12:
13: //display some info. about this file
14: if(path.exists()) {
15: out.println(path + " does exist.");
16: out.println("Readable : " + statusOk(path.canRead()));
17: out.println("Writable : " + statusOk(path.canWrite()));
18: out.println("Directory? : " + statusOk(path.isDirectory()));
19: out.println("File? : " + statusOk(path.isFile()));
20: out.println("Hidden? : " + statusOk(path.isHidden()));
21: }
22: else
23: out.println(path + " does not exist.");
24: }
25:
26: //return "Yes" or "No"
27: public static String statusOk(boolean yes) {
28: return yes ? "Yes" : "No";
29: }
30: }
e:\bc221Book\source
e:\bc221Book\source
\source
\bc221Book\source\FileInfo.java
1
Path ที่เริ่มตนจาก root directory ไปจนถึงไฟล เชน C:\javaBook\revision2\chapter2.doc
2
Path ที่เริ่มภายใน directory ที่มีโปรแกรมอยู เชนถาเราทํางานใน D:\temp ไฟลที่เราคนหาจะอยูใน directory นี้
3
URI หมายถึง Uniform Resource Identifier ซึ่งเปนอีกรูปแบบหนึ่งของ URL (Uniform Resource Relocator) ที่ใช
ในการคนหา web site
246
บทที่ 8: Streams I/O
เราเรียกใช method ที่มีอยูใน class File ในการตรวจสอบขอมูลของ file วาเปน file ลักษณะ
ไหน ขอมูลเฉพาะคือ อะไร คําวา file ใน Java นั้นเปนไดสองอยาง คือ file ที่เก็บขอมูลที่เราใช
(หรือ ระบบใช) และ file ที่เก็บ file หรือที่รียกวา directory (หรือ folder)
1: /**
2: Displaying file information
3: */
4:
5: import java.io.*;
6: import java.util.Date;
7: import static java.lang.System.out;
8:
9: class FileInfo1 {
10: public static void main(String[] args) {
11: //explain how to use if no argument is given
12: if(args.length < 1) {
13: out.println("Usage: FileInfo1 file-name");
14: System.exit(1);
15: }
16: //display information about this file
17: echoFileInfo(new File(args[0]));
18: }
19:
20: private static void echoFileInfo(File file) {
21: //display if file is a file or a directory
22: if(file.isFile())
23: out.println("\n" + file + " is a file.");
247
เริ่มตนการเขียนโปรแกรมดวย Java
24: if(file.isDirectory()) {
25: String []list = file.list();
26: out.println("\n" + file + " is a directory.");
หลังจากนั้นเราก็แสดงผลออกทางหนาจอ ดังที่แสดงใหดูเปนตัวอยางดานลางนี้
FileInfo1.java is a file.
Absolute path: D:\Intro.to.Java\Word.Format\edition3\source\FileInfo1.java
Name: FileInfo1.java
Parent: null
Path: FileInfo1.java
Length: 1364
Last modified: Mon May 16 08:09:53 ICT 2005
1: /**
2: Show files in directory
3: */
4:
5: import java.io.*;
6: import java.util.Arrays;
7:
8: //extract file name from path
9: //must implements FilenameFilter and override method accept()
10: //to get files with given information into a list
11: class DirFilter implements FilenameFilter {
12: String fileName;
13:
14: //constructor
15: DirFilter(String fileName) {
248
บทที่ 8: Streams I/O
>java DirListing te
BankRate.class
BankRate.java
ByteShort.class
ByteShort.java
Calculate.class
Calculate.java
249
เริ่มตนการเขียนโปรแกรมดวย Java
Method list() กําหนดให parameter ที่สงเขาไปเปน object จาก class FileNameFilter ดังนั้น
เราสามารถที่จะเขียน method accept() ในลักษณะใดก็ได ในที่นี้เราดึงเอาเฉพาะชื่อไฟลที่ไมมี
path รวมอยูดวย ดวยการกําหนดดังนี้
Method list() ใน class File มีอยูสองตัว คือ ตัวที่ไมมี parameter และตัวที่มี parameter
สําหรับ method ตัวที่มี parameter นี้ parameter ตองเปน object จาก class FileNameFilter
ดังนั้นเราตองสราง class ที่มาจาก class นี้พรอมทั้งทําการ override method accept() ให
ทํางานตามที่เราตองการ ผูอานควรทดลอง run โปรแกรมตัวนี้ดวยเงื่อนไขตาง ๆ เพื่อใหเกิด
ความเขาใจมากยิ่งขึ้น และควรทดลองเขียน code ให method accept() ใหมโดยกําหนดใหทํา
การตาง ๆ ที่ตางออกไปจากที่เขียนในโปรแกรมตัวอยางนี้
รูปแบบของขอมูลที่ถูกจัดเก็บในไฟลนั้นถูกแบงออกเปนสองลักษณะคือ
250
บทที่ 8: Streams I/O
1: /**
2: Reading from a text file
3: */
4:
5: import java.io.BufferedReader;
6: import java.io.File;
7: import java.io.FileReader;
8: import static java.lang.System.out;
9: import static java.lang.System.err;
10:
11: class ReadingTextFile {
12: public static void main(String[] args) {
13: String filename = args[0];
14:
15: try {
16: File file = new File(filename);
17: FileReader fileReader = new FileReader(file);
18: BufferedReader reader = new BufferedReader(fileReader);
19: String line;
20: int i = 1;
21: while((line = reader.readLine()) != null) {
22: out.printf("%4d: %s%n", i++, line);
23: }
24: }
25: catch(Exception e) {
26: err.printf("Unable to open file name '%s': %s",
filename, e.getMessage());
27: }
28: }
29: }
1: /**
2: Reading a text file
3: */
4:
5: import java.io.*;
6:
7: class ReadTextFile {
8: public static void main(String[] args) throws IOException {
9: FileInputStream in; //file input stream
10: int ch; //store each character read
11:
12: try {
13: in = new FileInputStream(args[0]);
14: while((ch = in.read()) != -1) {
15: System.out.print((char)ch);
251
เริ่มตนการเขียนโปรแกรมดวย Java
16: }
17: in.close();
18: }
เพื่อใหผูอานเขาใจงายขึ้น เราจึงจัดเก็บขอมูลอยูในรูปแบบของ
เชน
Notebook 12.00 30
CoffeeMug 5.00 40
PaperCutter 12.50 25
1: /**
2: Reading text data from a file
3: */
4:
5: import java.io.*;
6: import static java.lang.System.out;
7: import static java.lang.System.err;
8:
9: class TextWithStreamTok {
10: public static void main(String[] args) throws IOException {
11: BufferedReader in = null; //input buffer
12: FileReader file = null; //input file
13: StreamTokenizer stream = null; //tokens
14:
15: try {
16: file = new FileReader(args[0]); //get a file
17: in = new BufferedReader(file); //storage buffer
252
บทที่ 8: Streams I/O
253
เริ่มตนการเขียนโปรแกรมดวย Java
while(stream.nextToken() != StreamTokenizer.TT_EOF) {
//data is a string
if(stream.ttype == StreamTokenizer.TT_WORD) {
descs[i++] = stream.sval;
}
//data is a number (price or unit)
if(stream.ttype == StreamTokenizer.TT_NUMBER) {
//first data in line is price
if(first == true) {
prices[j++] = stream.nval;
first = false;
}
//next one is unit price
else {
units[k++] = (int)stream.nval;
first = true;
}
}
//ignore EOL
if(stream.ttype == StreamTokenizer.TT_EOL) {
/* do nothing */
}
}
Notebook 12.0 30
CoffeeMug 5.0 40
PaperCutter 12.5 25
หรือจะใหอยูในบรรทัดเดียวกันก็ได เชน
254
บทที่ 8: Streams I/O
1: /**
2: Using '|' as delimiter in a text file
3: */
4:
5: import java.io.*;
6: import java.util.StringTokenizer;
7: import static java.lang.System.out;
8: import static java.lang.System.err;
9:
10: class TokenWithDelimiter {
11: public static void main(String[] args) throws IOException {
12: //data to write to file
13: String[] items = {"Notebook", "Coffee Mug", "Paper Cutter"};
14: double[] prices = {12.0D, 5.0D, 12.5D};
15: int[] units = {30, 40, 25};
16:
17: //check to see if a file is provided
18: if(args.length < 1) {
19: err.println("Usage: TokenWithDelimeter file-name.");
20: System.exit(1);
21: }
22: writeToFile(args[0], items, prices, units);
23: processData(args[0]);
24: }
25:
26: //writing data in arrays to a given file
27: private static void writeToFile(String fileName, String[] items,
28: double[] prices, int[] units)
29: throws IOException {
30: File dataFile = null;
31: FileWriter fWriter = null;
32: BufferedWriter buffer = null;
33: PrintWriter outFile = null;
34:
35: try {
36: dataFile = new File(fileName);
37: fWriter = new FileWriter(dataFile);
38: buffer = new BufferedWriter(fWriter);
39: outFile = new PrintWriter(buffer);
40:
41: //printing data to file with '|' in between
42: for(int i = 0; i < items.length; i++) {
43: outFile.print(items[i]);
44: outFile.print('|');
45: outFile.print(prices[i]);
46: outFile.print('|');
47: outFile.println(units[i]);
48: }
49: }
50: catch(IOException e) {
51: err.println("Error writing to file");
52: e.printStackTrace();
53: System.exit(1);
54: }
55: finally {
56: if(outFile != null)
57: outFile.close();
58: }
59: }
60:
61: //reading data from a given file & display to screen
62: private static void processData(String fileName)
63: throws IOException {
255
เริ่มตนการเขียนโปรแกรมดวย Java
256
บทที่ 8: Streams I/O
ผลลัพธที่ไดจากการ run
1: /**
2: Simple record for sequential access file
3: */
4:
5: import java.io.Serializable;
6:
7: class OfficeSupply implements Serializable {
8: private int id;
9: private String name;
257
เริ่มตนการเขียนโปรแกรมดวย Java
1: /**
2: Creating sequential access file
3: */
4:
5: import java.io.*;
6: import java.util.*;
7: import java.lang.*;
8: import static java.lang.System.out;
9: import static java.lang.System.err;
10:
11: class CreateSequentialFile {
12: private ObjectOutputStream ostream;
13: private FileOutputStream fstream;
4
นําเอา object กลับออกมาจากการ serialization
258
บทที่ 8: Streams I/O
14:
15: //create an output file
16: CreateSequentialFile(String fName) {
ostream.writeObject(record);
259
เริ่มตนการเขียนโปรแกรมดวย Java
เราไดเขียนโปรแกรมเพื่อปอนขอมูลเขาสูไฟลขึ้นดังนี้
ฌํ ♣sr ♀OfficeSupply▼↕ sY
ในการดึงขอมูลกลับออกมาจากไฟลนั้นเราก็ทําคลายกับการนําขอมูลเขา ตางกันตรงที่วาเราตอง
เรียกใช ObjectInputStream และ FileInputStream แทน ทั้งนี้การอานขอมูลก็ตองเรียกใช
method readObject() แทนการใช writeObject() ที่เราไดทํามากอนหนานี้
1: /**
2: Accessing sequential access text file
3: */
4:
5: import java.io.*;
6: import java.util.*;
7: import java.lang.*;
8: import static java.lang.System.out;
9: import static java.lang.System.err;
10:
11: class AccessSequentialFile {
12: private ObjectInputStream input;
13:
14: //open an input file
15: AccessSequentialFile(String fName) {
16: try {
17: input = new ObjectInputStream(
18: new FileInputStream(fName));
19: }
20: catch(IOException ioe) {
21: err.printf("Cannot open file: %s%n", fName);
22: System.exit(1);
23: }
24: }
25:
26: //read records from file
260
บทที่ 8: Streams I/O
เราไดเขียนโปรแกรมสําหรับดึงขอมูลออกมาจากไฟลดังนี้
1: /**
2: Test writing/reading sequential text file
3: */
4:
5: import static java.lang.System.out;
6:
7: class ReadSequentialFile {
8: public static void main(String[] args) {
9: if(args.length < 1) {
10: out.println("Usage: TestSequentialFile file-name");
11: System.exit(1);
12: }
261
เริ่มตนการเขียนโปรแกรมดวย Java
13:
14: //reading sequential file and display records
15: AccessSequentialFile af = new AccessSequentialFile(args[0]);
262
บทที่ 8: Streams I/O
1. id
2. description
3. price
4. quantity
เรามาดูโปรแกรมตัวอยางกันดีกวา
1: /**
2: Binary file - sequential access
3: */
4:
5: import java.io.*;
6: import static java.lang.System.out;
7: import static java.lang.System.err;
8:
9: class DataFile {
10: public static void main(String[] args) throws IOException {
11: FileOutputStream fout; //file output stream
12: DataOutputStream dout; //data output stream
13: FileInputStream fin; //file input stream
14: DataInputStream din; //data input stream
15: //setting up data to be written to a file
16: int[] id = {100, 200, 300};
17: String[] desc = {"Coffee Mug", "Bookmark", "Note book"};
18: double[] prices = {5.00, 2.00, 10.00};
19: int[] unit = {12, 50, 30};
20:
21: //variables storing data from file
22: int no;
23: String description;
24: double price, total = 0.00;
25: int unitPrice;
26:
27: //open file for writing
28: try {
29: fout = new FileOutputStream(args[0]);
30: dout = new DataOutputStream(fout);
31: for(int i = 0; i < desc.length; i++) {
32: dout.writeInt(id[i]);
33: dout.writeUTF(desc[i]);
34: dout.writeDouble(prices[i]);
35: dout.writeInt(unit[i]);
36: }
37: dout.close();
38: }
39: catch(FileNotFoundException e) {
40: err.println("Cannot open " + args[0]);
41: return;
42: }
43: catch(ArrayIndexOutOfBoundsException e) {
44: err.println("Usage: DataFile file-name.");
45: return;
46: }
47:
48: //open file for input
49: try {
50: fin = new FileInputStream(args[0]);
51: din = new DataInputStream(fin);
52: out.printf("%4s %-10s %12s %9s %7s%n",
53: "Id", "Description", "Price", "Quantity", "Total");
54: while(true) {
55: no = din.readInt();
56: description = din.readUTF();
57: price = din.readDouble();
263
เริ่มตนการเขียนโปรแกรมดวย Java
264
บทที่ 8: Streams I/O
ตัวอยางที่เห็นดานบนเปนอีกวิธีหนึ่งที่เราตองการแสดงใหผูอานเห็นวาเราสามารถที่จะใช
method อื่น ๆ ที่ Java มีใหในการเขียนหรืออานไฟลที่อยูในรูปแบบของ binary ทั้งนี้ก็คงจะ
1: /**
2: Differences between WriteChars() and WriteUTF()
3: */
4:
5: import java.io.*;
6:
7: class WriteCharsAndWriteUTF {
8: public static void main(String[] args) throws IOException {
9: File f = new File(args[0]);
10: DataOutputStream out = new DataOutputStream(
11: new BufferedOutputStream(
12: new FileOutputStream(f)));
13: out.writeUTF("If it does not work, blame the computer.");
14: int utfSize = out.size();
15:
16: out.writeChars("If it does not work, blame the computer.");
17: int charsSize = out.size() - utfSize;
18:
19: out.close();
20: System.out.printf("writeUTF() writes %d bytes%n", utfSize);
21: System.out.printf("writeChars writes %d bytes%n", charsSize);
22: }
23: }
265
เริ่มตนการเขียนโปรแกรมดวย Java
1: /**
2: Writing/Reading Random access file
3: */
4:
5: import java.io.*;
6: import java.io.RandomAccessFile;
7: import static java.lang.System.out;
8: import static java.lang.System.err;
9:
10: class RandomAccessFileDemo {
11: public static void main(String[] args) throws IOException {
12: //data to be written to a file
13: String[] names = {"John", "Paul", "Stephen", "Hendrix"};
14: String[] lasts = {"Kawakami", "Collins", "Anderson", "McCoy"};
15: int[] years = {1965, 1978, 1985, 1972};
16: double[] pays = {2400.0, 500.0, 5000.0, 9500.0};
17:
18: //random positions for reading
19: int[] random = {2, 3, 0, 1};
20:
21: //writing to a file
22: RandomAccessFile fout = new RandomAccessFile("emp.dat", "rw");
23: try {
24: for(int i = 0; i < 4; i++) {
25: Employee emp = new Employee(names[i], lasts[i],
26: years[i], pays[i]);
27: emp.write(fout);
28: }
29: }
30: catch(IOException e) {
31: err.println("Error writing file");
32: e.printStackTrace();
33: System.exit(1);
34: }
35: finally {
36: if(fout != null) {
37: fout.close();
38: }
39: }
40:
41: //reading from a file by position given in random array
42: RandomAccessFile fin = null;
43: try {
44: fin = new RandomAccessFile("emp.dat", "r");
45: Employee em = new Employee();
46: out.printf("Records in file: %d (%d bytes)%n%n",
47: em.size(fin), fin.length());
48: for(int i = 0; i < 4; i++) {
49: em.read(fin, random[i]);
50: out.print("Record #" + (i+1) + ": ");
51: em.show();
52: }
53: }
54: catch(IOException e) {
55: err.println("Error reading file");
56: e.printStackTrace();
57: System.exit(1);
58: }
59: finally {
60: if(fin != null)
61: fin.close();
62: }
63: }
64: }
266
บทที่ 8: Streams I/O
1: /**
2: Simple record for random-access file
3: */
4:
5: import java.io.*;
6: import java.io.RandomAccessFile;
7: import java.lang.String;
8: import static java.lang.System.out;
9: import static java.lang.System.err;
10:
11: class Employee {
12: private String firstName; //15 characters (30 bytes)
13: private String lastName; //15 characters (30 bytes)
14: private int year; //4 bytes
15: private double salary; //8 bytes
16: private static final int RECORD_SIZE = 72;
17:
18: //default constructor
19: Employee() {
20: firstName = "";
21: lastName = "";
22: year = 0;
23: salary = 0.0D;
24: }
25:
26: //setting up fields
27: Employee(String firstName, String lastName,
28: int year, double salary) {
267
เริ่มตนการเขียนโปรแกรมดวย Java
268
บทที่ 8: Streams I/O
write(RandomAccessFile)
read(RandomAccessFile, position)
writeString(DataOutptu, String, length)
readString(DataInput, length)
size(RandomAccessFile)
หนาที่ของ write() คือ การนําขอมูลจาก field ตาง ๆ ของ Employee object เขาสูไฟล
ตามลําดับของขอมูลใน array ดังที่เราไดกลาวไวแลว โดยไดรับการชวยเหลือจาก
269
เริ่มตนการเขียนโปรแกรมดวย Java
file.seek((long)(position * RECORD_SIZE));
ซึ่งเมื่อหาตําแหนงไดแลวเราก็อานขอมูลไปเก็บไวในตัวแปรที่เราไดกําหนดไว ดังที่ไดแสดงให
ดูในบรรทัดที่ 79 – 83 เชนเดียวกันกับการเขียนขอมูลเขาสูไฟล เราตองใช method
readString() ชวยในการอานขอมูลที่เปน String ใหเรา
D:\>java RandomAccessFileDemo
Enter file name: temp.dat
Records in file: 4 (288 bytes)
270
บทที่ 8: Streams I/O
1: /**
2: Updating Random-access file
3: */
4:
5: import java.io.*;
6: import java.util.Scanner;
7: import java.io.RandomAccessFile;
8: import static java.lang.System.out;
9: import static java.lang.System.err;
10:
11: class Update {
12: public static void main(String[] args) throws IOException {
271
เริ่มตนการเขียนโปรแกรมดวย Java
272
บทที่ 8: Streams I/O
D:\>java RandomAccessFileDemo
Enter file name: temp.dat
Records in file: 4 (288 bytes)
สรุป
แบบฝกหัด
273
เริ่มตนการเขียนโปรแกรมดวย Java
4. จงเขียนโปรแกรมที่อานขอมูลจากไฟลที่เขียนขึ้นในขอ 3 เสร็จแลวใหคํานวณหาผลรวม
ของขอมูลในแตละแถว หลังจากนั้นใหเขียนขอมูลในแตละแถวรวมทั้งผลรวมที่หาไดลงใน
5. จงปรับปรุงโปรแกรมที่เขียนขึ้นในขอ 4 โดยใหมีการคํานวณหาคาเฉลี่ยของขอมูลทุกตัวใน
แนวตั้ง (column) นําผลลัพธที่ไดพรอมทั้งขอมูลในแตละแถวไปเก็บไวในไฟลตัวใหม
6. จงเขียนโปรแกรมที่อานขอมูลในรูปแบบที่กําหนดใหดานลางนี้ หลังจากนั้นใหแสดงขอมูลที่
อานไดไปยังหนาจอ โดยไมตอ งแสดง delimiter ที่ใช ใหกําหนดจํานวนของขอมูลที่มีอยูใน
ไฟลจํานวนเทากับ 10 แถว
John Longman+25.0+30.50+48.00
Peter Wang+35.00+50.00+98.00
…
…
Mike Kawakami+90.00+80.00+85.00
class Student {
String firstName;
String lastName;
double[] grades;
}
274