Tutorial

C Language 101 - File I/O (EP.10)

By Arnon Puitrakul - 15 มิถุนายน 2015

C Language 101 - File I/O (EP.10)

ในที่สุดเราก็มาถึงเรื่องเกือบสุดท้ายกันแล้ว นั่นคือ File I/O หรือ การอ่านเขียนไฟล์นั่นเอง !!
คำเตือน ในเรื่องนี้ จะมีเรื่อง Pointer และ Structure เข้ามาเกี่ยวข้องฉะนั้น ถ้ายังไม่เข้าใจเรื่อง Pointer และ Structure ให้ย้อนกลับไปอ่านเรื่อง Pointer และ Structure ให้เข้าใจซะก่อน แล้วค่อยมาอ่านเรื่องนี้

การเปิดและปิดไฟล์

ในการอ่านเขียนไฟล์ในภาษา C เราจะต้องเรียกผ่าน Structure ที่ชื่อ FILE เท่านั้น (ตัวใหญ่หมดจริง ๆ นะ) ซึ่งเราก็ต้องประกาศเป็น Pointer ด้วย

FILE *a;

สังเกตได้ว่ามันจะมี parameter 2 ตัว ตัวแรกคือที่อยู่ไฟล์ แต่ในกรณีนี้คือไฟล์ที่ต้องการเปิดอยู่ที่เดียวกับที่ที่เราเรียกโปรแกรมเลยเขียนแค่ชื่อกับสกุลไฟล์
ส่วนอีกอันคือ mode ของการเปิด ซึ่ง mode ของการเปิดนั้นจะมีหลาย mode แต่ mode ที่แนะนำคือ r+ เพราะเปิดทีเดียวจะเขียนก็ได้จะอ่านก็ได้ หลักๆก็จะมี

  • r - Read อ่านอย่างเดียว
  • w - write เขียนอย่างเดียว
  • r+ - เขียนด้วยอ่านด้วย

ซึ่งในโลกความเป็นจริงๆมันจะมีบางครั้งที่ไฟล์เปิดไม่ได้ด้วยสาเหตุใดก็ตาม เราจะต้องมีวิธีรับมือกับมัน ซึ่ง fopen ถ้ามันเปิดไฟล์ไม่ได้มันจะ return ค่ากลับมาเป็น NULL
เพราะฉะนั้นวิธีเช็คคือใช้ if ในการเช็ค เช่น

if((a=fopen(“hello.txt”,”r”)) == NULL) printf(“Can’t Open File”);

จากโค๊ตด้านบนเราพยายามที่จะเปิดไฟล์ขื่อ hello แต่เราเอา if มาค่อมเพื่อเช็คว่า ตอนเปิดไฟล์ออกมา คำสั่ง fopen มัน return ค่า NULL มารึเปล่า ถ้าไม่คือไฟล์เปิดได้ แต่ถ้ามันได้ค่า NULL ออกมานั้นคือ ไฟล์นั้นเปิดไม่ได้ด้วยเหตุผลอะไรสักอย่าง อาจเพราะว่าหาไฟล์ไม่เจอ หรือติดเรื่อง permission ประการใด
แต่ ๆ ๆ มีเปิดไฟล์ ก็ต้องมีปิดไฟล์ ในการปิดไฟล์เราจะใช้คำสั่ง fclose(); ในการปิด

fclose(a);

การอ่านเขียนไฟล์

หลังจากที่เราเปิดปิดไฟล์ได้แล้ว เราจะมาอ่านไฟล์กัน
การอ่านไฟล์ทำได้เหมือนกันกับการรับข้อมูลเข้าทางหน้าจอปกติเลย เช่น
scanf ที่เราคุ้นเคยกัน เราก็แค่เปลี่ยนเป็น fscanf แต่มันจะต่างกันนิดหน่อย
fscanf(filepointer,"",destination); เช่น

fscanf(a,”%d %d %s %s”,&id,&year,name,surname);

เช่นเดียวกับ การเขียนไฟล์ ก็เหมือนกับ printf ที่เคยใช้ แต่เปลี่ยนเป็น fprintf แทน
fprintf(filepointer,"",destination); เช่น

 fprintf(a,”%d %d %s %s\n”,id,year,name,surname);

