33
บทที10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Files คลาส FileInputStream และ FileOutputStream ใช้ในการอ่านและเขียนข้อมูลแบบ Binary ส่วนคลาส FileReader และ FileWriter ใช้ในการอ่านและเขียนข้อมูลแบบ Character โปรแกรม ReadFile.java แสดงการอ่าน ข้อมูลจากแฟ้มข้อมูลที่ชื่อ Hello.txt ซึ่งเป็นแฟ้มข้อมูลชนิดตัวอักษร โดยใช้คลาส FileReader ในการอ่านข้อมูล import java.io.*; public class ReadFile { public static void main(String[] args) { String filename = "hello.txt"; File myFile = new File(filename); if ( !myFile.canRead() ) { System.out.println(filename+ " is not readable"); System.exit(1); } try { FileReader input_file = new FileReader(myFile); int c; while ( ( c = input_file.read()) != -1 ) { // ตรวจสอบสถานะ End of Line System.out.print( (char) c ); // Casting จาก int ไปเป็น char } } catch (FileNotFoundException e) { System.out.println("Error file is not found"); System.exit(1); } catch (IOException e) { System.out.println("Error while reading the file"); System.exit(1); } } // จบ main } ---------- Java Output---------- Hello, how are you? This text file is used for test FileReader. Thank you. Binary Character FileInputStream FileOutputStream FileReader FileWriter

บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

บทท 10

การอาน และเขยนแฟมขอมล Read and Write Files คลาส FileInputStream และ FileOutputStream ใชในการอานและเขยนขอมลแบบ Binary สวนคลาส FileReader และ FileWriter ใชในการอานและเขยนขอมลแบบ Character โปรแกรม ReadFile.java แสดงการอานขอมลจากแฟมขอมลทชอ Hello.txt ซงเปนแฟมขอมลชนดตวอกษร โดยใชคลาส FileReader ในการอานขอมล

import java.io.*;

public class ReadFile {

public static void main(String[] args) {

String filename = "hello.txt";

File myFile = new File(filename);

if ( !myFile.canRead() ) {

System.out.println(filename+ " is not readable");

System.exit(1);

}

try {

FileReader input_file = new FileReader(myFile);

int c;

while ( ( c = input_file.read()) != -1 ) { // ตรวจสอบสถานะ End of Line

System.out.print( (char) c ); // Casting จาก int ไปเปน char }

}

catch (FileNotFoundException e) {

System.out.println("Error file is not found");

System.exit(1);

}

catch (IOException e) {

System.out.println("Error while reading the file");

System.exit(1);

}

} // จบ main

}

---------- Java Output----------

Hello, how are you?

This text file is used for test FileReader.

Thank you.

Binary

Character

FileInputStream FileOutputStream

FileReader FileWriter

Page 2: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 165

คลาส FileInputStream คลาส FileReader คลาส FileOutputStream และคลาส FileWriter สามารถน ามาใชในการอานหรอเขยนขอมลได แตไมเหมาะส าหรบการอานหรอเขยนขอมลชนด Primitive (เชน Integer หรอ Double ยกเวน Byte) เพราะคลาสทง 4 ถกออกแบบมาใหอานเขยนขอมลครงละ 8 บต หรอ 1 ไบตเทานน ในการใชงานจรงจ าเปนตองใชคลาสอนๆ ใน Package java.io ควบคไปดวย ตามทแสดงไวในตารางท 10.1

ตารางท 10.1 แสดงคลาสทใชในการอานและเขยนแฟมขอมล รปแบบการอานเขยน รปแบบคลาสทใช

อานขอมลตวอกษรจาก Text File ครงละ 1 ค า StreamTokenizer (new BufferedReader (new InputStreamReader(new FileInputStream)))

อานขอมลตวอกษรจาก Text File ครงละบรรทด BufferedReader (new InputStreamReader (new FileInputStream))

เขยนขอมลชนด Primitive ไปเปน Text File PrintWriter (new FileOutputStream) เขยนขอมลชนด Primitive ไปเปน Binary File DataOutputStream (new FileOutputStream) อานขอมลชนด Primitive จาก Binary File DataInputStream (new FileInputStream)

การอานขอมลตวอกษรจาก Text File ครงละ 1 ค า การอานขอมลครงละ 1 ค าจากตวอกษรสามารถใชรปแบบคลาสดงตวอยาง

StreamTokenizer (new BufferedReader (new

InputStreamReader(new

FileInputStream)));

คลาส BufferedReader ใชส าหรบจองหนวยความจ า (Buffer) ส าหรบการอานขอมลจ านวนมาก ซงตองใชคกบคลาส InputStreamReader เสมอ เนองจากคลาส FileInputStream ไมสามารถเปน Parameter ใน Constructor ของ BufferedReader ไดโดยตรง

การอ านข อม ล โดยใชคลาส StreamTokenizer ไดกล าว ไปแล ว ในบทท 8 โปรแกรม Read1WordFromTextFile.java แสดงการอานขอมลจาก Hello.txt ครงละ 1 ค า โดยขอมลใน Hello.txt คอ

Hello, how are you? This text file is used for test FileReader. Thank you.

Page 3: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

166 การเขยนโปรแกรมภาษา Java

import java.io.*;

public class Read1WordFromTextFile {

public static void main(String[] args) {

// แฟมขอมลชอ Hello.txt String filename = "Hello.txt";

File myFile = new File(filename);

// ตรวจสอบกอนวา Hello.txt มอยจรงโดยใช Method canRead() if ( !myFile.canRead() ) {

System.out.println(filename+ " is not readable");

System.exit(1);

}

// สรางวตถ StreamTokenizer จาก BufferedReader try {

StreamTokenizer token = new StreamTokenizer (

new BufferedReader (

new InputStreamReader (

new FileInputStream (myFile))));

/* ถาไมมการใช Method whitespaceChars() โปรแกรมจะใช ชองวางในการตดค า การใชค าสง whitespaceChars() เพอเพมตวอกษรทเปน White space เชน ; หรอ ? ดวย ท าใหโปแกรมจะตดค าโดยไมสนใจเครองหมาย ดงตอไปน */ token.whitespaceChars('.','.');

token.whitespaceChars(',',',');

token.whitespaceChars('!','!');

token.whitespaceChars('?','?');

int ttype=0;

// ค าสง nextToken() เพออานค า ttype = token.nextToken();

while ( ttype != StreamTokenizer.TT_EOF) { // ทดสอบวาไมใช End of file

if(ttype == StreamTokenizer.TT_NUMBER) {

System.out.println(token.nval);

}

else {

System.out.println(token.sval);

}

ttype = token.nextToken(); // Read word

} // จบ while

} // จบ try catch (FileNotFoundException e) {

System.out.println("Error file is not found");

System.exit(1);

Page 4: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 167

}

catch (IOException e) {

System.out.println("Error while reading the file");

System.exit(1);

}

} // จบ main

}

---------- Java Output----------

Hello

how

are

you

This

text

file

is

used

for

test

FileReader

Thank

you

การอานขอมลตวอกษรจาก Text File ครงละบรรทด คลาสทใชในการอานขอมลทละบรรทดจากแฟมขอมลคอคลาส BufferedReader เหตผลทใชคลาสนเนองจากคลาสนม Method readLine() ซงเหมาะสมในการใชในการอานขอมลชนดตวอกษรเปนบรรทดซงมรปแบบการสรางคลาสดงตอไปน BufferedReader(new InputStreamReader(new FileInputStream));

โปรแกรม ReadLineFromTextFile.java แสดงการอานขอมลจาก Hello.txt ครงละ 1 บรรทดโดยใช

Method readLine() ของคลาส BufferedReader ในกรณทอานจนกระทงไปถงทายแฟมขอมล Method readLine() จะสงคากลบเปน Null ซงสามารถใชในการตรวจสอบจดสนสดของแฟมขอมลนนเอง import java.io.*;

public class ReadLineFromTextFile {

public static void main(String[] args) {

String filename = "Hello.txt";

File myFile = new File(filename);

if ( !myFile.canRead() ) {

System.out.println(filename+ " is not readable");

System.exit(1);

}

try {

BufferedReader reader = new BufferedReader (

new InputStreamReader (

new FileInputStream (myFile)));

String st = reader.readLine();

while( st != null ){

Page 5: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

168 การเขยนโปรแกรมภาษา Java

System.out.println( st );

st = reader.readLine();

}

} // จบ try catch (FileNotFoundException e) {

System.out.println("Error file is not found");

System.exit(1);

}

catch (IOException e) {

System.out.println("Error while reading the file");

System.exit(1);

}

} // จบ main

}

---------- Java Output----------

Hello, how are you?

This text file is used for test FileReader.

Thank you.

การเขยนขอมลชนด Primitive ไปเปน Text File คลาส PrintWriter สามารถใชเขยนขอมล Primitive ไปยง Text File ดงโปรแกรม WriteTextFile.java ในคลาส PrintWriter ม Method print() และ printlin() ทใชในการเขยนขอมลไปท Text File เมอมการเขยนขอมลแลวตองเรยกใช Method flush() ดวยเพราะการเขยนขอมลโดยใชค าสง print() หรอ println() เปนการเขยนขอมลไปท Buffer เทานน การเรยกใช Method flush() เพอใหเขยนขอมลลงดสกทนท สวน Method close() เปนการจบการเขยนขอมลไปทแฟมขอมล โปรแกรม WriteTextFile.java แสดงการเขยนขอมลตวอกษร ตวเลขจ านวนเตมและทศนยม ไปทแฟมขอมลเดยวกน import java.io.*;

public class WriteTextFile {

public static void main(String[] args) {

PrintWriter writer=null;

try {

writer = new PrintWriter (

new FileOutputStream (

new File("output.txt")));

}

// ตรวจสอบในกรณทไมสามารถเปดแฟมขอมลได catch (FileNotFoundException e) { System.out.println("Error file is not found");

System.exit(1);

}

writer.println("Hello how are you CS316”);

writer.println("This line will print String");

writer.println("Line below will write integer");

int i = 100;

writer.println(i);

double d = 123456.123456;

writer.println("Line below will write double");

writer.print(d);

Page 6: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 169

writer.flush(); writer.close();

} // จบ main

}

จากตารางท 10.1 สงเกตไดวา ไมมการอานขอมลทเปน Primitive จาก Text File เพราะเมอมการเขยน

ขอมลชนด Primitive ไปท Text File แลว ขอมลทถกเขยนจะเปลยนเปน Character เชนคา Integer 123 เมอเขยนจะมคาเปนตวอกษร ‘1’ ‘2’ และ ‘3’ ดงนนการอานขอมลกลบมาเปน Integer ผเขยนโปรแกรมจ าเปนตองทราบจ านวนหลกทแนนอนของขอมลทตองการอาน อยางไรกตาม ผเขยนโปรแกรมสามารถใชชองวางเปนตวแบงในการเกบคาได และสามารถใชคลาส StreamTokenizer อานคา กลบเปน Integer ดงโปรแกรม Read1WordFromTextFile.java ทแสดงไวแลวในชวงตน

เขยนขอมลชนด Primitive ไปท Binary File การเขยนขอมลชนด Primitive ไปท Binary File ท าไดโดยใชคลาส DataOutputStream และตองเรยก Method flush() ทกครงเพอใหขอมลทอยใน Buffer เขยนลงไปทดสกเหมอนค าสง flush() ในคลาส PrintWriter กอนการเขยนขอมลไปทแฟมขอมลควรมการตรวจสอบวาแฟมขอมลนนไมไดมอยกอนเพอปองกนไมใหเขยนขอมลทบแฟมขอมลเดมทมอย โปรแกรม WriteToBinary.java แสดงการเขยนขอมลชนด Integer คา 0 ถง 9 ไปทแฟมขอมลชอ ‚output.dat‛ และไมสามารถเปดอานไดโดย Text Editor ทวไป เนองจากเปนขอมลชนด Binary import java.io.*;

public class WriteToBinary {

public static void main(String[] args) {

File myFile = new File("output.dat");

if( myFile.isFile() ) {

System.out.println("Error, file exists");

System.exit(1);

}

try {

// สรางวตถ DataOutputStream ขน DataOutputStream output = new DataOutputStream (new

FileOutputStream (myFile));

// เขยนตวเลข 0 ถง 9 ไปทแฟมขอมล for(int i=0; i<10; i++) {

output.writeInt(i);

}

output.flush();

output.close();

}

catch (FileNotFoundException e) {

System.out.println("Error, cannot create the file");

System.exit(1);

}

catch (IOException e) {

System.out.println("Error while reading the file");

System.exit(1);

Page 7: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

170 การเขยนโปรแกรมภาษา Java

}

System.out.println("Writing file complete");

} // end main

}

