φυβλαςのβλογ
บล็อกของ phyblas



ภาษา python เบื้องต้น บทที่ ๑๘: การเขียนข้อมูลลงไฟล์
เขียนเมื่อ 2016/03/05 23:10
แก้ไขล่าสุด 2024/02/22 11:04
 

ในบทที่แล้วได้พูดถึงการเปิดไฟล์เพื่ออ่านไปแล้ว

เมื่อสามารถเปิดอ่านไฟล์ได้แล้ว ต่อไปสิ่งที่จำเป็นไม่แพ้กันก็คือการเขียนไฟล์ขึ้นมาใหม่



การเปิดไฟล์สำหรับเขียน

การเขียนไฟล์นั้นก็เช่นเดียวกับการอ่านไฟล์ คือจะต้องเปิดไฟล์ขึ้นมาเสียก่อน เพียงแต่ต้องกำหนดโหมดการใช้งานเป็น 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://www.ops.dti.ne.jp/ironpython.beginner/textfile.html
http://www.yukun.info/blog/2008/09/python-file-write-writelines.html




-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

บทความแต่ละเดือน

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2020年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文