std.os
操作系统接口模块:文件句柄读写、目录操作、环境变量与工作目录。
use std.os本模块全部函数依赖操作系统能力,在
wasm32目标上不导出。
文件句柄模型
句柄按引用传递(#337 已修复):
read/write/seek/tell/flush/close的签名均为(file: &File, ...),故句柄可反复使用:yaoxiangf = os.open(p, "w") os.write(f, "hello world") os.close(f)定位后读写(
seek存在的理由)也已可用:yaoxiangr = os.open(p, "r") os.seek(r, 6) tail = os.read(r, 5) // "world" os.close(r)修复前签名无
&,句柄按值传入 → 线性所有权 → 用一次即失效,open → write → close会报E2014。若想避免手工管理句柄,仍可用不开句柄的便捷函数:
std.io.read_file/write_file/append_file,或本模块的append_file。
open 返回的是一个 Int 类型的文件描述符(引擎内部维护句柄表),因此签名中的 File 实为 Int。
写入后内容立即落盘,无需显式 close:
use std.assert
use std.io
use std.os
main: () -> Void = {
p = "__yx_doc_open.txt"
n = os.write(os.open(p, "w"), "hello")
assert(n == 5)
assert(io.read_file(p) == "hello")
os.remove(p)
}open 支持的模式:
| 模式 | 含义 |
|---|---|
r | 只读,文件须存在 |
w | 只写,创建或清空 |
a | 追加,创建或追加到末尾 |
r+ | 读写,文件须存在 |
w+ | 读写,创建或清空 |
a+ | 读写,创建或追加 |
函数一览
| 函数 | 签名 |
|---|---|
open | (path: &String, mode: &String) -> File |
close | (file: &File) -> Void |
read | (file: &File, n: Int) -> String |
write | (file: &File, content: String) -> Int |
seek | (file: &File, offset: Int) -> Bool |
tell | (file: &File) -> Int |
flush | (file: &File) -> Void |
mkdir | (path: &String) -> Bool |
rmdir | (path: &String) -> Bool |
read_dir | (path: &String) -> String |
remove | (path: &String) -> Bool |
exists | (path: &String) -> Bool |
is_file | (path: &String) -> Bool |
is_dir | (path: &String) -> Bool |
copy | (src: &String, dst: &String) -> Bool |
rename | (old: &String, new: &String) -> Bool |
get_env | (name: &String) -> String |
set_env | (name: &String, value: &String) -> Void |
args | () -> String |
chdir | (path: &String) -> Bool |
getcwd | () -> String |
append_file | (path: &String, content: &String) -> Bool |
open
open: (path: &String, mode: &String) -> File打开文件并返回文件描述符。
path—— 文件路径(只读借用)mode—— 打开模式,见上表
返回:内部句柄表分配的 Int 描述符。该句柄只能使用一次——任一下游调用都会移动它(见文件句柄模型),因此通常把 open 内联进单次调用。
错误:模式非法、文件不存在或无权限时抛出 E6007。
句柄只能使用一次(#337),因此该返回值通常直接内联进下游调用。
use std.assert
use std.os
main: () -> Void = {
p = "__yx_doc_open_only.txt"
f = os.open(p, "w")
assert(os.exists(p))
os.remove(p)
}close
close: (file: &File) -> Void关闭文件句柄并释放表项。
因为句柄只能使用一次,close 只在“打开后不作他用”的场景有意义;写入内容在 write 返回时已落盘,通常无需显式关闭。
错误:描述符无效(未打开或已关闭)时抛出 E6007。
use std.os
main: () -> Void = {
p = "__yx_doc_close.txt"
f = os.open(p, "w")
os.close(f)
os.remove(p)
}read
read: (file: &File, n: Int) -> String从当前读写位置读取最多 n 字节。
file—— 文件描述符n—— 期望读取的字节数
返回:实际读到的内容(可能短于 n,到达文件末尾时为空串)。非法 UTF-8 字节以替换字符形式返回,不报错。错误:描述符无效或读取失败时抛出 E6007。
use std.assert
use std.io
use std.os
main: () -> Void = {
p = "__yx_doc_read.txt"
io.write_file(p, "abcdef")
part = os.read(os.open(p, "r"), 3)
assert(part == "abc")
os.remove(p)
}write
write: (file: &File, content: String) -> Int向当前读写位置写入全部 content。
content—— 按值传入
返回:写入的字节数。错误:描述符无效或写入失败时抛出 E6007。
use std.assert
use std.os
main: () -> Void = {
p = "__yx_doc_write.txt"
n = os.write(os.open(p, "w"), "hello")
assert(n == 5)
os.remove(p)
}seek
seek: (file: &File, offset: Int) -> Bool把读写位置移动到绝对偏移 offset(相对文件开头)。
offset—— 目标字节偏移,须非负
返回:成功返回 true。错误:描述符无效或偏移非法时抛出 E6007。
use std.assert
use std.io
use std.os
main: () -> Void = {
p = "__yx_doc_seek.txt"
io.write_file(p, "abcdef")
ok = os.seek(os.open(p, "r"), 2)
assert(ok)
os.remove(p)
}tell
tell: (file: &File) -> Int返回当前读写位置的字节偏移。
错误:描述符无效时抛出 E6007。
use std.assert
use std.os
main: () -> Void = {
p = "__yx_doc_tell.txt"
pos = os.tell(os.open(p, "w"))
assert(pos == 0)
os.remove(p)
}flush
flush: (file: &File) -> Void把缓冲内容刷入磁盘。
错误:描述符无效或刷新失败时抛出 E6007。
use std.assert
use std.os
main: () -> Void = {
p = "__yx_doc_flush.txt"
os.flush(os.open(p, "w"))
assert(os.exists(p))
os.remove(p)
}目录操作
mkdir
mkdir: (path: &String) -> Bool创建单层目录(不递归创建父目录)。
返回:成功返回 true。错误:父目录不存在或目录已存在时抛出 E6007。
use std.assert
use std.os
main: () -> Void = {
d = "__yx_doc_mkdir"
assert(os.mkdir(d))
assert(os.is_dir(d))
os.rmdir(d)
}rmdir
rmdir: (path: &String) -> Bool删除空目录。
返回:成功返回 true。错误:目录不存在或非空时抛出 E6007。
use std.assert
use std.os
main: () -> Void = {
d = "__yx_doc_rmdir"
os.mkdir(d)
assert(os.rmdir(d))
assert(!os.exists(d))
}read_dir
read_dir: (path: &String) -> String列出目录下的条目名。
返回:入口名称以 \n 连接的单个字符串(不是 List)。错误:目录不存在或无权限时抛出 E6007。
use std.assert
use std.os
use std.string
main: () -> Void = {
d = "__yx_doc_read_dir"
os.mkdir(d)
names = os.read_dir(d)
// 空目录返回空串
assert(string.is_empty(names))
os.rmdir(d)
}路径与文件工具
remove
remove: (path: &String) -> Bool删除文件,语义等同 remove_file(不能删目录,删目录用 rmdir)。
返回:成功返回 true。错误:文件不存在或路径是目录时抛出 E6007。
use std.assert
use std.io
use std.os
main: () -> Void = {
p = "__yx_doc_remove.txt"
io.write_file(p, "x")
assert(os.remove(p))
assert(!os.exists(p))
}exists
exists: (path: &String) -> Bool路径是否存在(文件或目录皆可)。不报错,不存在返回 false。
use std.assert
use std.os
main: () -> Void = {
assert(os.exists("."))
assert(!os.exists("__yx_definitely_missing_path__"))
}is_file
is_file: (path: &String) -> Bool路径是否为普通文件。目录返回 false,不存在返回 false。
use std.assert
use std.os
main: () -> Void = {
assert(!os.is_file("."))
}is_dir
is_dir: (path: &String) -> Bool路径是否为目录。文件返回 false,不存在返回 false。
use std.assert
use std.os
main: () -> Void = {
assert(os.is_dir("."))
}copy
copy: (src: &String, dst: &String) -> Bool复制文件。目标已存在时覆盖。
返回:成功返回 true。错误:源文件不存在或无权限时抛出 E6007。
use std.assert
use std.io
use std.os
main: () -> Void = {
a = "__yx_doc_copy_a.txt"
b = "__yx_doc_copy_b.txt"
io.write_file(a, "data")
assert(os.copy(a, b))
assert(io.read_file(b) == "data")
os.remove(a)
os.remove(b)
}rename
rename: (old: &String, new: &String) -> Bool重命名或移动文件。
返回:成功返回 true。错误:源文件不存在或目标已存在时抛出 E6007。
use std.assert
use std.io
use std.os
main: () -> Void = {
a = "__yx_doc_rename_a.txt"
b = "__yx_doc_rename_b.txt"
io.write_file(a, "data")
assert(os.rename(a, b))
assert(os.exists(b))
os.remove(b)
}append_file
append_file: (path: &String, content: &String) -> Bool追加写入(不开句柄的便捷函数)。文件不存在时创建。
返回:成功返回 true。错误:无权限时抛出 E6007。
这是
std.io.append_file的同名同类接口,两个模块都提供,行为一致。
use std.assert
use std.io
use std.os
main: () -> Void = {
p = "__yx_doc_os_append.txt"
io.write_file(p, "a")
os.append_file(p, "b")
assert(io.read_file(p) == "ab")
os.remove(p)
}环境变量
get_env
get_env: (name: &String) -> String读取环境变量。
返回:变量值;变量不存在时返回空串(不报错)。因此无法区分“未设置”与“设置为空串”。
use std.assert
use std.os
use std.string
main: () -> Void = {
// PATH 在主流平台必然存在
path = os.get_env("PATH")
assert(string.len(path) > 0)
// 不存在的变量返回空串
assert(string.is_empty(os.get_env("__YX_DEFINITELY_MISSING__")))
}set_env
set_env: (name: &String, value: &String) -> Void设置环境变量(影响当前进程)。
use std.assert
use std.os
main: () -> Void = {
os.set_env("__YX_DOC_ENV", "hello")
assert(os.get_env("__YX_DOC_ENV") == "hello")
}进程与工作目录
args
args: () -> String返回命令行参数。
返回:所有 argv 以 \n 连接的单个字符串(不是 List)。首项是程序自身路径。
use std.assert
use std.os
use std.string
main: () -> Void = {
argv = os.args()
assert(string.len(argv) > 0)
}chdir
chdir: (path: &String) -> Bool切换当前工作目录。
返回:成功返回 true。错误:目录不存在时抛出 E6007。
use std.assert
use std.os
main: () -> Void = {
before = os.getcwd()
assert(os.chdir(".."))
assert(os.chdir(before)) // 切回
assert(os.getcwd() == before)
}getcwd
getcwd: () -> String返回当前工作目录的绝对路径。
错误:无法获取时抛出 E6007。
use std.assert
use std.os
use std.string
main: () -> Void = {
cwd = os.getcwd()
assert(string.len(cwd) > 0)
}