---------- Java Output----------

Writing file complete

การอานขอมลชนด Primitive จาก Binary File โปรแกรม ReadFromBinary.java แสดงการอานขอมลชนด Primitive จาก Binary File โดยใชขอมลจากแฟมขอมล ‚output.data‛ ซงไดมาจากโปรแกรม WriteToBinary.java

ในคลาส DataInputStream ม Method ทใชในการอานขอมลชนด Integer โดยใช Method readInt() หรอถาตองการใหอานขอมลชนด Double ใช Method readDouble() ดงนน การบนทกขอมลใชคลาส DataOutputStream และการอานขอมลตองใชค าสงทสอดคลองกบขอมลทบนทกดวย เชน ถาบนทกขอมลเปน Integer โดยใช writeInt() เวลาอานขอมลควรใชค าสง readInt() import java.io.*;

public class ReadFromBinary {

public static void main(String[] args) {

try {

DataInputStream input = new DataInputStream (

new FileInputStream ("output.dat"));

for(int i=0; i<10; i++) {

// อานขอมลชนด Integer System.out.println( input.readInt() );

}

}

catch (FileNotFoundException e) {

System.out.println("Error, cannot create the file");

System.exit(1);

}

catch (IOException e) {

System.out.println("Error while reading the file");

System.exit(1);

}

} // จบ main

}

---------- Java Output----------

0

1

2

3

4

5

6

7

8

9

Page 8: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 171

โปรแกรม ReadFromBinary.java แสดงการอานขอมลโดยททราบจ านวนขอมลลวงหนา ดงนนสามารถใช for(int i=0; i<10; i++) ไดทนท แตถาไมทราบจ านวนขอมล สามารถใช Method ชอ available() ไดดงตวอยาง while(input.available() != 0 ) {

input.readInt();

}

Method available() จะสงจ านวนขอมลทเหลออย ในกรณทไมมขอมลในแฟมขอมลแลว available() จะสงคา 0 กลบ ดงนนผเขยนโปรแกรมใช while Loop ในการตรวจสอบคาได New File I/O ส าหรบ Java SDK version 1.4 หรอใหมกวา ผพฒนาภาษา Java ไดมการออกแบบ Package ใหมชอ java.nio และ java.nio.channels ซง Package Java New I/O มความสามารถเหนอกวาการอานเขยนขอมลโดยใช Stream ใน java.io แบบเดม ใน Package java.nio รวมค าสงทใชในการสราง Buffer เพอเกบขอมลส าหรบเขยนลงแฟมขอมลหรอใชเกบขอมลทอานมาจากอปกรณน าเขาดงภาพท 10.1 การเขยนขอมลไปทแฟมขอมลโดยใช Java New I/O จ าเปนตองใชคลาสและขนตอนดงตอไปน

1. ใชคลาส File ในการสราง Path และชอของแฟมขอมล รวมถงใชในการทดสอบวาแฟมขอมลสามารถเขยนไดซงปองกนไมใหเขยนทบแฟมขอมลทมอยแลว

2. ใชคลาส FileOutputSteam ในการสราง Stream ไปทแฟมขอมลเพอใชในการเขยน โดย Parameter ใน Constructor ของ FileOutputStream เปนวตถ File

3. ใชคลาส ByteBuffer ซงอยใน Package java.nio ในการเตรยมขอมลส าหรบเขยนไปทแฟมขอมล

