Files and mapping
API summary (generated from the Beans source by npm run coverage): 3 types · 18 static methods · 35 instance methods.
file system নিয়ে কাজ করার জন্য Beans-এ তিনটা builtin type আছে: একটা file-এর জন্য
File, directory-র জন্য Dir, আর memory-mapped file ও shared memory-র জন্য
MMap। এগুলো native builtin, এদের কোনো .b source নেই, আর runtime ABI table দিয়ে
এদের কাছে পৌঁছানো হয় —
compiler/beans/expression.b-তে।
এগুলো builtin বলে এদের signature গুলো positional: parameter-এর type গুলো fixed, নাম
গুলো signature-এর অংশ না। বেশিরভাগ call একটা Result
দেয়, কারণ file নিয়ে কাজ ব্যর্থ হতে পারে। read আর write Bytes
সরায়।
File
“File” সেকশনএকটা খোলা file, সাথে একটা read/write cursor।
Static গুলো
“Static গুলো” সেকশনএগুলো File type-এর ওপরই call করা হয়। খোলাটা হলো সেই constructor যেটা ব্যর্থ হতে
পারে: এটা Result<File> দেয়।
File.exists(string) -> boolFile.size(string) -> Result<int>File.open(string, string) -> Result<File>File.copy(string, string) -> Result<int>File.remove(string) -> Result<bool>File.rename(string, string) -> Result<bool>File.open-এর দ্বিতীয় argument হলো mode, এর একটা:
"r": শুধু পড়া"rw": পড়া আর লেখা, file আগে থেকেই থাকতে হবে"create": নতুন বানায়, বা থাকা file-টা খালি করে, পড়া আর লেখার জন্য"append": শেষে যোগ করার জন্য খোলে
File.exists file না খুলেই বলে দেয় সেটা আছে কিনা। File.size একটা static
হিসেবেও কাজ করে যেটা একটা path নেয়, তাই কোনো খোলা handle ছাড়াই file-এর length পড়া
যায়; একই call একটা খোলা file-এর ওপর method হিসেবেও আছে (নিচে)। File.copy যেখানে
পাওয়া যায় সেখানে platform-এর নিজের file-copy পথ ব্যবহার করে, আর byte-এর সংখ্যাটা
ফেরত দেয়।
Method গুলো
“Method গুলো” সেকশনFile.read(int) -> Result<Bytes>File.read_at(int, int) -> Result<Bytes>File.read_text(int) -> Result<string>File.read_text_at(int, int) -> Result<string>File.write(Bytes) -> Result<int>File.write_at(int, Bytes) -> Result<int>File.write_text(string) -> Result<int>File.write_text_at(int, string) -> Result<int>File.seek(int) -> intFile.seek_from_end(int) -> intFile.tell() -> intFile.size() -> Result<int>File.truncate(int) -> Result<bool>File.sync() -> Result<bool>File.close() -> Result<bool>File.lock() -> Result<bool>File.try_lock() -> Result<bool>File.unlock() -> Result<bool>read(n)বর্তমান cursor থেকেnbyte পর্যন্ত পড়ে আর cursor-টা সামনে সরিয়ে দেয়; file-এর শেষে গিয়ে কম পড়া হলে যেটুকু byte আছে সেটুকুই দেয়।write(b)cursor থেকে লেখে, কত byte গেল সেটা ফেরত দেয়, আর cursor-টা সামনে সরিয়ে দেয়।read_at(pos, n)আরwrite_at(pos, b)একটা পূর্ণ অবস্থান নেয় আর cursor ব্যবহার বা সরায় না, তাই file-এর একাধিক জায়গা থেকে এগুলো call করা নিরাপদ।read_textআরread_text_atহলো text-এর রূপ। এগুলোBytesপড়ে convert না করে সরাসরি ফেরত দেওয়া string-টা ভরে দেয়।write_textআরwrite_text_atসরাসরি string storage লেখে। data যখন text, তখন এগুলো ব্যবহার করা হয়; byte method গুলো তাদের নিজের ownedBytesআচরণ রাখে।seek(pos)cursor-টাpos-এ সরায়;seek_from_end(off)সেটাকে file-এর শেষ থেকেoffbyte আগে সরায়। দুইটাই নতুন অবস্থানটা ফেরত দেয় আর file বন্ধ থাকলে panic করে।tell()বর্তমান অবস্থানটা ফেরত দেয়।truncate(n)file-টাকে ঠিকnbyte-এ কাটে বা বাড়ায়।sync()file-এর data disk-এ flush করে (fsync)।close()descriptor-টা ছেড়ে দেয়; আগেই বন্ধ হয়ে যাওয়া একটা file আবার বন্ধ করা একটা error।lock,try_lock, আরunlockএকটা advisory whole-file lock (flock) নেয় ও ছাড়ে।locklock না পাওয়া পর্যন্ত block করে থাকে;try_lockঅন্য কেউ lock ধরে রাখলে অপেক্ষা না করেok(false)দেয়।
Beans যে file descriptor-এর মালিক, সেগুলো সবই close-on-exec।
একটা file লেখা, তারপর cursor দিয়ে তার একটা অংশ আবার পড়া:
import std.io
fn main() { let f: File = File.open("greeting.txt", "create").expect("open") f.write(Bytes.from("hello world")).expect("write")
f.seek(0) let head: Bytes = f.read(5).expect("read") io.println(head.to_string()) io.println("cursor now at {f.tell()}")
f.close().expect("close")}Dir
“Dir” সেকশনসব directory-র কাজ Dir type-এর static-এর ওপর।
Dir.create(string) -> Result<bool>Dir.create_all(string) -> Result<bool>Dir.current() -> stringDir.exists(string) -> boolDir.list(string) -> Result<List<string>>Dir.walk(string) -> Result<List<string>>Dir.remove(string) -> Result<bool>Dir.remove_all(string) -> Result<bool>Dir.sync(string) -> Result<bool>Dir.temp_path() -> stringcreateএকটা directory বানায় আর কোনো parent না থাকলে ব্যর্থ হয়;create_alldirectory-টা আর যেসব parent নেই সেগুলোও বানায়।current()process-এর বর্তমান working directory একটা absolute path হিসেবে ফেরত দেয়।listএকটা directory-র ঠিক ভেতরের নাম গুলো sorted অবস্থায় ফেরত দেয়।walkতার নিচের প্রতিটা file আর symlink ফেরত দেয়, recursive, sorted, আর প্রতিটা path যে directory দেওয়া হয়েছে তার relative।removeএকটা খালি directory সরায়;remove_allএকটা directory আর তার ভেতরের সবকিছু সরায়।syncdirectory entry-টা নিজেই flush করে।temp_pathsystem-এর temporary directory-টা একটা সাধারণ string হিসেবে ফেরত দেয়; এটা disk-এ হাত দেয় না।
import std.io
fn main() { let base: string = "{Dir.temp_path()}/beans_docs_demo" Dir.create_all(base).expect("create")
let names: List<string> = Dir.list(Dir.temp_path()).expect("list") io.println("{names.len()} entries in the temp directory")
Dir.remove_all(base).expect("clean up")}MMap
“MMap” সেকশনMMap একটা file, বা একটা POSIX shared memory object, memory-তে map করে, যাতে
সেটা একটা buffer-এর মতো পড়া আর লেখা যায়।
Static গুলো
“Static গুলো” সেকশনMMap.open(string, bool) -> Result<MMap>MMap.open_shared_memory(string, int, bool) -> Result<MMap>MMap.unlink_shared_memory(string) -> Result<bool>MMap.open(path, writable)পুরো file-টাMAP_SHAREDদিয়ে map করে। writable mapping-এর জন্যtrueদিতে হয়, শুধু পড়ার জন্যfalse।MMap.open_shared_memory(name, size, create)একটা নাম-ধরা shared memory object খোলে। প্রতিবার খোলার সময়sizeদিতে হয়, আর object না থাকলে বানানো হবে কিনা সেটাcreateঠিক করে।MMap.unlink_shared_memory(name)নাম দিয়ে একটা shared memory object সরিয়ে দেয়।
Method গুলো
“Method গুলো” সেকশনMMap.len() -> intMMap.get_u8(int) -> intMMap.get_u16(int) -> intMMap.get_u32(int) -> intMMap.get_u64(int) -> intMMap.get_i64(int) -> intMMap.put_u8(int, int) -> MMapMMap.put_u16(int, int) -> MMapMMap.put_u32(int, int) -> MMapMMap.put_u64(int, int) -> MMapMMap.put_i64(int, int) -> MMapMMap.read(int, int) -> BytesMMap.write(int, Bytes) -> MMapMMap.flush() -> Result<bool>MMap.flush_range(int, int) -> Result<bool>MMap.resize(int) -> Result<bool>MMap.close() -> Result<bool>len()হলো map-করা আকার, byte-এ।get_*reader গুলো একটা byte-অবস্থানে একটা integer পড়ে, little-endian আর bounds-checked; সীমার বাইরের অবস্থান হলে panic হয়।put_*writer গুলো একটা অবস্থানে একটা integer লেখে, little-endian আর bounds-checked, আর একই mapping ফেরত দেয় যাতে চেইন করা যায়।read(pos, n)pos-এ থাকাnbyte একটা নতুনBytes-এ copy করে।write(pos, b)b-কে mapping-এরpos-এ copy করে আর mapping-টা ফেরত দেয়।flush()সব বদল আবার লিখে দেয় (msync);flush_range(pos, n)শুধু[pos, pos + n)flush করে।resize(n)mapping-টা resize করে আর এটা shared memory-তে পাওয়া যায় না।close()সেটা unmap করে।
import std.io
fn main() { let name: string = "beans_docs_shm" let m: MMap = MMap.open_shared_memory(name, 64, true).expect("open")
m.put_u32(0, 123456789).put_u64(8, 42) io.println("{m.get_u32(0)} {m.get_u64(8)} over {m.len()} bytes")
m.flush().expect("flush") m.close().expect("close") MMap.unlink_shared_memory(name).expect("unlink")}Error-এর ধরন
“Error-এর ধরন” সেকশনকোনো file call ব্যর্থ হলে, Error.kind slug-টা এগুলোর একটা হয়:
not_found, permission, exists, is_dir, not_dir, not_empty, closed,
io।
কী করা হবে সেটা ঠিক করতে kind-এর ওপর match করা যায়। দেখুন Option, Result, আর Error।
আরও দেখুন
“আরও দেখুন” সেকশন- Bytes, read আর write যে buffer ব্যবহার করে।
- Option, Result, আর Error, ব্যর্থতা সামলানো।
- standard library, উঁচু-স্তরের I/O module গুলো।