แต่คุณเคยประสบปัญหาแบบนี้มั้ย ?

สมมุติว่า ในไฟล์เรามีคำว่า Hello World แล้วเราอ่านไฟล์ไปแล้ว cursor มันไปอยู่ที่ W แล้วเราต้องการที่จะเขียนคำว่า Hi ต่อ แต่ถ้าเราใช้วิธีการเขียนไฟล์แบบเมื่อกี้ที่เรารู้มา มันก็จะออกมาเป็น Hello WHiorld เลยทันที เพราะฉะนั้นเราจึงมีวิธีการเขียนไฟล์อีกแบบนึง เราเรียกมันว่า Randomly Accessed File
แต่ในการที่จะใช้วิธีนี้ ตอนเราเปิดไฟล์เราจะต้องเติม b ไปในโหมดการเปิดด้วยเช่น rb,wb,rb+ เป็นต้น และอีกอย่างส่วนใหญ่เราจะใช้ structure มารองรับเพื่อความง่าย
ในการอ่านไฟล์แบบ Randomly Accessed File เราจะต้องใช้อีกคำสั่งนึงนั่นคือ fread();

fread(Structure_Name,Number of Read,1,fileptr);

อย่างที่บอกว่า ในการอ่านเขียนแบบนี้ เราจะใช้ Structure เข้ามาช่วย เพราะฉะนั้นใน fread() อันแรกมันเลยต้องการ Structure ที่จะเอาข้อมูลที่อ่านลงมาเก็บ และถัดไปเป็น จำนวนครั้งที่ต้องการอ่านเข้ามา และสุดท้ายคือ FILE Pointer ที่เราได้ประกาศไว้
ส่วนการเขียวไฟล์ ก็เหมือนกับอ่านไฟล์เลย แต่เปลี่ยนชื่อคำสั่งจาก fread(); เป็น fwrite() แทน และ Parameter เหมือนกันเลย เราลองมาดูตัวอย่างกันเลย

struct student
{
    int id;
    char name[20];
    char surname[20];
};

student ict[20];
fread (ict,sizeof(student),20,file_ptr); //1. read file
fwrite(ict,sizeof(student),20,file_ptr); //2. write file

ก่อนอื่นเลย เราก็สร้างพิมพ์เขียวของ Structure Student ขึ้นมา และเราก็เอาพิมพ์เขียวมันมาสร้างเป็น Array ของ Structure ชื่อ ict
ถัดมา เราก็มาอ่านไฟล์โดยใช้คำสั่ง fread เราจะอ่านลงไปใน Structure ชื่อ ict จำนวน เป็นขนาดของ Array ของ Structure หรือ พูดอีกแบบนึงคือ อ่านจนครบ 20 เต็ม Array นั่นเอง ผ่าน FILE pointer ที่ชื่อว่า file_ptr
และสุดท้าย เราก็มาเขียนไฟล์ ก็เหมือนกับอ่านไฟล์เลย เราจะอ่านไฟล์จาก Structure ชื่อ ict จำนวน 20 ครั้งลงไปในไฟล์ผ่าน FILE Pointer ชื่อ file_ptr

แล้วเราจะเลือกวิธีไหนดีล่ะ ?