4. ใชคลาส FileChannel ใน Package java.nio.channels เชอมตอกบแฟมขอมล เนองจาก ByteBuffer ไมสามารถเชอมตอกบแฟมขอมลไดโดยตรงจงจ าเปนตองอาศย FileChannel ใชเปนทางเชอมตอระหวาง ByteBuffer กบ FileOutputStream

ภาพท 10.1 แสดงการอานเขยนขอมลโดยใช Buffer เรมตนใชวตถ File เพอสรางชอของแฟมขอมลกอน รวมถงการตรวจสอบวาแฟมขอมลนสามารถอานได หลกจากนนสรางวตถ FileOutputStream เพอเปน Stream ทตดตอกบแฟมขอมล โดย Constructor ของ FileOutputStream เปนวตถจากคลาส File ทสรางขนไวแลวตอนแรก เมอไดวตถ FileOutputStream แลว จงสราง FileChannel โดยใช Method ของ FileOutputStream ทชอ getChannel() เมอไดวตถ FileChannel แลว ขนตอน

Write

Read Disk Buffer

Page 9: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

172 การเขยนโปรแกรมภาษา Java

ตอไปสรางวตถ ByteBuffer เพอใชในการเตรยมขอมลทตองการเขยน สวนวธการเขยนใช Method ของ FileChannel ชอ write(ByteBuffer buf)

ภาพท 10.2 แสดงความสมพนธของคลาสทใชในการอานแฟมขอมล ภาพท 10.2 แสดงความส าพนธระหวางคลาสตางๆ ใน Package java.io, java.nio และ java.nio.channels การเขยนขอมลไปทแฟมขอมลตองเตรยมขอมลทตองการเขยนไวท ByteBuffer ดงนนผอานตองเขาใจการใชงานคลาส ByteBuffer กอนวามเรยกใชงานไดอยางไร ByteBuffer การเขยนขอมล จ าเปนตองเตรยม Buffer เปนทเกบขอมลส าหรบการเขยนขนกอน โดยใชคลาส ByteBuffer ซงคลาสนเปน Abstract Class ท าใหไมสามารถสรางวตถไดโดยตรงจากคลาส ByteBuffer แตใชการเรยก Static Method ทชอ allocate() ในคลาส ByteBuffer แทน เพอท าการสรางวตถจาก ByteBuffer ไดดงตวอยาง ByteBuffer buf = ByteBuffer.allocate(1024);

ตวเลข 1024 หมายถงการจองหนวยความจ าขนาด 1024 ไบต (ซงคานไมสามารถเปลยนแปลงไดหลงจาก

มการก าหนดคาแลว) ใหกบตวแปร buf โดยมโครงสรางของ ByteBuffer ดงภาพท 10.3 ซงมตวแปรทเกยวของ 3 ตวคอ

1. capacity คอคาสงสดของหนวยความจ าทจองไว คา capacity ไมสามารถเปลยนได 2. position ต าแหนงเรมตนทเขยนหรออานขอมลจาก ByteBuffer 3. limit ต าแหนงแรกทไมมการเขยนหรออานขอมล ดงนนต าแหนง limit -1 เปนต าแหนงสนสดการ

เขยนหรออานขอมลจาก ByteBuffer

จากรป 10.3 การอานหรอเขยนขอมลจาก ByteBuffer เรมตนจากต าแหนง position จนไปถงต าแหนงท limit-1 ดงนน หรอเรมตนการเขยนขอมลจากต าแหนงท 0 จนไปถงต าแหนงท 1020 รวมเปนจ านวน 1021 ไบต (limit มคาเทากบจ านวนไบตทสามารถเขยนได)

File(แฟมขอมล) FileChannel

ByteBuffer

FileOutputStream

write()

Page 10: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 173

ภาพท 10.3 แสดงโครงสรางของ ByteBuffer

ผเขยนโปรแกรมสามารถอานหรอเขยนขอมลไปท ByteBuffer ต าแหนงใดกได โดยระบคาของ position ในต าแหนงทตองการ เชน position เทากบ 3 หมายถงเรมขยนขอมลต าแหนงท 3 ส าหรบคา position และ limit สามารถเปลยนแปลงได โดยมกฎวา คา position ตองมคานอยหรอเทากบคา limit และคา limit ตองมคานอยกวาหรอเทากบคา capacity ดงสมการตอไปน

capacitylimitposition0

คลาส ByteBuffer มการ Inherit มาจากคลาส Buffer ดงนนสามารถใช Methods ของคลาส Buffer ไดดวย เชน Method ทใชในการตงคา position และ limit

Buffer position(int newPosition) Buffer limit(int newLimit)

Method ทงสองสงคากลบเปน Buffer ซงท าใหสามารถการเรยกใช Method แบบตอเนองไดในค าสงเดยวกน ดงตวอยางตอไปน ByteBuffer buf = ByteBuffer.allocate(1024);

buf.position(100).limit(512);

การใชค าสง buf.position(100) เปนการตงคาให position มคาเปน 100 และคาทสงกลบเปน Buffer ท าใหสามารถเรยกใช Method limit(512) ตอเนองไดทนท ในกรณทมการตงคาให position มคามากกวาคา limit จะมการสง Exception ทชอ IllegalArgumentException ออกมา ในกรณทตองการทราบคา position, limit และ capacity สามารถเรยกใชงาน Method ตอไปน

int position() int limit() int capacity()

capacity = 1024

position = 0 limit = 1021

Page 11: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

174 การเขยนโปรแกรมภาษา Java

ส าหรบ Method int position() และ int limit() ซงมลกษณะการเขยนคลายกบ Method Buffer postion(newPosition) และ Buffer limit(newLimit) แต Method ทงสามเพยงสงคากลบเปนคาของตวแปร position, limit และ capacity ตามล าดบ ไมไดมการตงคาตวแปรใดๆ ในคลาส ByteBuffer โปรแกรม TestBuffer.java แสดงวธการใช Method postion(), limit() และ capcity() import java.nio.*;

public class TestBuffer {

public static void main(String[] args) {

ByteBuffer buf = ByteBuffer.allocate(1024);

System.out.println("position is " + buf.position() );

System.out.println("limit is " + buf.limit() );

System.out.println("capacity is " + buf.capacity() );

// ตงคา position และ limit buf.position(100).limit(512);

System.out.println("\nAfter call buf.position(100).limit(512);");

System.out.println("position is " + buf.position() );

System.out.println("limit is " + buf.limit() );

System.out.println("capacity is " + buf.capacity() );

}

}

---------- Java Output----------

position is 0

limit is 1024

capacity is 1024

After call buf.position(100).limit(512);

position is 100

limit is 512

capacity is 1024

จากโปรแกรม TestBuffer.java เรมตนเมอสราง ByteBuffer คา position มคาเทากบ 0 และคา limit มคาเทากบ capacity เสมอคอ 1024 ส าหรบ Method ตอไปคอ

Buffer clear()

วตถ ByteBuffer ทใชไปแลวสามารถน ามาใชใหมไดโดยใช Method clear() ซงท าหนาทปรบคาตวแปร position และ limit ใหเปนคาเรมตน หลงจากเรยกใชค าสง clear() ท าใหคา position กลบไปเทากบ 0 และ limit เทากบ capacity นนเอง ไมไดลบขอมลใน ByteBuffer ทงแตอยางไร โปรแกรม TestClearBuffer.java แสดงวธการใชงาน Method clear() import java.nio.*;

public class TestClearBuffer {

public static void main(String[] args) {

ByteBuffer buf = ByteBuffer.allocate(1024);

showAll(buf);

Page 12: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 175

// ตงคา position และ limit buf.position(100).limit(512);

System.out.println("\nAfter call buf.position(100).limit(512);");

showAll(buf);

// ตงคา position และ limit ใหเปนคาเรมตน buf.clear();

System.out.println("\nAfter call buf.clear()");

showAll(buf);

}

public static void showAll(ByteBuffer buf) {

System.out.println("position is " + buf.position() );

System.out.println("limit is " + buf.limit() );

System.out.println("capacity is " + buf.capacity() );

}

}

---------- Java Output----------

position is 0

limit is 1024

capacity is 1024

After call buf.position(100).limit(512);

position is 100

limit is 512

capacity is 1024

After call buf.clear()

position is 0

