跳到主要内容

基础I/O操作

I/O(输入/输出)操作是程序与外部世界交互的基础。本章将详细介绍 Sii 2 中的文件操作、标准输入输出、环境变量等 I/O 功能。

I/O 操作概述

Sii 2 通过不同的命名空间提供 I/O 操作功能:

  • 标准输入输出:通过 sii.io 命名空间(sii.io.print(), sii.io.readLine() 等)
  • 文件操作:通过 sii 命名空间(sii.readText(), sii.writeText() 等)
  • 目录操作:通过 sii 命名空间(sii.mkdirs(), sii.pathJoin() 等)
  • 环境变量:通过 sii 命名空间(sii.env()

标准输入输出

输出操作

sii.io.print()

print() 函数用于向标准输出打印内容:

// 打印字符串
sii.io.print("Hello, World!");

// 打印变量
let name: string = "Alice";
sii.io.print(name);

// 打印多个值(通过字符串拼接)
let age: int = 25;
sii.io.print("Name: " + name + ", Age: " + string(age));

格式化输出

let name: string = "Bob";
let score: int = 95;
let percentage: singlef = 95.5;

// 基本格式化
sii.io.print("Student: " + name);
sii.io.print("Score: " + string(score));
sii.io.print("Percentage: " + string(percentage));

输入操作

Sii 2 提供了多种输入函数来获取用户输入:

sii.io.readLine()

读取一行字符串输入:

// 获取字符串输入
let name: string = sii.io.readLine();
sii.io.print("Hello, " + name + "!");

sii.io.readInt()

读取整数输入:

// 获取整数输入
let age: int = sii.io.readInt();
sii.io.print("Age: " + string(age));

sii.io.readSinglef()

读取单精度浮点数输入:

// 获取单精度浮点数输入
let price: singlef = sii.io.readSinglef();
sii.io.print("Price: " + string(price));

sii.io.readMultif()

读取多精度浮点数输入:

// 获取多精度浮点数输入
let value: multif = sii.io.readMultif();
sii.io.print("Value: " + string(value));

输入函数说明

  • sii.io.readLine() - 返回 string 类型
  • sii.io.readInt() - 返回 int 类型
  • sii.io.readSinglef() - 返回 singlef 类型
  • sii.io.readMultif() - 返回 multif 类型

文件操作

读取文件

sii.readText()

读取文本文件内容:

// 读取文件
let content: string = sii.readText("./data.txt");
sii.io.print("File content: " + content);

错误处理

func readFileSafely(path: string): string | void {
if (!sii.exists(path)) {
sii.io.print("Error: File not found: " + path);
back;
}
back sii.readText(path);
}

// 使用
let content: string | void = readFileSafely("./config.json");
if (typeins(content) == "string") {
let text: string = content as string;
sii.io.print(text);
}

写入文件

sii.writeText()

将内容写入文件:

// 写入文件
sii.writeText("./output.txt", "Hello, Sii 2!");

// 写入多行内容
let content: string = "Line 1\nLine 2\nLine 3";
sii.writeText("./multiline.txt", content);

自动创建目录

writeText() 会自动创建不存在的父目录:

// 如果 ./logs/ 不存在,会自动创建
sii.writeText("./logs/app.log", "Log message");

检查文件存在

sii.exists()

检查文件或目录是否存在:

let filePath: string = "./data.txt";
if (sii.exists(filePath)) {
sii.io.print("File exists");
let content: string = sii.readText(filePath);
} else {
sii.io.print("File does not exist");
}

目录操作

sii.mkdirs()

创建目录(包括所有父目录):

// 创建单个目录
sii.mkdirs("./logs");

// 创建嵌套目录
sii.mkdirs("./data/2024/12");

检查目录存在

let dirPath: string = "./data";
if (!sii.exists(dirPath)) {
sii.mkdirs(dirPath);
sii.io.print("Directory created");
}

路径操作

sii.pathJoin()

拼接路径:

// 拼接路径
let basePath: string = "./data";
let fileName: string = "config.json";
let fullPath: string = sii.pathJoin(basePath, fileName);
// 结果: ./data/config.json

// 多级路径
let path1: string = "/usr";
let path2: string = "local";
let path3: string = "bin";
let fullPath: string = sii.pathJoin(sii.pathJoin(path1, path2), path3);
// 结果: /usr/local/bin

sii.cwd()

获取当前工作目录:

let currentDir: string = sii.cwd();
sii.io.print("Current directory: " + currentDir);

环境变量

sii.env()

读取环境变量:

// 读取环境变量
let homeDir: string = sii.env("HOME");
let path: string = sii.env("PATH");
let user: string = sii.env("USER");

sii.io.print("Home directory: " + homeDir);
sii.io.print("User: " + user);

环境变量使用示例

func getConfigPath(): string {
let configDir: string = sii.env("CONFIG_DIR");
if (configDir.length() == 0) {
configDir = "./config"; // 默认值
}
back sii.pathJoin(configDir, "app.json");
}

JSON 操作

sii.jsonParse()

解析 JSON 字符串:

let jsonString: string = '{"name": "Alice", "age": 25}';
let data: obj = sii.jsonParse(jsonString);

// 访问解析后的数据
let name: string = data.name;
let age: int = data.age;

sii.jsonStringify()

将对象转换为 JSON 字符串:

crob person = new Object();
person.name = "Bob";
person.age = 30;

let jsonString: string = sii.jsonStringify(person);
sii.io.print(jsonString);
// 输出: {"name":"Bob","age":30}

文件操作完整示例

示例 1:配置文件读写

func loadConfig(): obj | void {
let configPath: string = "./config.json";

if (!sii.exists(configPath)) {
sii.warn("Config file not found, creating default");
crob defaultConfig = new Object();
defaultConfig.host = "localhost";
defaultConfig.port = 8080;
defaultConfig.debug = false;

let jsonString: string = sii.jsonStringify(defaultConfig);
sii.writeText(configPath, jsonString);
back defaultConfig;
}

let content: string = sii.readText(configPath);
let config: obj = sii.jsonParse(content);
back config;
}

func saveConfig(config: obj): void {
let configPath: string = "./config.json";
let jsonString: string = sii.jsonStringify(config);
sii.writeText(configPath, jsonString);
sii.io.print("Config saved");
}

示例 2:日志系统

func writeLog(message: string): void {
let logDir: string = "./logs";
if (!sii.exists(logDir)) {
sii.mkdirs(logDir);
}

let timestamp: string = string(sii.now());
let logFile: string = sii.pathJoin(logDir, "app.log");

let logEntry: string = "[" + timestamp + "] " + message + "\n";

// 追加到日志文件(简化版,实际可能需要读取后追加)
let existingContent: string = if (sii.exists(logFile)) { sii.readText(logFile) } else { "" };
let newContent: string = existingContent + logEntry;
sii.writeText(logFile, newContent);
}

示例 3:文件复制

func copyFile(sourcePath: string, destPath: string): bool {
// 检查源文件
if (!sii.exists(sourcePath)) {
sii.error("Source file not found: " + sourcePath);
back false;
}

// 读取源文件
let content: string = sii.readText(sourcePath);

// 确保目标目录存在
let destDir: string = sii.pathJoin(destPath, "..");
if (!sii.exists(destDir)) {
sii.mkdirs(destDir);
}

// 写入目标文件
sii.writeText(destPath, content);

// 验证复制
if (sii.exists(destPath)) {
sii.log("File copied successfully");
back true;
} else {
sii.error("Failed to copy file");
back false;
}
}

I/O 操作最佳实践

1. 错误处理

始终检查文件操作是否成功:

func safeReadFile(path: string): string | void {
if (!sii.exists(path)) {
sii.error("File not found: " + path);
back;
}

let content: string = sii.readText(path);
back content;
}

2. 路径处理

使用 pathJoin() 而不是字符串拼接:

// 好的做法
let path: string = sii.pathJoin("./data", "config.json");

// 不好的做法
let path: string = "./data" + "/" + "config.json"; // 跨平台可能有问题

3. 资源管理

及时处理文件,避免资源泄漏:

func processFile(path: string): void {
let content: string = sii.readText(path);
// 立即处理内容
processContent(content);
// 不需要显式关闭,Sii 2 会自动管理
}

4. 大文件处理

对于大文件,考虑分块处理:

// 注意:Sii 2 的 readText 可能一次性读取整个文件
// 对于大文件,可能需要其他处理方式
func processLargeFile(path: string): void {
let content: string = sii.readText(path);
// 处理内容...
}

跨平台注意事项

路径分隔符

不同操作系统使用不同的路径分隔符:

  • Windows: \
  • Unix/Linux/macOS: /

使用 pathJoin() 可以自动处理这些差异。

文件权限

在某些系统上,文件权限可能影响操作:

func checkFileAccess(path: string): bool {
if (!sii.exists(path)) {
back false;
}

// 尝试读取以检查权限
let content: string = sii.readText(path);
back true;
}

小结

本章介绍了 Sii 2 中的基础 I/O 操作:

  • 标准输入输出sii.io.print(), sii.io.readLine(), sii.io.readInt()
  • 文件操作sii.readText(), sii.writeText(), sii.exists()
  • 目录操作sii.mkdirs(), sii.pathJoin(), sii.cwd()
  • 环境变量sii.env()
  • JSON 操作sii.jsonParse(), sii.jsonStringify()
  • 最佳实践:错误处理、路径处理、资源管理

下一章我们将学习网络编程,了解如何构建 HTTP 客户端和服务器。