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



การจัดการไฟล์ด้วย python โดยใช้มอดูล os และ shutil
เขียนเมื่อ 2020/03/19 17:43
การจัดการไฟล์ด้วย python (ใช้มอดูล os และ shutil)


ไพธอนมีฟังก์ชันมากมายที่เกี่ยวกับการจัดการไฟล์ ส่วนใหญ่จะอยู่ในมอดูลชื่อ os ซึ่งเป็นมอดูลที่มีการใช้งานที่หลากหลาย และมีบางส่วนที่อยู่ในมอดูล shutil

ทั้ง ๒​ มอดูลนี้ต่างก็มีอยู่แล้วในไพธอนโดยไม่ต้องติดตั้งเพิ่ม

เนื่องจากคำสั่งภายใน ๒ มอดูลนี้มีความเกี่ยวข้องกันมาก จึงขอสรุปเกี่ยวกับพวกฟังก์ชันต่างๆที่ใช้จัดการไฟล์จาก ๒ มอดูลนี้ลงในบทความนี้ทีเดียวเลย

อย่างไรก็ตาม มอดูล os นั้นแบ่งเป็นหลายส่วน คำสั่งถูกใช้งานได้ในหลายด้าน เช่นมีมอดูลย่อย os.path ซึ่งใช้ในการจัดการเรื่องพาธและข้อมูลไฟล์ ซึ่งได้เขียนถึงไปใน https://phyblas.hinaboshi.com/20200304

shutil เองก็ยังมีอีกหลายฟังก์ชันซึ่งไม่ได้เกี่ยวกับการจัดการไฟล์ ในที่นี้ก็จะไม่ได้พูดถึง