limit is 1024

capacity is 1024

Buffer flip() Buffer rewind() int remaining()

Method flip() ท าใหคา limit เทากบ position ในปจจบน และ คา position เทากบ 0 โดยทวไปการเขยนขอมลไปท ByteBuffer ใชค าสง put(byte b) เชน buf.put( (byte) 1 ); จะท าใหคา position เพมอกหนงดวย ดงนนเมอมการเขยนขอมลไปท ByteBuffer จะท าใหคา position เปลยนไปเปนจ านวนเทากบจ านวนขอมลทถกเขยนลงไป เมอเตรยมขอมลใน ByteBuffer เรยบรอยแลว และตองการเขยนขอมลทอยใน ByteBuffer ไปทแฟมขอมลโดยผานวตถ FileChannel จ าเปนตองตงคาให limit เทากบ position กอน และ ใหคา position เทากบ 0 เสมอ เพอใหสะดวกในการเขยนค าสง ผเขยนโปรแกรมสามารถใช filp() แทนได ดงภาพท 10.4 Method Buffer rewind() ท าใหคา position เทากบ 0 สวนคา limit จะไมเปลยนแปลง Method นใชในกรณทตองการอานขอมลจาก ByteBuffer หลายครง หรอตองการเขยนขอมลเดมไปทแฟมขอมลหลายแฟมขอมล และไมตองการใช ByteBuffer จ านวนมาก สามารถน า ByteBuffer ทมอยแลวมาใชใหมไดโดยใชค าสง rewind()

Page 13: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

176 การเขยนโปรแกรมภาษา Java

ค าสง remaining() สงคากลบเปน limit() – position() หมายถงจ านวน ByteBuffer ทสามารถอานหรอเขยนไดมจ านวนเทาไร สวน Method ในสวนสดทายคอ

หลงจากเขยนขอมล 100 ไบต คา position จะเทากบ 100

ถาตองการเขยนขอมล 100 ไบตไปทแฟมขอมล จะเปนตองใชค าสง flip() เพอตงคาให limit เทากบ 100 และ position เทากบ 0 กอน หลงจากเรยก Method flip()

ภาพท 10.4 แสดงการท างานของค าสง flip()

ByteBuffer duplicate(); ByteBuffer slice();

ผเขยนโปรแกรมสามารถท าส าเนา ByteBuffer ได 2 วธคอใช 1) Method ByteBuffer duplicate() และ 2) ByteBuffer slice() ซงมความแตกตางคอ การใช duplicate() ไมไดเปนการสราง ByteBuffer ใหม แตเปนการสรางตวแปรใหชไปทหนวยความจ าในต าแหนงเดยวกน โดยม position และ limit แยกกน ดงนนถามการเปลยนแปลงขอมลในหนวยความจ าส าหรบ ByteBuffer เดมจะท าใหสงผลกระทบตอวตถ ByteBuffer ทใชงานอย เพราะใชหนวยความจ าทเดยวกน ดงภาพท 10.5

capacity = 1024

position = 0 limit = 1021

capacity = 1024

position = 100 limit = 1021

capacity = 1024

position = 0 limit = 100

Page 14: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 177

สวนค าสง slice() มการท างานคลายกบค าสง duplicate() ซงเปนการใช ByteBuffer รวมกน แตเปนการสราง ByteBuffer ใหมซงมขนาดเทากบ position จนไปถงต าแหนง limit -1 ของ ByteBuffer เดม ค าสง slice() เปนการสรางทางเดนใหมใหผเขยนโปรแกรมสามารถอางถง ByteBuffer ในมมมองใหม

ByteBuffer buf = ByteBuffer.allocate(10); buf.position(3).limit(7); ByteBuffer newBuf = buf.duplicate();

ByteBuffer newBuf1 = buf.slice();

ภาพท 10.5 แสดงการใช duplicate() และ slice()

การสราง View จาก ByteBuffer บางครงการอานและเขยนขอมล ไมมความจ าเปนตองอยในรปของ Byte เสมอไป ขอมลอาจเปน Integer หรอ Short ได ดงนนเพอชวยอ านวยความสะดวกในการเขยนโปรแกรม ภาษา Java อนญาตใหผเขยนโปรแกรมสามารถสราง View จาก ByteBuffer ไปเปน Buffer ชนดอนได โดยใช Method ตอไปน

capacity=10

position = 3 limit = 7

capacity=10

buf.position = 3 newBuf.position = 3

buf.limit = 7 newBuf.limit = 7

buf

buf

newBuf

capacity=10

position = 3

limit = 7

buf newBuf1

position = 0

limit = 4

slice() ไมไดสราง ByteBuffer ขนใหมแตเปนการใช ByteBuffer บางสวนรวมกน

Page 15: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

178 การเขยนโปรแกรมภาษา Java

CharBuffer asCharBuffer(); ............................ Buffer ชนดตวอกษร DoubleBuffer asDoubleBuffer(); ..................... Buffer ชนด Double FloatBuffer asFloatBuffer(); ........................... Buffer ชนด Float IntBuffer asIntBuffer(); ................................... Buffer ชนด Integer LongBuffer asLongBuffer(); ........................... Buffer ชนด Long ShortBuffer asShortBuffer(); .......................... Buffer ชนด Short

การสราง View ไมไดเปนการสราง Buffer ใหม แตเปนการสรางมมมองขอมลแบบ ByteBuffer ใหเปนขอมลตาม View ทสรางขน การสราง View มประโยชนส าหรบการเขยนขอมลหลายชนดลงไปท ByteBuffer และเขยนขอมลทเปน Array ไปท ByteBuffer ตวอยางการสราง View ทเปน Integer เชน ByteBuffer buf = ByteBuffer.allocate(10);

IntBuffer intBuf = buf.asIntBuffer();

ภาพท 10.6 การสราง View IntBuffer จาก ByteBuffer

จากรป 10.6 คา position, limit และ capacity ของ intBuf ไมตรงกบคาของ buf เพราะ IntBuffer ตองการ 4 ไบตส าหรบขอมล 1 ตว ดงนนจากเดม buf ม capacity เทากบ 10 ซงหารดวย 4 มคาเทากบ 2 ท าใหสามารถเกบขอมลทเปน Integer ไดเพยง 2 คาเทานน การสราง View ใหม มความสมพนธกบคา position และ limit ท ByteBuffer ในปจจบนดวย กลาวคอการสราง Veiw จะเรมจากต าแหนง position จงถง limit-1 จากตวอยางถา position ของ buf มคาเทากบ 5 จะท าใหสราง View IntBuffer ทสามารถบรรจคา Integer ไดเพยงคาเดยวเทานน ผเขยนโปรแกรมสามารถสราง View โดยตรงจาก allocate() เชน LongBuffer longBuf = LongBuffer.allocate(1024);

capacity=10

position = 0

limit = 10 buf

capacity=2

position = 0

limit = 2 intBuf

การสราง View ไมไดสราง Buffer ขนใหมแตเปนการสรางมมมองใหใหกบ ByteBuffer หมายความวาถามการเปลยนขอมลใน View จะท าใหขอมลใน ByteBuffer เปลยนตามดวย

Page 16: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 179

เนองจากการเขยนขอมลโดย FileChannel รบ Parameter ทเปน ByteBuffer เทานน ถามการสราง View โดยตรงแลว การเปลยนขอมลจาก View เปน ByteBuffer เพอใชกบ FileChannel มความซบซอน เพอใหเขยนโปรแกรมงายขน ควรสราง ByteBuffer กอน แลวจงสราง View ทตองการจาก ByteBuffer อกครงหนง การสราง ByteBuffer โดยใชขอมลจาก Array ByteBuffer สามารถสรางจาก Array ไดโดยใชค าสง ByteBuffer wrap(byte[] array) ซงจะเปลยนให Array เปน ByteBuffer แตไมไดสราง ByteBuffer ขนใหม ดงนนถามการแกไขขอมลใน ByteBuffer จะท าใหขอมลใน Array เปลยนตามไปดวย โปรแกรม ArraytoByteBuffer.java แสดงวธการใช Method wrap() import java.nio.*;

