การเขียนข้อมูลลงไฟล์
การเปิดไฟล์สำหรับเขียน
การเขียนไฟล์นั้นก็เช่นเดียวกับการอ่านไฟล์ คือจะต้องเปิดไฟล์ขึ้นมาเสียก่อน เพียงแต่ต้องกำหนดโหมดการใช้งานเป็น w หรือ a แทนที่จะเป็น r แบบตอนอ่าน ที่อาจจะฟังดูแปลกหน่อย ก็คือแม้ว่าไฟล์ที่จะเขียนนั้นยังไม่ได้มีตัวตนอยู่ ก็ตาม แต่ก็ยังต้องใช้คำสั่ง open เพื่อเปิดอะไรที่ว่างเปล่านั้นขึ้น ซึ่งการเปิดในที่นี้นั้นเท่ากับเป็นการสร้างไฟล์ขึ้นมา หาก open ไฟล์ในโหมด w จะพบว่าไฟล์นั้นถูกสร้างขึ้นมาทันทีหากมันไม่ได้มีตัวตนอยู่แต่แรก
f = open('xxxx.txt','w',encoding='utf-8')
f.close()
ลองไปดูจะพบว่ามีไฟล์ชื่อ xxxx.txt โผล่มาในโฟลเดอร์เดียวกับไฟล์โปรแกรม และภายในว่างเปล่าไม่มีอะไร โหมด w กับ a นั้นจะต่างกันตรงที่ว่าในกรณีที่ไฟล์เดิมมีตัวตนอยู่แล้วถ้าเป็นโหมด w ไฟล์จะถูกเขียนทับใหม่ทันที แต่ถ้าเป็น a จะเป็นการเขียนต่อจากไฟล์เดิม การเขียนไฟล์ก็ต้องเลือกรูปแบบการเอนโค้ดเช่นกัน ในที่นี้ใช้เป็น utf-8 เช่นเคย
คำสั่งเขียนไฟล์
มี ๒ เมธอดที่ใช้ในการเขียนไฟล์ คือ write กับ writelines ข้อแตกต่างคือ write จะใช้กับสายอักขระอันเดียว แต่ writelines จะใช้กับลิสต์ของสายอักขระ กรณีที่ใช้กับสายอักขระเดียวยาวต่อเนื่อง จะใช้ write หรือ writelines ก็ได้เหมือนกันทั้งคู่
s = '''เวลาที่เข้าหาผู้อื่น ให้มีหัวใจที่อบอุ่นดั่งฤดูใบไม้ผลิ
เวลาที่ทำงาน ให้มีหัวใจที่เร่าร้อนดั่งฤดูร้อน
เวลาที่คิดอะไร ให้มีหัวใจที่แจ่มใสดั่งฤดูใบไม้ร่วง
เวลาที่เผชิญหน้ากับตัวเอง ให้มีหัวใจที่เข้มงวดดั่งฤดูหนาว'''
f = open('samejima.txt','w',encoding='utf-8')
f.write(s)
#หรือ f.writelines(s)
f.close()
แต่ถ้ามีสายอักขระหลายๆอันแยกกันอยู่จะใช้ได้แต่ writelines เช่น
s = ['เวลาที่เข้าหาผู้อื่น ให้มีหัวใจที่อบอุ่นดั่งฤดูใบไม้ผลิ', 'เวลาที่ทำงาน ให้มีหัวใจที่เร่าร้อนดั่งฤดูร้อน', 'เวลาที่คิดอะไร ให้มีหัวใจที่แจ่มใสดั่งฤดูใบไม้ร่วง', 'เวลาที่เผชิญหน้ากับตัวเอง ให้มีหัวใจที่เข้มงวดดั่งฤดูหนาว']
f = open('samejima.txt','w',encoding='utf-8')
f.writelines(s)
f.close()
เพียงแต่ว่าจะไม่มีการเว้นบรรทัดให้ระหว่างสายอักขระแต่ละท่อน ถ้าต้องการก็ต้องเพิ่มเอาเอง ถ้าจะใช้ write ก็อาจใช้เป็น f.write('\n’.join(s)) คือใช้เมธอด join เพื่อรวมสายอักขระเข้าด้วยกันโดยมีการขึ้นบรรทัดใหม่เป็นตัวแบ่ง หรืออาจจะเขียนต่อๆกันไปเลยก็ได้ การใช้คำสั่ง write หลายครั้งจะเป็นการเขียนต่อไปเรื่อยๆ โดยจะไม่มีการขึ้นบรรทัดใหม่ให้ดังนั้นต้องเติม ‘\n’ ไปด้วย
for a in s:
f.write(a+'\n')
สิ่งที่จะเขียนได้นั้นต้องเป็นสายอักขระเท่านั้น หากไม่ใช่สายอักขระก็ต้องแปลงก่อน
ตัวอย่าง โปรแกรมเขียนเลข 1 ถึง 10000 ลงไฟล์
f = open('10000.txt','w',encoding='utf-8')
for i in range(1,10001):
f.write('|%d|'%i)
if(i%100==0): f.write('\n') # ขึ้นบรรทัดใหม่ถ้านับถึง 100
f.close()
แค่พิมพ์โค้ดสั้นๆแค่นี้ก็มีเลขโผล่ขึ้นมาถึงหมื่นภายในพริบตา ขนาดไฟล์หลายสิบกิโลไบต์ ลองคิดดูว่าถ้าเปลี่ยนจากหมื่นเป็นพันล้านจะเป็นอย่างไร เท่านี้ก็สามารถไปประยุกต์สร้างไวรัสอย่างง่ายๆได้แล้ว ลองเขียนโปรแกรมทำนองนี้แล้วส่งให้ไปรันในเครื่องคนอื่นก็จะเกิดไฟล์ขนาดใหญ่ขึ้นอย่างรวดเร็ว แค่คิดก็น่ากลัวแล้ว ตัวอย่างทั้งหมดนี้ใช้โหมด r คือพอเปิดไฟล์มาก็จะถูกลบทิ้งแล้วเริ่มเขียนใหม่ทันที ถ้าอยากให้ไฟล์เขียนต่อก็แค่เปลี่ยน r เป็น a เท่านั้น ลองทำดูกันได้
การคัดลอกไฟล์
เมื่อสามารถเปิดอ่านและสามารถเขียนไฟล์ได้แล้ว ต่อไปสิ่งที่จะทำได้ตามมาอย่างไม่ยากก็คือการนำข้อมูลจากไฟล์หนึ่งคัดลอกไปลงในอีกไฟล์ ซึ่งก็คือการอ่านไฟล์หนึ่ง ดึงข้อมูลมา แล้วก็นำไปเขียนในอีกไฟล์ ลองดูตัวอย่าง
f1 = open('nishikaze.txt','r',encoding='utf-8') # เปิดไฟล์ต้นฉบับ
f2 = open('nishikaze2.txt','w',encoding='utf-8') # กำหนดไฟล์ใหม่ที่จะเขียน
a = f1.read() # นำข้อมูลจากไฟล์ต้นฉบับมาเก็บในตัวแปร
f2.write(a) # นำข้อมูลจากตัวแปรมาเขียนลงในไฟล์ใหม่
f1.close() # ปิดไฟล์ต้นฉบับ
f2.close() # ปิดไฟล์ที่เขียนเสร็จ
เท่านี้ก็จะได้ไฟล์ใหมที่เหมือนกับไฟล์ต้นฉบับทุกประการ แต่ความจริงแล้วนอกจากนี้ยังมีอีกวิธีที่ง่ายกว่านั้น นั่นคือใช้ฟังก์ชัน copyfile ในมอดูล shutil
import shutil
shutil.copyfile('nishikaze.txt', 'nishikaze2.txt')
นอกจากนี้ยังมีฟังก์ชัน move เอาไว้ย้ายไฟล์
import shutil
shutil.move('nishikaze2.txt', 'nishikaze3.txt')
เท่านี้ข้อมูลจากไฟล์เดิมก็ย้ายไปอยู่ในไฟล์ชื่อใหม่ แค่การคัดลอกมาทั้งหมดอาจดูง่ายไปไม่ค่อยมีอะไร เราลองมาทำอะไรที่ต้องออกแรงมากกว่านั้นสักหน่อย ต่อไปเป็นการนำข้อความจากไฟล์ต้นฉบับมาแตกออกเป็นไฟล์ย่อยแบ่งทีละบรรทัด
f = open('nishikaze.txt','r',encoding='utf-8') # เปิดไฟล์ต้นฉบับ
i = 1
for r in f: # วนซ้ำเพื่อแยกวิเคราะห์ทีละบรรทัด
if(r=='\n'): continue # หากบรรทัดไหนว่างเปล่าก็ข้ามไปเลย ไม่ต้องสร้างไฟล์ บรรทัดที่ว่างคือบรรทัดที่มีแต่ \n คือคำสั่งขึ้นบรรทัดใหม่
fw = open('n%02d.txt'%i,'w',encoding='utf-8') # สร้างไฟล์ใหม่ ตั้งชื่อเป็น n ตามด้วยหมายเลข
fw.writelines(r) # เขียนข้อมูลที่อ่านได้ในบรรทัดนั้นลงไฟล์
fw.close() # ปิดไฟล์ที่เขียน
i += 1
f.close() # ปิดไฟล์ต้นฉบับ
การจัดเก็บข้อมูลเพื่อใช้งาน
โดยทั่วไปแล้วข้อมูลมักจะถูกจัดเก็บเป็นแถวๆอย่างเป็นระเบียบเพื่อให้อ่านง่ายและสะดวกต่อการใช้งาน เราอาจเก็บข้อมูลในลักษณะคล้ายตารางโดยแยกเป็นแถวและมีการเว้นวรรคระหว่างข้อมูลแต่ละตัว ยกตัวอย่าง เช่นสร้างระบบบันทึกคะแนนสอบโดยให้นักเรียนแต่ละคนป้อนคะแนนสอบแต่ละวิชาแล้วข้อมูลก็ถูกบันทึกลงไปเรื่อยๆ
rahat = input('ป้อนรหัสผู้สอบ: ')
physics = input('คะแนนฟิสิกส์: ')
chemi = input('คะแนนเคมี: ')
chiwa = input('คะแนนชีวะ: ')
f = open('khanaen.txt','a',encoding='utf-8')
f.write('%s %s %s %s\n'%(rahat,physics,chemi,chiwa))
f.close()
แบบนี้พอรันโปรแกรมแต่ละครั้งก็จะมีข้อความขึ้นมาให้กรอกรหัส แตามด้วยคะแนนแต่ละวิชา เมื่อกรอกครบคะแนนก็จะถูกบันทึกลงไฟล์ สมมุติว่ามีนักศึกษามาบันทึกคะแนนแล้วทั้งหมด ๓ คน ไฟล์ก็จะออกมาในลักษณะนี้
590001 90 76 84
590003 99 90 88
590007 80 92 100
ข้อมูลแบบนี้นำมาใช้งานได้ง่าย หากต้องการดึงข้อมูลคะแนนทั้งหมดมาวิเคราะห์ก็เปิดไฟล์ขึ้นมาอ่านแล้ว read แล้ว split แยกเอาแต่ละส่วน เช่นเอาข้อมูลที่ได้นี้มาหาค่าต่ำสุด สูงสุด และค่าเฉลี่ย
f = open('khanaen.txt','r',encoding='utf-8')
physics = []
chemi = []
chiwa = []
for s in f:
a = s.split()
physics += [int(a[1])]
chemi += [int(a[2])]
chiwa += [int(a[3])]
f.close()
print('คะแนนฟิสิกส์ ต่ำสุด=%d, สูงสุด=%d, เฉลี่ย=%.2f'%(min(physics),max(physics),sum(physics)/len(physics)))
print('คะแนนเคมี ต่ำสุด=%d, สูงสุด=%d, เฉลี่ย=%.2f'%(min(chemi),max(chemi),sum(chemi)/len(chemi)))
print('คะแนนชีววิทยา ต่ำสุด=%d, สูงสุด=%d, เฉลี่ย=%.2f'%(min(chiwa),max(chiwa),sum(chiwa)/len(chiwa)))
บางครั้งตัวกั้นข้อมูลก็อาจใช้แท็บ \t หรือในกรณีไฟล์ชนิด .csv จะกั้นด้วยจุลภาค , จะใช้เป็นอะไรก็ได้ แต่เวลาเปิดอ่านข้อมูลก็ต้องรู้และระบุตัวแยกให้ถูกต้อง
สรุปเนื้อหา
- การเขียนไฟล์ก็คล้ายกับการอ่านไฟล์ ต้องเปิดไฟล์ขึ้นมาก่อน โดยต้องเลือกโหมดเป็น w หรือ a
- w กับ a ต่างกันตรงที่ w เป็นการเขียนทับ ส่วน a เป็นการเขียนต่อ
- เมธอดที่ใช้เขียนคือ write และ writelines
- write ใช้กับสายอักขระ ส่วน writelines ใช้กับลิสต์ของสายอักขระ
- การคัดลอกไฟล์ทำได้โดยเปิดไฟล์ขึ้นมาอ่านแล้วเขียนใส่อีกไฟล์ หรือใช้ shutil.copyfile ก็ได้
- สามารถใช้การอ่านและเขียนไฟล์เพื่อจัดการกับข้อมูลอย่างเป็นระบบได้
อ้างอิง
http://docs.python.jp/3/library/functions.html
http://diveintopython3-ja.rdy.jp/files.html
http://www.ops.dti.ne.jp/ironpython.beginner/textfile.html
http://www.yukun.info/blog/2008/09/python-file-write-writelines.html
Reference : https://phyblas.hinaboshi.com/tsuchinoko18