px普贤教程PuXian
普贤教程 › 基础教程

文件与 IO

文件操作分两层:高层是一行搞定的 read_file / write_file,底层是 open / read / write / close。日常用高层,处理二进制或流才用底层。

高层 API

函数作用失败时
read_file(path)读全文为字符串运行时错误
read_file_opt(path)读全文返回 Err
write_file(path, text)覆盖写入运行时错误
append_file(path, text)追加写入运行时错误
write_bytes(path, b)写二进制运行时错误
exists(path)是否存在返回 bool
px
write_file("/tmp/px_demo.txt", "第一行\n第二行\n")
append_file("/tmp/px_demo.txt", "第三行\n")

var text = read_file("/tmp/px_demo.txt")
print(text)

var lines = split(trim(text), "\n")
print("共 " + str(len(lines)) + " 行")
text
第一行
第二行
第三行

共 3 行

安全读取

处理"文件可能不存在"的场景,用 read_file_opt,不要先 exists 再读——两步之间有竞态:

px
def safe_read(path):
    var r = read_file_opt(path)
    if r.is_err():
        return Err("读不到 " + path + ":" + r.err())
    return Ok(r.ok())

print(safe_read("/tmp/nope_xyz.txt").err())
text
读不到 /tmp/nope_xyz.txt:io: 读取文件失败 /tmp/nope_xyz.txt: No such file or directory (os error 2)

底层:open / read / write / close

px
var f = open("/tmp/px_low.txt", "w")
write(f, "hello\n")
close(f)

var g = open("/tmp/px_low.txt", "r")
var chunk = read(g, 100)
close(g)
print(bytes_to_str(chunk))
text
hello
read 返回 bytes底层 read 给的是字节串,转文本用 bytes_to_str()。write 接受字符串;写二进制用 write(f, 字节串) 或 write_bytes。
用完要 close没有 with 语法,句柄必须显式关。长驻进程里忘记 close 会耗尽文件描述符,表现是"跑几小时后突然打不开文件"。

读标准输入、写标准输出

PuXian 写 CGI 风格的接口时,靠 /dev/stdin 与 /dev/stdout 收发:

px
# 读请求体(二进制安全)
var body_in = read_file_opt("/dev/stdin")
var body = ""
if body_in.is_ok():
    body = body_in.ok()

# 写响应(必须分块写,见部署一章)
var out = open("/dev/stdout", "w")
write(out, "Status: 200 OK\n")
write(out, "Content-Type: application/json\n")
write(out, "\n")
write(out, json_stringify({"ok": true, "len": len(body)}))
close(out)
二进制不要用 read_fileread_file 遇到 NUL 字节会截断,读图片、zip、编译产物一律用 read_file_opt(或底层 open + read)。

遍历目录

目录相关工具在标准库 path 与生态包 dirs / glob 里:

px
import std.path
print(path_join("/data/www", "px_dzty_club"))
text
/data/www/px_dzty_club

日志文件写法

px
def log_line(path, msg):
    var ts = str(now_ms())
    append_file(path, ts + "\t" + msg + "\n")

log_line("/tmp/px_app.log", "started")
log_line("/tmp/px_app.log", "tick")
print(read_file("/tmp/px_app.log"))
text
1793869xxx	started
1793869xxx	tick
日志轮转append 写日志不控大小,长期运行要用 logrotate 或自己在文件超过 N MB 时改名。别让日志把磁盘写满——这是最常见的事故之一。

文件操作的常见失败

现象原因
写入失败父目录不存在、无权限、磁盘满
读到空内容用了 read_file 读二进制,遇 NUL 截断
读取内容少一截read(f, n) 的 n 给小了,需要循环读
句柄泄漏异常路径没有 close