public class ArraytoByteBuffer {

public static void main(String[] args) {

String s = "Hello, how are you today?";

// เปลยน String ไปเปน byte[] byte[] b = s.getBytes() ;

// สราง ByteBuffer จาก Array b ByteBuffer buf = ByteBuffer.wrap( b );

// ดงขอมลจาก buf กลบไปเปน Array out byte[] out = buf.array();

System.out.println( new String(out) );

}

}

---------- Java Output----------

Hello, how are you today?

จากโปรแกรม ArraytoByteBuffer.java ค าสง array() มการสงคากลบเปน Array ของ byte และไมสามารถแสดงผลโดยใชค าสง System.out.println() ไดโดยตรง จงใชคลาส String ชวยเปลยนให byte[] เปน String จงสามารถแสดงผลลพธทางจอภาพได การเขยนขอมลไปท ByteBuffer การเขยนขอมลไปท ByteBuffer ม 2 วธ คอ การเขยนขอมลแบบ Relative และ Absolute การเขยนขอมลแบบ Relative จะเรมเขยนตรงกบต าแหนง position และท าใหคา position มการเพมขนเทากบจ านวนขอมลทเขยนไป สวนการเขยนขอมลแบบ Absolute เปนการระบต าแหนงทตองการเขยนโดยไมตองใชคา position ท าใหคา position ไมมการเปลยนแปลง แตไมสามารถระบต าแหนงทตองการเขยนเกนต าแหนง limit-1 ได Method ทใชในการเขยนขอมลไปท ByteBuffer แบบ Relative คอ

ByteBuffer put(byte b); เขยนขอมลไปท ByteBuffer ครงละ 1 ไบต คา position เพมอก 1

Page 17: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

180 การเขยนโปรแกรมภาษา Java

ByteBuffer put(byte[] src); เขยนขอมล Array ของ src ทงหมดไปท ByteBuffer คา position เพมเปนจ านวน src.length

ByteBuffer put(byte[] src, int offset, int length); เขยน Array ของ src โดยเรมท src[offset] จนไปถง src[offset + length -1] และท าใหคา

position เพมขนเทากบ length ดวย ByteBuffer put(ByteBuffer src)

น าขอมลจาก src ซงเปนชนด ByteBuffer โดยเรมตนจากต าแหนง src.position จนไปถง src.limit-1 เขยนไปท ByteBuffer

Method ทใชในการเขยนขอมลไปท ByteBuffer แบบ Absolute มเพยง Method เดยว คอ

ByteBuffer put(int index, byte b) เขยนขอมล b ไปท ByteBuffer ต าแหนง index และคา position ไมเปลยนแปลง การเขยนขอมล

แบบ Absolute สวนใหญใชในการแกไขขอมลใน ByteBuffer ในกรณททราบต าแหนง

การเขยนขอมลชนด Byte ไปทแฟมขอมล การเขยนขอมลชนด Byte ไปทแฟมขอมลสามารถใชคลาส ByteBuffer ไดทนทโดยไมจ าเปนตองสราง View และเมอเสรจการเตรยมขอมลใน ByteBuffer แลว กอนทจะเขยนขอมลลงแฟมขอมล ตองเรยกใชค าสง flip() ดงทกลาวแลวในตอนตนดวย เพอใหต าแหนง position กลบไปท 0 กอน โปรแกรม WriteByteToFile.java แสดงการเขยนขอมลชนด Byte ไปทแฟมขอมลชอ ‚data1.dat‛ import java.io.*;

import java.nio.*;

import java.nio.channels.*;

public class WriteByteToFile {

public static void main(String[] args) {

byte[] b = {0,1,2,3,4,5,6,7,8,9};

// สราง ByteBuffer โดยมขนาดเทากบ b.length ByteBuffer buf = ByteBuffer.allocate(b.length);

// เขยน Array b ไปท ByteBuffer buf.put(b);

// เมอเขยนเสรจแลวตองเรยกค าสง flip() ดวย buf.flip();

// สรางวตถ File File f = new File("data1.dat");

// ตรวจสอบวา data1.dat ไมไดถกสรางกอนหนาน if ( f.exists() ){

Page 18: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 181

System.out.println("Cannot write. data1.dat exists.");

System.exit(1);

}

FileOutputStream fos = null;

try{

// สราง FileOutputStream โดยม Paramter เปน File fos = new FileOutputStream(f);

}

catch (FileNotFoundException e) {

// แสดง Error ถาผดพลาด

e.printStackTrace(System.err); }

// สราง FileChannel เปนทางเชอมตอระหวางแฟมขอมลและ ByteBuffer FileChannel fc = fos.getChannel();

try {

fc.write(buf); // เขยนขอมลไปท ByteBuffer ผานทางวตถ FileChannel fc.close(); // ปดวตถ FileChannel fos.close(); // ปดวตถ FileOutputStream

}

catch (IOException e) {

e.printStackTrace(System.err);

}

System.out.println("data1.dat has been written successfully");

}

}

---------- Java Output----------

data1.dat has been written successfully

การเขยนขอมลชนด Array ไปทแฟมขอมล การเขยนขอมล Array ของ Short, Integer, Long, Float, Double หรอ Character ไปทแฟมขอมล ควรมการสราง View เพอใชเขยนขอมลตามชนดตางๆ ทตองการ เพราะใน View มค าสง put() ทเปลยนขอมลจาก Array ไปเปน Buffer ได เชนคลาส DoubleBuffer มค าสง put(double[] src) หรอ คลาส LongBuffer มค าสง put(long[] src) เชนกน การสราง View สงผลใหตวแปร position และ limit แยกจาก ByteBuffer ดงนนการเขยนขอมลไปท View แบบ Relative จะท าใหคา position ของ View นนเปลยนไป แตคา position ของ ByteBuffer นนคงเดม ดงนนเมอเขยนขอมลไปทแฟมขอมล ตองท าการปรบคา limit ของ ByteBuffer ใหมคาเทากบคา position ของ View x ขนาดของขอมล (เชนถาเปน Long ตองคณดวย 8) และคา position ของ ByteBuffer ใหมคาเปน 0 กอนเขยนขอมลไปทแฟมขอมล ตวอยางตอไปแสดงถงขนตอนการเขยนขอมลชนดอนทไมใช Byte // สราง ByteBuffer ขนาด 800 ByteBuffer buf = ByteBuffer.allocate(800);

Page 19: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

182 การเขยนโปรแกรมภาษา Java

/* สราง View ทเปนชนด Long จาก ByteBuffer ท าให LongBuffer ม position เปน 0 และ limit เทากบ 100 หรอเทากบ capacity เพราะขอมลชนด Long มขนาด 8 ไบต */ LongBuffer longBuf = buf.asLongBuffer();

long[] data = {1L, 2L, 3L, 4L, 5L};

longBuf.put(data);

/* หลงจากค าสง put() ท าใหคา position ของ longBuf เปน 5 และ limit เปน 100 เทาเดม ถาตองการเขยนขอมลไปทแฟมขอมลโดยใช FileChannel ตองปรบคา position ของ buf ใหเทากบ position ของ longBuf กอน แลวจงใช filp() เพอปรบให position ของ buf เปน 0 และ limit ของ buf เทากบ position */ /* คา position ของ longBuf เปลยนไป 1 ท าใหคา position ของ buf เปลยนไป 8 เพราะ Long มขนาด 8 ไบต จงตองคณดวย 8 */ buf.position( longBuf.position() * 8 );

// ปรบคา position และ limit เพอการเขยนไปทแฟมขอมลโดยใช FileChannel buf.flip();

โปรแกรม WriteArrayToFile.java แสดงการเขยนขอมล Array ชนด Long ไปทแฟมขอมลชอ data2.dat import java.io.*;

import java.nio.*;

import java.nio.channels.*;