วิธีแรกจะเหมาะกับการอ่านเขียนไฟล์แบบ ธรรมดาเลย คือ ไม่มีข้อมูลอะไรเยอะ อาจจะแค่อยากจะเขียนคำลงไปอะไรแบบนี้ แต่อีกแบบนึง Randomly Accessed File เราจำเป็นต้องใช้ Structure ซึ่งมันเหมาะกับการอ่านเขียนไฟล์ที่เป็นลำดับ ๆ เหมือนในตัวอย่างที่เป็นทะเบียนนักศึกษาเลย ซึ่งนั่นก็แล้วแต่ แล้วล่ะ ว่าเวลาเราเจอปัญหาจริง ๆ เราจะเลือกใช้แบบไหน
สรุปสุดท้ายแล้ว ไม่รู้จะสรุปอะไรดี เอาเป็นว่า การอ่านเขียนไฟล์จะมี 2 แบบล่ะกัน แบบแรกจะเป็นการอ่านและเขียนแบบเรียงไปเรื่อย เหมือนกับเราพิมพ์งานที่จะมี Cursor วิ่งไปเรื่อย ๆ เมื่อเราอ่านหรือเขียนมัน ถ้าเราเขียนมันก็จะเขียนลงไปที่ตำแหน่งของ Cursor ที่มันวิ่งอยู่ คำสั่งที่ใช้จะเหมือนกับเรารับค่า ส่งค่าที่หน้าจอเลย แค่เราเติมตัว f เข้าไป ส่วนอีกแบบ หรือเรียกว่า Randomly Accessed File จะเป็นการอ่านเขียนไฟล์แบบ Random เลยแต่เวลาเราอ่านหรือเขียนเราจะต้องใช้ Structure เข้ามาช่วย มันจะเหมาะกับการอ่านเขียนข้อมูลที่ทำออกมาในรูปของลำดับ ๆ มากกว่า คำสั่งที่ใช้คือ fread(); เพื่ออ่านไฟล์ และ fwrite เพื่อเขียนไฟล์

Read Next...

จัดการข้อมูลบน Pandas ยังไงให้เร็ว 1000x ด้วย Vectorisation

จัดการข้อมูลบน Pandas ยังไงให้เร็ว 1000x ด้วย Vectorisation

เวลาเราทำงานกับข้อมูลอย่าง Pandas DataFrame หนึ่งในงานที่เราเขียนลงไปให้มันทำคือ การ Apply Function เข้าไป ถ้าข้อมูลมีขนาดเล็ก มันไม่มีปัญหาเท่าไหร่ แต่ถ้าข้อมูลของเราใหญ่ มันอีกเรื่องเลย ถ้าเราจะเขียนให้เร็วที่สุด เราจะทำได้โดยวิธีใดบ้าง วันนี้เรามาดูกัน...

ปั่นความเร็ว Python Script เกือบ 700 เท่าด้วย JIT บน Numba

ปั่นความเร็ว Python Script เกือบ 700 เท่าด้วย JIT บน Numba

Python เป็นภาษาที่เราใช้งานกันเยอะมาก ๆ เพราะความยืดหยุ่นของมัน แต่ปัญหาของมันก็เกิดจากข้อดีของมันนี่แหละ ทำให้เมื่อเราต้องการ Performance แต่ถ้าเราจะบอกว่า เราสามารถทำได้ดีทั้งคู่เลยละ จะเป็นยังไง เราขอแนะนำ Numba ที่ใช้งาน JIT บอกเลยว่า เร็วขึ้นแบบ 700 เท่าตอนที่ทดลองกันเลย...

Humanise the Number in Python with "Humanize"

Humanise the Number in Python with "Humanize"

หลายวันก่อน เราทำงานแล้วเราต้องการทำงานกับตัวเลขเพื่อให้มันอ่านได้ง่ายขึ้น จะมานั่งเขียนเองก็เสียเวลา เลยไปนั่งหา Library มาใช้ จนไปเจอ Humanize วันนี้เลยจะเอามาเล่าให้อ่านกันว่า มันทำอะไรได้ แล้วมันล่นเวลาการทำงานของเราได้ยังไง...

ทำไม 0.3 + 0.6 ถึงได้ 0.8999999 กับปัญหา Floating Point Approximation

ทำไม 0.3 + 0.6 ถึงได้ 0.8999999 กับปัญหา Floating Point Approximation

การทำงานกับตัวเลขทศนิยมบนคอมพิวเตอร์มันมีความลับซ่อนอยู่ เราอาจจะเคยเจอเคสที่ เอา 0.3 + 0.6 แล้วมันได้ 0.899 ซ้ำไปเรื่อย ๆ ไม่ได้ 0.9 เพราะคอมพิวเตอร์ไม่ได้มองระบบทศนิยมเหมือนกับคนนั่นเอง บางตัวมันไม่สามารถเก็บได้ เลยจำเป็นจะต้องประมาณเอา เราเลยเรียกว่า Floating Point Approximation...