คำสั่งส่วนใหญ่นั้นจริงๆแล้วมีความใกล้เคียงกับคำสั่งที่สั่งในคอมมานด์ไลน์ ซึ่งถ้าใช้มอดูล subprocess (ดูใน https://phyblas.hinaboshi.com/20200306) เพื่อสั่งคอมมานด์ไลน์ก็สามารถทำได้

แต่ถ้าคำสั่งไหนใช้ฟังก์ชันที่มีอยู่แล้วในไพธอนได้ก็ย่อมสะดวกกว่า หากไม่ใช่งานที่ระดับสูงมากนักแค่ใช้ฟังก์ชันต่างๆที่มีอยู่ในมอดูล os และ shutil ก็จัดการได้โดยง่าย

ขอแบ่งอธิบายเป็นกลุ่มๆ ตามการใช้งาน ดูชื่อฟังก์ชันทั้งหมดได้ที่สารบัญข้างบน




การสร้างโฟลเดอร์ (os.mkdir, os.makedirs)

คำสั่งสำหรับสร้างโฟลเดอร์ขึ้นมาใหม่มีอยู่ ๒ ตัวคือ os.mkdir() และ os.makedirs() วิธีการใช้คล้ายกัน คือใส่ชื่อโฟลเดอร์ที่ต้องการสร้าง เช่น
import os

os.mkdir('aki') # สร้างโฟลเดอร์ชื่อ aki
os.makedirs('aya') # สร้างโฟลเดอร์ชื่อ aya

ในกรณีแบบนี้จะใช้อันไหนก็ไม่ต่างกัน แต่ข้อแตกต่างจะเกิดขึ้นในกรณีที่สร้างโฟลเดอร์ซ้อนภายในโฟลเดอร์ที่ไม่มีมาก่อน ถ้าเป็น os.mkdir() จะเกิดข้อผิดพลาดขึ้น แต่ os.makedirs() จะสร้างได้
os.mkdir('ama/saki') # FileNotFoundError: [Errno 2] No such file or directory: 'ama/saki'
os.makedirs('ama/saki') # สร้างโฟลเดอร์ชื่อ ama แล้วจึงสร้างโฟลเดอร์ชื่อ saki ในนั้น

ถ้าหากโฟลเดอร์ที่สร้างมีตัวตนอยู่แล้ว จะเกิดข้อผิดพลาดขึ้น ไม่ว่าจะใช้คำสั่งไหน
os.mkdir('aki') # ได้ FileExistsError: [Errno 17] File exists: 'aki'
os.makedirs('aya') # ได้ FileExistsError: [Errno 17] File exists: 'aya'

แต่สำหรับ os.makedirs สามารถใส่ exist_ok=True เพื่อให้ไม่เกิดอะไรขึ้นเมื่อโฟลเดอร์มีอยู่แล้วได้
os.makedirs('aya',exist_ok=True) # ไม่เกิดอะไรขึ้น




การย้ายหรือเปลี่ยนชื่อไฟล์ (os.rename, os.renames, os.replace, shutil.move)

การย้ายไฟล์หรือเปลี่ยนชื่อไฟล์นั้นที่จริงแล้วก็เป็นเรื่องเดียวกัน มีหลายคำสั่งที่ใช้ในการเปลี่ยนชื่อหรือย้าย ได้แก่ os.rename(), os.renames(), os.replace() และ shutil.move()

ถ้าใช้กับไฟล์หรือโฟลเดอร์ที่มีอยู่แล้ว ไม่ว่าจะใช้อันไหนก็ให้ผลไม่ต่างกัน เป็นการเปลี่ยนชื่อไฟล์หรือโฟลเดอร์นั้น
import os,shutil

os.rename('aki','aka') # เปลี่ยนชื่อ aki เป็น aka
os.renames('ama','ami') # เปลี่ยนชื่อ ama เป็น ami
os.replace('aya','maya') # เปลี่ยนชื่อ aya เป็น maya
shutil.move('maya','saya') # เปลี่ยนชื่อ maya เป็น saya

แต่ในกรณีที่ปลายทางเป็นโฟลเดอร์ที่มีอยู่แล้วและเป็นโฟลเดอร์ที่ไม่ว่างเปล่า แบบนี้ os.rename(), os.renames(), os.replace() จะเกิดข้อผิดพลาดขึ้น ในขณะที่ shutil.move() จะเป็นการย้ายเข้าโฟลเดอร์นั้น
os.rename('aka','ami') # OSError: [Errno 66] Directory not empty: 'aka' -> 'ami'
os.renames('aka','ami') # OSError: [Errno 66] Directory not empty: 'aka' -> 'ami'
os.replace('aka','ami') # OSError: [Errno 66] Directory not empty: 'aka' -> 'ami'
shutil.move('aka','ami') # ย้าย aka ไปไว้ใน ami

เพียงแต่หากไฟล์ที่ต้องการย้ายนั้นเป็นโฟลเดอร์ และย้ายไปโฟลเดอร์ปลายทางซึ่งพอดีเป็นโฟลเดอร์เปล่า แบบนี้ os.rename(), os.renames(), os.replace() จะกลายเป็นการย้ายโฟลเดอร์ต้นทางไปทับโฟลเดอร์นั้นแทน

กรณีที่ปลายทางอยู่ในโฟลเดอร์ที่ไม่มีตัวตนอยู่ os.rename() กับ os.replace() จะเกิดข้อผิดพลาด ส่วน os.renames() กับ shutil.move() จะสร้างโฟลเดอร์ใหม่ขึ้นมาตามเส้นทาง
os.rename('aka','hana/saka') # FileNotFoundError: [Errno 2] No such file or directory: 'aka' -> 'hana/saka'
os.replace('aka','hana/saka') # FileNotFoundError: [Errno 2] No such file or directory: 'aka' -> 'hana/saka'
os.renames('aka','hana/saka') # aka ย้ายไปอยู่ใน hana และเปลี่ยนชื่อเป็น saka
# shutil.move('aka','hana/saka') ก็ให้ผลเหมือน os.renames()

กรณีที่ย้ายไฟล์ออกจากโฟลเดอร์แล้วโฟลเดอร์นั้นไม่เหลือไฟล์อื่น หากใช้ os.renames() จะทำการลบโฟลเดอร์นั้นทิ้งโดยอัตโนมัติ ส่วนตัวอื่นจะแค่ย้ายไปที่ใหม่
os.renames('hana/saka','saya/suki')
# saka ย้ายไปอยู่ใน saya และเปลี่ยนชื่อเป็น suki ส่วน โฟลเดอร์ hana ถูกลบทิ้ง




การคัดลอกไฟล์ (shutil.copy, shutil.copy2, shutil.copyfile, shutil.copytree, shutil.copystat)

ฟังก์ชันสำหรับทำการคัดลอกอยู่ในมอดูล shutil ทั้งหมด

shutil.copy(), shutil.copy2(), shutil.copyfile() ใช้คัดลอกไฟล์ธรรมดาที่ไม่ใช่โฟลเดอร์ ถ้าใช้กับโฟลเดอร์จะเกิดข้อผิดพลาด

ข้อแตกต่างคือ shutil.copy() กับ shutil.copyfile() จะแค่คัดลอกเนื้อหาจากไฟล์เดิมไปสร้างไฟล์ให้มีเนื้อหาเหมือนเดิม แต่พวกข้อมูลสถานะเช่นพวกเวลาสร้าง เวลาแก้ไข จะไม่ได้คัดลอกมาด้วย แต่จะเหมือนสร้างใหม่

ตัวอย่างเช่น มีไฟล์นึงชื่อ sasori.txt ลองคัดลอกไปเป็นไฟล์อีกชื่อ
shutil.copy('sasori.txt','sasuru.txt') # คัดลอกแค่เนื้อหาไฟล์
shutil.copy2('sasori.txt','sosoru.txt') # คัดลอกทั้งเนื้อหาไฟล์และสถานะ
shutil.copyfile('sasori.txt','susuri.txt') # คัดลอกแค่เนื้อหาไฟล์

ส่วน shutil.copytree() จะใช้คัดลอกโฟลเดอร์ พร้อมทั้งเนื้อหาที่อยู่ในโฟลเดอร์ทั้งหมด ถ้าปลายทางอยู่ในโฟลเดอร์ที่ยังไม่มีตัวตนอยู่ก็จะถูกสร้างใหม่
shutil.copytree('ami','hama') # ตัดลอกโฟลเดอร์และเนื้อใน ami ไปยัง hama
shutil.copytree('ami','asa/nagi') # โฟลเดอร์ asa จะถูกสร้างขึ้นถ้าไม่มีอยู่ แล้วจึงคัดลอกข้อมูลจาก ami ไป nagi ใน asa

ปกติแล้วการคัดลอกจะให้ผลเหมือยน shutil.copy2() คือคัดลอกทั้งเนื้อหาไฟล์และข้อมูลประกอบไฟล์ แต่หากต้องการทำให้คัดลอกแบบ shutil.copy ก็ทำได้โดยใส่ copy_function=shutil.copy
shutil.copytree('ami','nami',copy_function=shutil.copy)

ถ้าโฟลเดอร์ปลายทางมีอยู่แล้วก็จะเกิดข้อผิดพลาดขึ้น แต่ในไพธอน 3.8 สามารถใส่ dirs_exist_ok=True เพื่อจะทำให้สามารถคัดลอกได้แม้จะมีโฟลเดอร์เดิมอยู่ โดยเนื้อหาจากต้นฉบับจะถูกคัดลอกเข้าไปยังโฟลเดอร์ปลายทางนั้น ส่วนเนื้อหาในโฟลเดอร์ปลายทางที่มีอยู่เดิมก็ไม่ได้หายไปไหน
shutil.copytree('ami','nami',dirs_exist_ok=True)

ส่วน shutil.copystat() มีไว้คัดลอกสถานะของไฟล์หนึ่งไปยังอีกไฟล์ที่มีอยู่แล้ว โดยไม่ได้เปลี่ยนเนื้อหาข้างใน
shutil.copystat('sasori.txt','sasuru.txt')




สร้างลิงก์หรือชอร์ตคัต (os.link, os.symlink)

ฟังก์ชัน os.link() มีไว้สร้างฮาร์ดลิงก์ ส่วน os.symlink() ไว้ใช้สร้างซิมโบลิกลิงก์
os.link('sasori.txt','sasoru.txt') # สร้างฮาร์ดลิงก์ของ sasori.txt ชื่อ sasoru.txt
os.symlink('sasori.txt','sasara.txt') # สร้างซิมโบลิกลิงก์ของ sasori.txt ชื่อ sasara.txt

เกี่ยวกับความแตกต่างระหว่างฮาร์ดลิงก์กับซิมโบลิกลิงก์ได้เขียนถึงไว้ใน https://phyblas.hinaboshi.com/20200303




การลบไฟล์หรือโฟลเดอร์ (os.remove, os.unlink, os.rmdir, os.removedirs, shutil.rmtree)

ฟังก์ชันที่ใช้ในการลบไฟล์คือ os.remove() และ os.unlink() ใช้อันไหนก็เหมือนกัน
os.remove('sasara.txt') # ลบ sasara.txt

os.rmdir() กับ os.removedirs() มีไว้ใช้ลบโฟลเดอร์เปล่า แต่ถ้าใช้กับโฟลเดอร์ที่มีอะไรอยู่จะเกิดข้อผิดพลาด
os.rmdir('hama/saki') # ลบโฟลเดอร์ saka ในโฟลเดอร์ hama แต่ถ้าใน saka ไม่ได้ว่างเปล่าจะเกิดข้อผิดพลาด

หากต้องการลบโฟลเดอร์ที่มีอะไรอยู่พร้อมกับไฟล์ในนั้นทั้งหมดให้ใช้ shutil.rmtree
shutil.rmtree('asa') # ลบโฟลเดอร์ asa และไฟล์ที่อยู่ข้างในทั้งหมด




โฟลเดอร์ที่ทำงาน (os.chdir, os.getcwd)

os.getcwd() ใช้หาพาธของโฟลเดอร์ที่ทำงานอยู่ปัจจุบัน และหากต้องการย้ายโฟลเดอร์ก็ใช้ os.chdir()

ตัวอย่าง
os.chdir('/') # ย้ายโฟลเดอร์ทำงานไปที่ /
os.getcwd() # ได้ /




ดูสถานะไฟล์ (os.stat, os.lstat)

os.stat ใช้สำหรับดูข้อมูลสถานะของไฟล์
stat = os.stat('sasori.txt')
print(stat) # ได้ os.stat_result(st_mode=33188, st_ino=14819342, st_dev=16777223, st_nlink=3, st_uid=501, st_gid=20, st_size=5, st_atime=1584553332, st_mtime=1584549830, st_ctime=1584553331)
print(stat.st_mode) # ได้ 33188

st_atime, st_ctime และ st_mtime เป็นข้อมูลเวลา ถูกแสดงในรูปตัวเลขวินาที timestamp อาจใช้ datetime.datetime.fromtimestamp() เพื่อเปลี่ยนเป็นวันที่ที่อ่านได้ (รายละเอียดการใช้ดูได้ใน https://phyblas.hinaboshi.com/20160621)
import datetime

print(datetime.datetime.fromtimestamp(stat.st_atime)) # ได้ 2020-03-19 01:42:12.758729
print(datetime.datetime.fromtimestamp(stat.st_ctime)) # ได้ 2020-03-19 01:42:11.705659
print(datetime.datetime.fromtimestamp(stat.st_mtime)) # ได้ 2020-03-19 00:43:50.621884

os.lstat() จะเหมือนกับ os.stat() แต่ต่างกันตรงที่ถ้าหากใช้กับไฟล์ที่เป็นซิมโบลิกลิงก์ จะตามไปหาข้อมูลไฟล์ต้นทางแทน

เช่นสมมุติว่า sasara.txt เป็นซิมโบลิกลิงก์ของไฟล์ sasori.txt เมื่อครู่นี้ ก็จะได้ว่าผลของ os.stat() กับ os.fstat() ต่างกัน
stat = os.stat('sasara.txt')
lstat = os.lstat('sasara.txt')
print(stat==lstat) # ได้ T False
print(stat) # ได้ os.stat_result(st_mode=33279, st_ino=14819342, st_dev=16777223, st_nlink=3, st_uid=501, st_gid=20, st_size=5, st_atime=1584595520, st_mtime=1584549830, st_ctime=1584595595)
print(lstat) # ได้ os.stat_result(st_mode=41453, st_ino=14851181, st_dev=16777223, st_nlink=1, st_uid=501, st_gid=20, st_size=10, st_atime=1584594424, st_mtime=1584594424, st_ctime=1584594424)
print(os.stat('sasori.txt')==os.lstat('sasori.txt')) # ได้ True




จัดการสิทธิไฟล์ (os.chmod, os.chown, os.chflags, os.lchmod, os.lchown, os.lchflags)

os.chmod(), os.chown(), os.chflags() มีไว้สำหรับเปลี่ยนพวกสิทธิหรือสถานะต่างๆใน unix เทียบเท่ากับการใช้คำสั่ง chmod, chown, chflags ในเชลยูนิกซ์ ในที่นี้จะไม่อธิบายละเอียด แต่มีเขียนถึงไว้ใน https://phyblas.hinaboshi.com/20190126

ตัวอย่างการใช้
os.chflags('sasori.txt',0)
os.chmod('sasori.txt',0o777)
os.chown('sasori.txt',501,20)

ส่วน os.lchmod(), os.lchown(), os.lchflags() จะคล้ายกัน แค่ต่างตรงที่ว่าถ้าเจอซิมโบลิกลิงก์จะไปจัดการที่ตัวต้นทางแทน




ดูไฟล์ที่มีอยู่ในโฟลเดอร์ (os.listdir, os.scandir)

ฟังก์ชัน os.listdir() จะแสดงลิสต์ของชื่อไฟล์ทั้งหมดในโฟลเดอร์ที่ระบุ แต่ถ้าหากไม่ระบุโฟลเดอร์ก็จะแสดงไฟล์ของโฟลเดอร์ที่ทำงานอยู่ปัจจุบัน

ตัวอย่าง
os.listdir('kami') # ได้ ['nari.txt', 'washinda']

นอกจากนี้ยังมี os.scandir() จะดูไฟล์ต่างๆในโฟลเดอร์ทั้งหมด คล้ายกับ os.listdir() แต่จะให้ผลออกมาเป็นอิเทอเรเตอร์ซึ่งสามารถนำมาดูข้อมูลของไฟล์ได้หลายอย่าง

วิธีการใช้มักใช้คู่กับ for เพื่อวนดูไฟล์ทีละตัว และใช้เสร็จก็ให้ใช้ .close() เพื่อปิดด้วย หรือจะใช้กับ with เพื่อจะได้ไม่ต้องมาปิดตอนท้ายก็ได้
fol = os.scandir('kami')
for f in fol:
    print('=='+f.name+'==') # แสดงชื่อไฟล์
    print('path: %s'%f.path) # แสดงพาธไฟล์
    print('inode: %s'%f.inode()) # แสดงไอโหนด
    print('file?: %s'%f.is_file()) # เป็นไฟล์ธรรมดาหรือเปล่า?
    print('dir?: %s'%f.is_dir()) #  เป็นโฟลเดอร์หรือเปล่า?
    print('symlink?: %s'%f.is_symlink()) # เป็นซิมโบลิกลิงก์หรือเปล่า?
    print('stat: %s'%(f.stat(),)) # แสดงข้อมูลสถานะ
fol.close()

ได้
==nari.txt==
path: kami/nari.txt
inode: 14849154
file?: True
dir?: False
symlink?: False
stat: os.stat_result(st_mode=33188, st_ino=14849154, st_dev=16777223, st_nlink=1, st_uid=501, st_gid=20, st_size=5, st_atime=1584592839, st_mtime=1584549830, st_ctime=1584592838)
==washinda==
path: kami/washinda
inode: 14849149
file?: False
dir?: True
symlink?: False
stat: os.stat_result(st_mode=16877, st_ino=14849149, st_dev=16777223, st_nlink=2, st_uid=501, st_gid=20, st_size=64, st_atime=1584592813, st_mtime=1584592813, st_ctime=1584592821)




ไล่จัดการโฟลเดอร์ไปทีละชั้น (os.walk)

os.walk() เป็นฟังก์ชันที่สะดวกเมื่อต้องการจะไล่จัดการกับไฟล์ที่อยู่ในโฟลเดอร์ที่ซ้อนอยู่ในโฟลเดอร์ย่อยเป็นชั้นๆ

ฟังก์ชันนี้เมื่อใช้ไปจะคืนค่าเป็นเจเนอเรเตอร์ที่มีข้อมูลของโฟลเดอร์ โดยจะให้ ๓ อย่างมาพร้อมกัน คือ
- [พาธโฟลเดอร์นั้น, ลิสต์ของโฟลเดอร์ข้างใน, ลิสต์ของไฟล์ข้างใน]

จากนั้นหากในนั้นมีโฟลเดอร์อยู่ ในรอบต่อๆไปของ for ก็จะไปวนดูโฟลเดอร์ด้านในนั้น และให้ค่า ๓ อย่างเหมือนเดิม เป็นอย่างนี้ซ้ำไปเรื่อยๆจนหมดทุกโฟลเดอร์ย่อยด้านใน

ตัวอย่างการใช้ เช่น สมมุติมีโฟลเดอร์ที่ข้างในมีโฟลเดอร์ย่อยและไฟล์แบบนี้



เมื่อลองใช้ os.walk() เพื่อให้ไล่ดูไฟล์และโฟลเดอร์ข้างในไปทีละชั้น
import os

i = 0
for path,lis_fol,lis_fai in os.walk('sa'):
    i += 1
    print('%d. ในโฟลเดอร์ '%i+path)
    print('มีโฟลเดอร์ %d โฟลเดอร์'%len(lis_fol))
    for fol in lis_fol:
        print('- '+os.path.join(path,fol))
    print('มีไฟล์ %d ไฟล์'%len(lis_fai))
    for fai in lis_fai:
        print('- '+os.path.join(path,fai))

ก็จะไล่ออกมาได้ผลแบบนี้
1. ในโฟลเดอร์ sa
มีโฟลเดอร์ 2 โฟลเดอร์
- sa/ga
- sa/ka
มีไฟล์ 0 ไฟล์
2. ในโฟลเดอร์ sa/ga
มีโฟลเดอร์ 1 โฟลเดอร์
- sa/ga/shi
มีไฟล์ 2 ไฟล์
- sa/ga/mi
- sa/ga/su
3. ในโฟลเดอร์ sa/ga/shi
มีโฟลเดอร์ 2 โฟลเดอร์
- sa/ga/shi/ma
- sa/ga/shi/te
มีไฟล์ 1 ไฟล์
- sa/ga/shi/ta
4. ในโฟลเดอร์ sa/ga/shi/ma
มีโฟลเดอร์ 1 โฟลเดอร์
- sa/ga/shi/ma/su
มีไฟล์ 0 ไฟล์
5. ในโฟลเดอร์ sa/ga/shi/ma/su
มีโฟลเดอร์ 0 โฟลเดอร์
มีไฟล์ 0 ไฟล์
6. ในโฟลเดอร์ sa/ga/shi/te
มีโฟลเดอร์ 0 โฟลเดอร์
มีไฟล์ 0 ไฟล์
7. ในโฟลเดอร์ sa/ka
มีโฟลเดอร์ 1 โฟลเดอร์
- sa/ka/mi
มีไฟล์ 1 ไฟล์
- sa/ka/na
8. ในโฟลเดอร์ sa/ka/mi
มีโฟลเดอร์ 0 โฟลเดอร์
มีไฟล์ 1 ไฟล์
- sa/ka/mi/chi

เนื่องจากมีทั้งหมด ๘ โฟลเดอร์ (รวมตัวโฟลเดอร์ที่เริ่มต้นด้วย) ดังนั้นจึงมีการวน ๘ ครั้ง แต่ละครั้งจะบอกเนื้อหาว่าข้างในมีโฟลเดอร์อะไรอยู่บ้าง โดยไล่จากนอกสุดเข้ามา




อ้างอิง


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

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

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

หมวดหมู่

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

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

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
python
-- numpy
-- matplotlib

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

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



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

  ค้นหาบทความ

  บทความแนะนำ

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

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

2020年

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

2019年

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

2018年

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

2017年

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

2016年

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

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

ไทย

日本語

中文