public class WriteArrayToFile {

public static void main(String[] args) {

long[] data = {0L,1L,2L,3L,4L,5L,6L,7L,8L,9L};

// สราง ByteBuffer ขนาด 800 ไบต ByteBuffer buf = ByteBuffer.allocate(800);

// สราง Long View จาก ByteBuffer LongBuffer longBuf = buf.asLongBuffer();

// เขยนขอมลของ Array long[] ไปท Long View longBuf.put(data);

// ปรบคา buf.position = longBuf.position * 8 buf.position( longBuf.position() * 8 );

// ตงคา limit ใหเทากบ current position และคา position ใหเทากบศนย buf.flip();

File f = new File("data2.dat");

if ( f.exists() ) {

System.out.println("Cannot write. data1.dat exists.");

System.exit(1);

}

FileOutputStream fos = null;

Page 20: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 183

try{

// สราง FileOutputStream fos = new FileOutputStream(f);

}

catch (FileNotFoundException e) {

// ในกรณทมความผดพลาดใหแสดงออกทาง Standard Error e.printStackTrace(System.err); }

FileChannel fc = fos.getChannel(); // สราง FileChannel try {

fc.write(buf); // เขยนขอมลจากวตถ ByteBuffer ไปทแฟมขอมล

fc.close(); // ปดวตถ FileChannel

fos.close(); // ปดวตถ FileInputStream

}

catch (IOException e) {

e.printStackTrace(System.err);

}

System.out.println("data2.dat has been written successfully");

}

}

---------- Java Output----------

data2.dat has been written successfully

การเขยนขอมล String ไปทแฟมขอมล การเขยนขอมลชนด String สามารถเขยนได 2 วธคอ แบบ ASCII และ Unicode การเขยนแบบ ASCII สามารถใชค าสง byte[] getBytes() ในคลาส String เพอเปลยนใหขอมล String เปน ASCII (ตวอยางอยในโปรแกรม ArraytoByteBuffer.java ทผานมา) สวนการเขยนขอมลแบบ Unicode ใชการสราง View ของ Character คลายการสราง View ของ Long โปรแกรม StringToFile1.java และ StringToFile2.java แสดงวธการเขยนขอมล String ไปทแฟมขอมลแบบ ASCII และ Unicode ตามล าดบ // เขยน ASCII ไปท output1.txt import java.io.*;

import java.nio.*;

import java.nio.channels.*;

public class StringToFile1 {

public static void main(String[] args) {

String data = "This data is used for testing. “ +

“The program will write data to output1.txt\n" +

“After writing, you can open output1.txt by text editor";

// สราง ByteBuffer โดยมขนาดเทากบ data.length() ByteBuffer buf = ByteBuffer.allocate( data.length() );

// ใชค าสง getBytes() เพอเปลยน String ใหเปน Array byte[] byte[] raw_data = data.getBytes();

Page 21: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

184 การเขยนโปรแกรมภาษา Java

// ใสขอมลไปท ByteBuffer และเรยก flip() เพอเตรยมเขยนขอมลลงแฟมขอมล

buf.put(raw_data).flip();

File f = new File("output1.txt");

FileOutputStream fos =null;

try{

// สรางวตถ FileOutputStream fos = new FileOutputStream(f);

}

catch (FileNotFoundException e) {

e.printStackTrace(System.err);

}

// สรางวตถ FileChannel FileChannel fc = fos.getChannel();

try {

// เขยนขอมลจาก ByteBuffer ไปทแฟมขอมล fc.write(buf);

fc.close();

fos.close();

}

catch (IOException e) {

e.printStackTrace(System.err);

}

System.out.println("output1.txt has been written successfully");

}

}

---------- Java Output----------

Outpu1.txt has been written successfully

ผลลพธจากโปรแกรม StringToFile2.java คอแฟมขอมลชอ output2.txt โดยมขอมลเปนชนด Unicode ในโปรแกรมนมการแสดงวธการใชค าสง size() ในคลาส FileChannel เพอหาขนาดของแฟมขอมล ซงค าสงนตองอยกอนค าสง close() เสมอ // เขยนตวอกษร Unicode ไปท output2.txt

import java.io.*;

import java.nio.*;

import java.nio.channels.*;

public class StringToFile2 { public static void main(String[] args) {

String data = "This data is used for testing. “ +

“The program will write data to output2.txt\n" +

"After writing, you cannot open output2.txt by text editor";

/* สราง ByteBuffer โดยมขนาดเทากบ data.length() * 2 เนองจาก 1 ตวอกษร Unicode มขนาด 2 ไบต */ ByteBuffer buf = ByteBuffer.allocate( data.length()* 2 );

CharBuffer charBuf = buf.asCharBuffer();

Page 22: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 185

// เขยนขอมลชนด String ไปท ByteBuffer charBuf.put(data);

// ปรบคา position และเรยกค าสง filp() buf.position( charBuf.position() *2 ).flip();

File f = new File("output2.txt");

FileOutputStream fos =null;

try{

// สรางวตถ FileOutputStream fos = new FileOutputStream(f);

}

catch (FileNotFoundException e) {

e.printStackTrace(System.err);

}

// สรางวตถ FileChannel FileChannel fc = fos.getChannel();

long file_size=0;

try {

// เขยนขอมลจาก ByteBuffer ไปทแฟมขอมล

fc.write(buf);

// ค าสง size() ใชหาขนาดของแฟมขอมลทถกเขยน file_size = fc.size();

fc.close();

fos.close();

}

catch (IOException e) {

e.printStackTrace(System.err);

}

System.out.println("output2.txt has been written successfully");

System.out.println("File size is "+ file_size);

}

}

---------- Java Output----------

output2.txt has been written successfully

File size is 282

การเขยนขอมลหลายชนดลงแฟมขอมลเดยวกน การเขยนขอมลหลายชนดไปทแฟมขอมลเดยวกน สามารถท าไดโดยใช Method ในคลาส ByteBuffer ซงขนตนดวย put มทงสน 6 Method คอ

ByteBuffer putChar(char value) ByteBuffer putDouble(double value) ByteBuffer putFloat(float value) ByteBuffer putInt(int value)

Page 23: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

186 การเขยนโปรแกรมภาษา Java

ByteBuffer putLong(long value) ByteBuffer putShort(short value)

ตวอยางเชนการเกบ String ทมความยาวไมเทากนไวในแฟมขอมลเดยวกน โดยใชโครงสรางขอมลซงประกอบดวย ขอมล 4 ไบตแรกเปนจ านวนตวอกษร ตามดวยขอมลตวอกษร และถดไปเปนขอมลชดท 2 ชดท 3 ตอเนองไปจนครบชดท N

โปรแกรม StringToFile3.java แสดงวธการเขยนเขยนบทสนทนาภาษาองกฤษอง A และ B โดยทแตละประโยคมขนาดไมเทากน โดยใชรปแบบการเกบขอมลดงทกลาวไปแลว

import java.io.*;

import java.nio.*;

import java.nio.channels.*;

public class StringToFile3 {

public static void main(String[] args) {

String[] data = { "A: Hello how are you?\n",

"B: I am fine\n",

"B: How about you?\n",

"A: I am ok\n",

"B: See you at java course, bye"};

// หาจ านวนตวอกษรทงหมดในตวแปร data int size = 0;

for(int i=0; i < data.length; i++)

size += data[i].length();

/* สราง ByteBuffer โดยมขนาดเทากบจ านวนบรรทดของบทสนทนา x 4 เนองจากในทก Record ตองเกบจ านวนตวอกษร (Length of String) ใน 1 บรรทดของบทสนทนา เปนตวแปรชนด Integer ซงมขนาดเปน 4 ไบต และบวกดวยจ านวนตวอกษรทงหมด (String data) */ ByteBuffer buf = ByteBuffer.allocate( data.length*4 + size );

// เขยน String ไปท ByteBuffer for(int i=0; i<data.length; i++){

byte[] raw_data = data[i].getBytes();

buf.putInt( data[i].length() );

buf.put(raw_data);

}

Length of String (int) String data (String) Length of String (int) String data (String) ...

ชดท 1 ชดท N

5 abcde 3 abc

ตวอยางการเกบขอมล abcde abc คา data.length มคาเทากบ 2 จ านวนไบตทงหมดทตองจองคอ 2 x 4 + 8 = 16

Page 24: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 187

// ใชค าสง flip() เพอเตรยมเขยนขอมลลงแฟมขอมล buf.flip();

File f = new File("output3.dat");

FileOutputStream fos =null;

try{

fos = new FileOutputStream(f);

}

catch (FileNotFoundException e) {

e.printStackTrace(System.err);

}

FileChannel fc = fos.getChannel();

long filesize = 0;

try {

fc.write(buf);

filesize = fc.size();

fc.close();

fos.close();

}

catch (IOException e) {

e.printStackTrace(System.err);

}

System.out.println("output3.dat has been written successfully");

System.out.println(filesize + " bytes");

}

}

