บทความก่อนหน้า
การจัดการไฟล์
กลับมาแล้วครับหายไปนานเลยตอนนี้พอว่างแล้วกลับมาทำบทความต่อแล้วครับ
แบบใช้ฟังก์ชันในมอดูล IO
Lua มีการจัดการเขียนอ่านไฟล์สองแบบอย่างแรกคือการใช้ฟังก์ชันในมอดูล io ตามที่เคยกล่าวถึงในตอนที่ 5 แล้วซึ่งมีรายละเอียดดังนี้
io.open()
เป็นฟังก์ชันเปิดไฟล์เพื่ออ่านเขียนข้อมูลโดยมีโหมดต่างๆ ดังนี้
r เปิดไฟล์ที่มีอยู่เพื่ออ่านอย่างเดียว
w เปิดไฟล์เพื่อเขียนทับข้อมูลเดิมหรือสร้างไฟล์ใหม่ถ้าไม่มีไฟล์นั้นอยู่
a เปิดไฟล์เพื่อเขียนข้อมูลต่อท้ายข้อมูลเดิมหรือสร้างไฟล์ใหม่ถ้าไม่มีไฟล์นั้นอยู่
r+ เปิดไฟล์ที่มีอยู่เพื่ออ่านและเขียน
w+ เปิดไฟล์เพื่ออ่านและเขียนโดยจะลบข้อมูลเก่าหรือสร้างไฟล์ใหม่
a+ เปิดไฟล์เพื่ออ่านและเขียนต่อท้ายข้อมูลเดิมหรือสร้างไฟล์ใหม่
rb เหมือน r แต่เป็น binary mode ไม่ใช่ text mode
wb เหมือน w แต่เป็น binary mode ไม่ใช่ text mode
ab เหมือน a แต่เป็น binary mode ไม่ใช่ text mode
r+b เหมือน r+ แต่เป็น binary mode ไม่ใช่ text mode
w+b เหมือน w+ แต่เป็น binary mode ไม่ใช่ text mode
a+b เหมือน a+ แต่เป็น binary mode ไม่ใช่ text mode
ตัวอย่าง
local f = io.open("test.txt","r") -- เปิดไฟล์ test.txt เก็บไว้ที่ตัวแปร f เพื่ออ่านข้อมูล
io.input(f) -- กำหนดให้ input ชี้ไปที่ f ( test.txt )
print(io.read()) -- อ่านข้อมูลบรรทัดแรก
print(io.read()) -- อ่านข้อมูลบรรทัดถัดไป
io.close(f) -- ปิดไฟล์
f = io.open("test.txt","a") -- เปิดไฟล์ test.txt เก็บไว้ที่ตัวแปร f เพื่อเขียนข้อมูลต่อท้าย
io.output(f) -- กำหนดให้ output ชี้ไปที่ f
io.write("\nNew line") -- เขียนข้อความ "New line" ต่อท้ายบรรทัดใหม่ใน f
io.write("Same line") -- เขียนข้อความ "Same line" ต่อท้ายบรรทัดเดิมใน f
io.close(f) -- บันทึกข้อมูลใน f แล้วปิดไฟล์ ( ข้อความบรรทัดสุดท้ายไฟล์ test.txt --> "New lineSame line" )
io.input(io.stdin) -- ให้ input กลับมารับค่าจากคีย์บอร์ด
io.output(io.stdout) -- ให้ output กลับไปชี้ที่จอ
io.read()
มีรูปแบบการรับข้อมูลดังนี้
n รับข้อมูลตัวเลขที่ตำแหน่งปัจจุบันแล้วแปลงเป็นข้อมูลชนิด number ถ้าไม่ใช่ตัวเลขจะได้ค่าเป็น nil
( รุ่น 5.1, 5.2 ใช้ *n หรือ *number )
a รับข้อมูลทั้งไฟล์ถ้าตำแหน่งที่รับข้อมูลเป็นตัวจบไฟล์ ( EOF ) จะคืนค่าว่าง ( "" )
( รุ่น 5.1, 5.2 ใช้ *a หรือ *all )
l รับข้อมูลที่ตำแหน่งปัจจุบันจนจบบรรทัดไม่รวมตัวจบบรรทัด ( EOL ) แล้วย้ายไปตำแหน่งบรรทัดถัดไป
ถ้าตำแหน่งที่รับค่าเป็นตัวจบไฟล์ ( EOF ) จะคืนค่า nil ( รุ่น 5.1, 5.2 ใช้ *l หรือ *line )
L เหมือน l แต่จะรวม EOL ด้วย ( รุ่น 5.2 ใช้ *L )
ตัวเลข รับค่าข้อมูลตาจำนวน bytes ที่กำหนด
ถ้าไม่กำหนดรูปแบบจะใช้ l เป็นค่าตั้งต้น
ตัวอย่าง
--[[ ข้อมูลไฟล์ test2.txt
10 10
asdff
]]
-- Ex.1
a = io.read()
b = io.read()
c = io.read()
print(type(a),a) -- "string" "10 10"
print(b) -- "asdff"
print(c) -- nil
-- Ex.2
a = io.read("n")
b = io.read()
c = io.read("n")
d = io.read()
print(type(a),a) -- "number" 10
print(type(b)) -- " 10"
print(c) -- nil
print(d) -- "asdff"
-- Ex.3
a = io.read("a")
print(a) -- "10 10\nasdff\n"
-- Ex.4
a,b = io.read("n","n")
c = io.read(3)
print(a) -- 10
print(b) -- 10
print(c) -- "asd"
io.lines()
มีรูปแบบการรับข้อมูลเหมือน io.read() แต่คืนค่าเป็น iterator
ตัวอย่าง
--[[ ข้อมูลไฟล์ test2.txt
10 10
asdff
]]
-- Ex.1
a = {}
for line in io.lines("test2.txt") do
table.insert(a,line)
end
print(#a, a[1]) -- 2 "10 10"
print(a[2]) -- "asdff"
print(a[3]) -- nil
-- Ex.2
a = {}
for line in io.lines("test2.txt","n") do
table.insert(a,line)
end
print(#a, a[1]) -- 2 10
print(a[2]) -- 10
print(a[3]) -- nil
-- Ex.3
a = {}
for line in io.lines("test2.txt",3) do
table.insert(a,line)
end
print(#a, a[1]) -- 4 "10 "
print(a[2]) -- "10\n"
print(a[3]) -- "asd"
print(a[4]) -- "ff\n"
print(a[5]) -- nil
แบบใช้เมธอดในอ๊อบเจกต์ไฟล์
โดยมี method ให้ใช้ดังนี้
- read([...]) อ่านข้อมูลจากอ๊อบเจกต์ไฟล์รูปแบบการใช้งานเหมือน io.read()
- seek([option][,pos]) คืนค่าเป็นตำแหน่ง byte ปัจจุบันที่จะอ่านข้อมูลโดยสามารถกำหนดตำแหน่งเริ่มต้น ( pos ) ได้โดยใช้คู่กับ option ถ้าไม่กำหนด option จะใช้ "cur" ( current ) เป็น option ( ค่า option ได้แก่ "cur" ให้ตำแหน่งเริ่มต้นเป็นตำแหน่งปัจจุบัน, "set" กำหนดตำแหน่งเริ่มต้นเป็นตำแหน่งต้นไฟล์ และ "end" กำหนดตำแหน่งเริ่มต้นเป็นตำแหน่งจบไฟล์ ) pos เป็นการเพิ่ม/ลดตำแหน่งจากที่กำหนดใน option ถ้าไม่กำหนดจะใช้ค่าเป็น 0
ตัวอย่าง "hello" ตำแหน่งเริ่มต้นคือ 0 ได้แก่ "h" ตัวสุดท้าย "o" คือตำแหน่งที่ 4 และตำแหน่งจบไฟล์ ( "end" ) คือตำแหน่งที่ 5 - write(...) เขียนข้อมูลลงอ๊อบเจกต์ไฟล์รูปแบบการใช้งานเหมือน io.write()
- lines([format]) คืนข้อมูลเป็น iterator เหมือน io.lines()
- flush() บันทึกข้อมูลใน buffer ลงไฟล์เหมือน io.flush()
- setvbuf(option[,size]) กำหนดการเก็บ buffer โดยที่ option "no" จะไม่เก็บ buffer, "full" จะเก็บจนกว่า buffer จะเต็มหรือสั่ง flush สามารถกำหนด size ได้, "line" จะเก็บจนเจอตัวขึ้นบรรทัดใหม่ ( \n )
ตัวอย่าง
local f = io.open("test2.txt","a+")
print(type(f)) -- "userdata"
print(f) -- file (0xe46100)
local a,b
print(f:seek()) -- 0 ( ตำแหน่งเริ่มต้นข้อมูลคือ 0 )
a = f:read()
print(a,f:seek()) -- "10 10" 6 ( ตำแหน่งเริ่มต้นบรรทัดถัดไป )
print(f:seek("cur",2)) -- 8 ( เลื่อนจากตำแหน่งปัจจุบันไป 2 bytes )
b = f:read()
print(b,f:seek()) -- "dff" 12 ( ตำแหน่งท้ายไฟล์ "10 10\nasdff\n" 12 bytes จาก 0-11 )
print(f:seek("cur",-6)) -- 6 ( เลื่อนจากตำแหน่งปัจจุบันย้อนกลับไป 6 bytes )
b = f:read("L") -- อ่านแบบรวมตัว EOL ด้วย
print(b) -- "asdff\n"
f:seek("set") -- ย้อนกลับไปตำแหน่ง 0
local c = {}
for l in f:lines(3) do
table.insert(c,l)
end
print(#c, c[1]) -- 4 "10 "
print(c[2]) -- "10\n"
print(c[3]) -- "asd"
print(c[4]) -- "ff\n"
print(c[5]) -- nil
f:write("qqq\n") -- เขียนข้อมูลลง buffer ยังไม่บันทึกลงไฟล์ต้องสั่ง flush หรือ close ก่อนหรือไม่ก็ใช้ setvbuf("no") ก็จะไม่เก็บ buffer แต่ส่งไปที่ output ( ไฟล์ ) เลย
f:flush() -- บันทึกลงไฟล์
a = f:read()
b = f:read("a")
print(a,b) -- nil ""
f:seek("set")
a = f:read("a") -- "10 10\nasdff\nqqq\n"
f:write("zzz\n")
f:close() -- บีนทึกลงไฟล์พร้อมปิดไฟล์
print(f) -- file (closed)
สำหรับใน Lua 5.4 จะมี attribute <close> สำหรับตัวแปรที่จะไปเรียก metamethod __close เมื่อออกจากบล๊อกที่ตัวแปรถูกสร้าง ในกรณีที่ตัวแปรเป็น file เมื่อออกจากบล๊อกจะปิดไฟล์เองโดยไม่ต้องเรียกใช้ io.close()
ตัวอย่าง
do
local f <close> = io.open("test2.txt","a+")
local c = {}
for l in f:lines() do
table.insert(c,l)
end
f:write("yyy\n")
end -- ปิดไฟล์อัตโนมัติเมื่อจบบล๊อก
print(#c, c[1]) -- 4 "10 10"
print(c[2]) -- "asdff"
print(c[3]) -- "qqq"
print(c[4]) -- "zzz"
print(c[5]) -- nil
local f2 = io.open("test2.txt")
print(f2:read("a")) -- "10 10\nasdff\nqqq\nzzz\nyyy\n"
f2:close()
ตอนต่อไปมารู้จัก Coroutine กันครับ
บทความถัดไป
ความคิดเห็น
แสดงความคิดเห็น