---------- Java Output----------

output3.dat has been written successfully

114 bytes

การอานขอมลจากแฟมขอมลโดยใช Java New I/O การอานขอมลจากแฟมขอมลโดยใช Java New I/O มขนตอนการเขยนโปรแกรมคลายกบการเขยนขอมลไปทแฟมขอมล แตมความแตกตางกนคอ การอานขอมลตองใชคลาส FileInputStream แทน FileOutputStream และเปลยนมาใช Method FileChannel.read() แทน FileChannel.write() เนองจากเปนการอานขอมลจากแฟมขอมล โปรแกรม ReadByteFromFile.java แสดงวธการอานขอมลชนด Byte โดยใชขอมลในแฟมขอมล data1.dat และแสดงผลลพธทางจอภาพ ซงแฟมขอมลนถกสรางขนจากโปรแกรม WriteByteToFile.java // ใชแฟมขอมล data1.dat จากโปรแกรม WriteByteToFile.java import java.io.*;

import java.nio.*;

import java.nio.channels.FileChannel;

public class ReadByteFromFile {

public static void main(String[] args) {

File myFile = new File("data1.dat");

// ประกาศตวแปร FileInputStream FileInputStream fis = null;

Page 25: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

188 การเขยนโปรแกรมภาษา Java

// สรางวตถ FileInputStream try{

fis = new FileInputStream(myFile);

}

catch (FileNotFoundException e) {

System.out.println("File not found");

System.exit(1);

}

// สรางวตถ FileChannel FileChannel inputChannel = fis.getChannel();

ByteBuffer buf = null;

// ใช try และ catch เนองจาก Method size() ใน FileChannel สามารถ throw IOException try {

/* สราง ByteBuffer เพออานขอมลจาก Channel ใช Method size() เพอหาขนาดของแฟมขอมล */ buf = ByteBuffer.allocate( (int) inputChannel.size() );

// อานขอมลจาก data1.dat ไปท ByteBuffer inputChannel.read(buf);

inputChannel.close();

fis.close();

}

catch (IOException e) {

e.printStackTrace(System.err);

System.exit(1);

}

byte[] b = buf.array();

System.out.println("Data from data1.dat are");

// พมพผลลพทธทางจอภาพ for(int i=0; i<b.length; i++) {

System.out.print(b[i] + " ");

}

}

}

---------- Java Output----------

Data from data1.dat are

0 1 2 3 4 5 6 7 8 9 Normal Termination

การอานขอมลชนดอนเชน Long สามารถใชค าสง getLong() ในคลาส ByteBuffer ไดเชนเดยวกน โปรแกรม ReadLongFromFile.java แสดงวธการอานขอมลจากแฟมขอมลชอ data2.dat ทถกสรางจากโปรแกรม WriteArrayToFile.java import java.io.*;

import java.nio.*;

import java.nio.channels.FileChannel;

public class ReadLongFromFile {

public static void main(String[] args) {

Page 26: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 189

File myFile = new File("data2.dat");

FileInputStream fis = null;

try{

fis = new FileInputStream(myFile);

}

catch (FileNotFoundException e) {

System.out.println("File not found");

System.exit(1);

}

// สราง FileChannel

FileChannel inputChannel = fis.getChannel();

ByteBuffer buf = null;

try {

buf = ByteBuffer.allocate( (int) inputChannel.size() );

inputChannel.read(buf);

inputChannel.close();

fis.close();

}

catch (IOException e) {

e.printStackTrace(System.err);

System.exit(1);

}

// ใช flip() เพอเตรยมการอานขอมลจาก Buffer buf.flip();

System.out.println("Data from data2.dat are");

// ใช for Loop พมพผลลพธทางจอภาพ for(int i=0; i < buf.limit()/8; i++) {

// Method getLong() สงคาใน Buffer เปนชนด Long System.out.print( buf.getLong() + " ");

}

}

}

---------- Java ----------

Data from data2.dat are 0 1 2 3 4 5 6 7 8 9

สวนการอาน String จากแฟมขอมล ท าไดโดยใช Method getChar() ของคลาส ByteBuffer โปรแกรม ReadCharFromFile.java แสดงการอานขอมลตวอกษรชนด ASCII จากแฟมขอมล output1.txt จากโปรแกรม StringToFile1.java import java.io.*;

import java.nio.*;

import java.nio.channels.FileChannel;

public class ReadCharFromFile {

public static void main(String[] args) {

File myFile = new File("output1.txt");

FileInputStream fis = null;

try{

fis = new FileInputStream(myFile);

Page 27: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

190 การเขยนโปรแกรมภาษา Java

}

catch (FileNotFoundException e) {

System.out.println("File not found");

System.exit(1);

}

FileChannel inputChannel = fis.getChannel();

ByteBuffer buf = null;

try {

buf = ByteBuffer.allocate( (int) inputChannel.size() );

inputChannel.read(buf);

inputChannel.close();

fis.close();

}

catch (IOException e) {

e.printStackTrace(System.err);

System.exit(1);

}

buf.flip();

System.out.println("Data from output1.txt are");

for(int i=0; i < buf.limit(); i++) {

System.out.print( (char)buf.get() );

}

}

}

---------- Java Output----------

Data from output1.txt are

This data is used for testing. The program will write data to output1.txt

After writing, you can open output1.txt by text editor.

การอานขอมลทมหลายชนดในแฟมขอมลเดยว โดยใชผลลพธจากโปรแกรม WriteStringToFile3.java ทไดสรางแฟมขอมลชอ output3.dat ซงเกบ String ทมขนาดไมเทากนในแฟมขอมล โปรแกรม ReadMultipleStringFromFile.java แสดงการอานขอมลจากแฟมขอมล output3.dat จากโปรแกรม StringToFile3.java import java.io.*;

import java.nio.*;

import java.nio.channels.FileChannel;

public class ReadMultipleStringFromFile {

public static void main(String[] args) {

File myFile = new File("output3.dat");

FileInputStream fis = null;

try{

fis = new FileInputStream(myFile);

}

catch (FileNotFoundException e) {

System.out.println("File not found");

System.exit(1);

}

FileChannel inputChannel = fis.getChannel();

ByteBuffer buf = null;

try {

buf = ByteBuffer.allocate( (int) inputChannel.size() );

inputChannel.read(buf);

Page 28: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 191

inputChannel.close();

fis.close();

}

catch (IOException e) {

e.printStackTrace(System.err);

System.exit(1);

}

buf.flip();

System.out.println("Data from output3.dat are");

while( buf.position() < buf.capacity() ) {

// อานจ านวนตวอกษรจากสวนแรก int count = buf.getInt();

// พมพขอมลในสวนทสองโดยใช count for(int i=0; i<count; i++) { System.out.print( (char)buf.get() );

}

}

}

}

---------- Java Output----------

Data from output3.dat are

A: Hello how are you?

B: I am fine

B: How about you?

A: I am ok

B: See you at java course, bye

การท าส าเนาแฟมขอมล การท าส าเนาขอมลใช Method ทชอ transferTo() ในคลาส FileChannel ซงถกออกแบบใหใชในการท าส าเนาขอมลโดยเฉพาะ

long transferTo(long position, long count, WritableByteChannel target) throws IOException

การเรยกใชค าสงตองระบคาตางๆ คอ คา position เปนตวก าหนดจดเรมตนการอานขอมลจากตนฉบบ (Source) คา count เปนจ านวนขอมลทตองการใหท าส าเนา สวน target เปนแฟมขอมลปลายทางซงเปน FileChannel การใชค าสง transferTo() ไมไดประกนวาขอมลไดท าส าเนาครบ โดยคาทสงกลบจากค าสงนเปนจ านวนไบตทสามารถท าส าเนาได ดงนนผเขยนโปรแกรมจ าเปนตองเรยกใชค าสง transferTo() หลายครงจนมนใจไดวาขอมลไดท าส าเนาครบแลว ซงอาจใชค าสง while Loop ในการเรยกใชงานได ค าสง transferTo() มการ throw คาดงตอไปน

IllegalArgumentException – ถา position หรอ count มคาตดลบ

5 abcde

Page 29: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

192 การเขยนโปรแกรมภาษา Java

NonReadableChannelException – ถา FileChannel ไมสามารถอานได เชนสราง FileChannle จาก FileOutputStream แทนทจะสรางจาก FileInputStream

NonWritableChannelException – ถาไมสามารถเขยน FileChannel ปลายทาง ได ClosedChannelException – ถา FileChannel มการปดไปแลว AsynchronousCloseException – มการปด FileChannel ระหวางการท าส าเนาขอมล ClosedByInterruptException – มการขดจงหวะของ Operating System ท าให FileChannel ปดลง IOException – ถามความผดพลาดอนๆ

ดงนนการเขยนโปรแกรมจ าเปนตองใช try and catch เพราะ Method transferTo() มการ throw IOException โดยตรง สวน Exception อนๆ จะจบหรอไมกได อยางไรกตาม ถาไมจบ Exception เมอเกดความผดพลาดขนจะท าใหโปรแกรมหยดการท างานทนท โปรแกรม CopyFile.java แสดงการใช Method transferTo() ในการท าส าเนาแฟมขอมล โดยผใชงานตองปอนชอแฟมขอมลทตองการท าส าเนาตอนเรมตนโปรแกรมผานทาง Command Line และเมอโปรแกรมท างานเสรจแลว ผลลพธทไดเปนแฟมขอมลทถกท าส าเนา โดยมชอขนตนวา backup และตามดวยชอของแฟมขอมลตนฉบบ import java.io.*;

import java.nio.*;

import java.nio.channels.FileChannel;

public class CopyFile {

public static void main(String[] args) {

// อานชอแฟมขอมลจาก Command Line if(args.length == 0){

System.out.println("Please enter filename

that you want to copy");

System.exit(0);

}

String filename = args[0];

File srcFile = new File(filename);

// ตรวจสอบวามแฟมขอมลตนฉบบจรง if( !srcFile.canRead() ){

System.out.println(filename + " does not exist.");

System.exit(1);

}

FileInputStream inputFile = null ;

FileOutputStream outFile= null ;

try {

// สราง FileInputStream ส าหรบแฟมขอมลตนฉบบ inputFile = new FileInputStream(srcFile);

// สราง FileOutputStream ส าหรบแฟมขอมลปลายทาง outFile = new FileOutputStream("copy of " + srcFile);

Page 30: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 193

}

catch (FileNotFoundException e){

System.out.println("I/O error");

System.exit(1);

}

// สราวตถ FileChannel FileChannel srcChannel = inputFile.getChannel();

FileChannel destChannel = outFile.getChannel();

// เรยกค าสง transferTo() เพอท าส าเนาแฟมขอมล try{

// จ านวนทไบตทท าส าเนาไปแลว

int written = 0;

// ขนาดของแฟมขอมลตนฉบบ long size = srcChannel.size();

// ใช while Loop เพอเขยนขอมล while(written < size) {

written += srcChannel.transferTo(written, size - written, destChannel);

}

// ปดวตถทงหมด srcChannel.close();

destChannel.close();

inputFile.close();

outFile.close();

System.out.println("Copy file complete: backup "+srcFile);

}

catch (IOException e) {

System.out.println("Error while copying the file");

System.exit(1);

}

}

}

---------- Java Output----------

การอานและเขยนในแฟมขอมลเดยวกน การอานและเขยนขอมลในแฟมขอมลเดยวกน สามารถท าไดโดยใชคลาส RandomAccessFile ใน Package java.io แทนการใช FileInputStream และ FileOutputStream โดย Constructor ของ RandomAcessFile คอ

RandomAccessFile(File, file, String mode)

Page 31: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

194 การเขยนโปรแกรมภาษา Java

mode คอ ‚rw‛ ส าหรบการอานและเขยนขอมลในแฟมขอมลเดยวกน ดงตวอยางเชน File myFile = new File(“test.dat”);

RandomAccessFile testFile = new RandomAccessFile(myFile, “rw”);

จากตวอยางเปนการเปดแฟมขอมล test.dat ส าหรบการอานและเขยน ตอไปเปนการสราง FileChannel จาก RandomAccessFile FileChannel ioChannel = testFile.getChannel();

เมอได FileChannel แลวผเขยนโปรแกรมสามารถใชงาน FileChannel นเปนทง Input และ Output Channel สวนวธการเขยนหรออานสามารถใชตวอยางการอานและเขยนขอมลขางตนทกลาวไปแลว โดยสามารถใชการ put() และ get() ใน FileChannel ได

Page 32: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

การเขยนโปรแกรมภาษา Java 195

สรป ในบทนอธบายวธการอานและเขยนขอมลจากแฟมขอมล ผเขยนโปรแกรมภาษา Java สามารถใชคลาสใน java.io ส าหรบการอานหรอเขยนตามลกษณะของขอมลทมความแตกตางกนได ในกรณทแฟมขอมลเปนชนด Binary ตองใชคลาส FileInputStream และ FileOutputStream ส าหรบในกรณทแฟมขอมลเปนชนด Character ตองใชคลาส FileReader และ FileWriter แตคลาสทง 4 เหมาะส าหรบการอานและเขยนขอมลเปนไบต ถาขอมลอยในรปอน เชน Integer หรอ Character ผเขยนโปรแกรมควรใชคลาสลกของคลาสทง 4 แทน ดงตารางท 10.1 ส าหรบ Java เวอรชน 1.4 ขนไป มการออกแบบ Package ใหมชอ java.nio และ java.nio.channels ซงเปนวธการอานและเขยนขอมลโดยใช Buffer ซงมประสทธภาพมากกวาการอานและเขยนขอมลแบบเดม

Page 33: บทที่ 10 การอ่าน และเขียนแฟ้มข้อมูล Read and Write Fileslily.bu.ac.th/~thirapon.w/gim/OOP_files/Chapter10.pdf · การเขียนโปรแกรมภาษา

196 การเขยนโปรแกรมภาษา Java

แบบฝกหดทายบทท 10

1. อธบายการใชคลาสใน java.io ในการขอมลจากแฟมขอมลครงละ 1 บรรทด 2. Package java.nio และ java.nio.channels มหนาทอะไร 3. อธบายคา position, limit และ capacity ในคลาส Buffer 4. อธบายการใชงานค าสง duplicate(), slice(), rewind() และ clear() ของ Buffer 5. การสราง View มวตถประสงคอะไร

Programming Problems 1. จงเขยนโปรแกรมเพอรบขอมลชนด double จ านวน 10 คา จาก Keyboard และเขยนลงแฟมขอมลชอ

‚output.dat‛ ใหแสดงการเขยนขอมลโดยใชคลาสใน Package javo.io ปกตและแสดงการเขยนโปรแกรมโดยใช Java New I/O ดวย

2. จงเขยนโปรแกรมเพออานขอมลตวเลขชนด double จากแฟมขอมล ‚output.dat‛ จากขอ 1 และเรยกขอมลจากนอยไปหามาก โดยเกบผลลพธทแฟมขอมลเปน Text File ชอ ‚sorted.txt‛ใหแสดงการอานขอมลโดยใชคลาสใน Package javo.io ปกตและแสดงการเขยนโปรแกรมโดยใช Java New I/O ดวย

3. น าผลลพธจากขอท 1 ‚output.dat‛ ท าส าเนาเปน ‚output.dat.bak‛ โดยใช Method transferTo() ดงตวอยางในหนงสอ

4. จงเขยนโปรแกรมท าส าเนาแฟมขอมลโดยรบชอแฟมขอมลตนฉบบ และแฟมขอมลปลายทางผานทาง Command Line ตวอยางการท าส าเนาแฟมขอมลจาก inputfile.txt ไปยง outputfile.txt ดงน

$java CopyFile inputfile.txt outputfile.txt