编程语言语言运行时标准库垃圾回收并发编程【免费下载链接】cangjie_runtime仓颉编程语言运行时与标准库。项目地址https://gitcode.com/Cangjie/cangjie_runtime点击查看免费下载std.fs 是仓颉标准库中负责文件系统操作的核心包为开发者提供文件、文件夹、路径与文件元数据的完整操作能力。本文以仓库内 fs 包概述文档 为骨架结合 stdlib/libs/std/fs 下的源码实现与各 API 参考文档系统讲解 Path 路径处理、顶层文件系统函数、File 流式读写、Directory 目录遍历、硬链接/符号链接以及 FileInfo 元数据查询等内容。读完本文你将能够熟练使用 std.fs 完成文件与目录的创建、拷贝、重命名、删除、读写和权限查询等日常开发任务。std.fs 包概览与能力边界fsfile system包提供对文件、文件夹、路径、文件元数据信息的一些操作函数。整个包的 API 构成如下类别成员能力顶层函数canonicalize / copy / exists / rename / remove / removeIfExists路径规范化、拷贝、存在性判断、重命名、删除类Directory、File、HardLink、SymbolicLink目录操作、文件读写、硬链接与符号链接枚举OpenMode文件打开模式结构体FileDescriptor、FileInfo、Path文件句柄、元数据、路径异常类FSException文件系统异常权限与平台限制注意std.fs 仅能对有相应权限的文件、目录或其他相关信息做出操作。例如iOS由于沙盒机制的原因系统仅允许对应用的 Documents、Library、tmp 等目录下的文件和文件夹进行操作。在撰写业务代码时应当始终考虑目标平台的权限模型Linux/macOS 下权限判断基于 POSIX 文件权限位而 Windows 下部分权限语义不同详见下文 FileInfo 权限 API 的逐项说明。此外所有涉及路径的 API 都会对空路径或包含字符串结束符\0的路径抛出 IllegalArgumentException具体实现在PathValidator.throwIfEmptyOrContainsNullByte见 stdlib/libs/std/fs/utils.cj。Path路径的表示、解析与规范化Path 是 std.fs 中最基础的结构体几乎所有其他 API 都接受Path或String两种形式的路径参数。从源码看Path内部仅封装一个原始路径字符串_rawPath见 stdlib/libs/std/fs/path.cjpublic struct Path : EquatablePath Hashable ToString { public static const Separator: String PATH_SEPARATOR public static const ListSeparator: String PATH_LISTSEPARATOR public init(rawPath: String) }Path构造时不检查路径字符串是否合法支持绝对路径与相对路径。路径的字符串最大支持 4096 个字节包括结束符\0Windows 平台已支持 DOS 设备路径和 UNC 路径长度限制跟随系统。路径分隔符常量常量含义Windows非 WindowsPath.Separator路径分隔符用于分隔多级目录\/Path.ListSeparator路径列表分隔符用于分隔路径列表中的不同路径;:源码中这两个常量由条件编译宏决定见 stdlib/libs/std/fs/path.cjWhen[os ! Windows] const PATH_SEPARATOR / When[os Windows] const PATH_SEPARATOR \\ When[os ! Windows] const PATH_LISTSEPARATOR : When[os Windows] const PATH_LISTSEPARATOR ;路径组成部分属性Path提供以下只读属性用于拆分路径属性说明典型示例parent父路径。以最后一个有效文件分隔符末尾分隔符会被忽略为分界parent 保留表示根目录的分隔符无父目录时返回空Path/a/b/c→/a/b/a→//→/fileName文件名含扩展名。Windows 下不包括卷名部分./NewFile.txt→NewFile.txt/a/b/→bfileNameWithoutExtension文件名不含扩展名按最后一个.划分./a.b.c→a.b./.gitignore→extensionName文件扩展名无扩展名时返回空字符串./NewFile.txt→txt./noextension→值得注意的边界行为文档与示例 path_samples.md 均有演示对于./和.fileName返回.而extensionName为空对于123.fileNameWithoutExtension返回123。parent属性不会访问文件系统也不会消除特殊名称因此不会消除..等组件——例如/a/./../b的parent仍是/a/./..若需要语义化的解析应结合normalize()或canonicalize()。常用方法isAbsolute()/isRelative()判断绝对/相对路径Unix 中以/开头为绝对路径二者结果互反。isEmpty()判断是否为空路径。join(path: Path | String)在当前路径后拼接另一路径。仅做字符串拼接不处理..等路径遍历组件参数为绝对路径时抛出 FSException。例如Path(/home/user).join(documents)得到/home/user/documents。normalize()将路径字符串按规则规范化仅做字符串解析不做任何 IO 操作。规则包括合并连续分隔符、删除末尾分隔符、删除.元素、删除..及其前面的非..元素、删除根路径开始的..、相对路径保留开头的../、空结果返回Path(.)。hashCode()/toString()哈希值与路径字符串。operator 判等时先对两个 Path 做规范化规则同normalize()规范化后字符串相等则视为同一路径。canonicalize获取真实绝对路径与纯字符串处理的normalize()不同顶层函数 canonicalize 会实际访问文件系统所有的中间引用.、..和软链接都会被解析处理返回绝对路径形式的规范化路径。例如路径/foo/test/../test/bar.txt会被规范化为/foo/test/bar.txtUNC 路径下的软链接无法被规范化。从源码看stdlib/libs/std/fs/path.cjcanonicalize先校验路径合法性然后检查路径是否存在public func canonicalize(path: String): Path { PathValidator.throwIfEmptyOrContainsNullByte(path, path, true) if (!exists(path)) { throw FSException(Failed to canonicalize path ${path}: path does not exist or permission denied.) } return Path(processPathHeader(path, Path.canonicalizePath(path))) }由此可归纳出canonicalize的两个关键异常场景路径不存在或无法规范化时抛出FSException路径为空或包含字符串结束符时抛出IllegalArgumentException。典型用法见 fs_package_funcs.mdimport std.fs.* main(): Unit { removeIfExists(./test/../test_canonicalize_path.txt, recursive: true) let testPath Path(./test/../test_canonicalize_path.txt) Directory.create(testPath, recursive: true) let canonicalPath canonicalize(testPath) println(Original path: ${testPath}) println(Canonical path: ${canonicalPath}) removeIfExists(./test/../test_canonicalize_path.txt, recursive: true) }可能的运行结果示例路径下Original path: ./test/../test_canonicalize_path.txt Canonical path: /home/user/test/test_canonicalize_path.txt安全建议由于join不做路径遍历防护文档明确提示如需安全验证请先调用canonicalize并检查路径范围。这在处理用户输入路径时尤为重要。顶层文件系统函数std.fs 在包级别提供了 6 组文件系统函数每组都同时提供Path与String两个重载语义完全一致。它们定义在 stdlib/libs/std/fs/common.cj其String重载最终都会转换为Path形式再委托处理。exists存在性判断public func exists(path: Path | String): Bool判断目标地址是否存在底层调用原生接口CJ_FS_Exists见 stdlib/libs/std/fs/common.cj。路径为空或含空字符时抛出IllegalArgumentException。典型用法import std.fs.* main(): Unit { removeIfExists(./test_exists_path.txt, recursive: true) let notExist exists(Path(./test_exists_path.txt)) println(File exists before creation: ${notExist}) var data: ArrayByte [69, 120, 105, 115, 116, 115] // Exists File.writeTo(./test_exists_path.txt, data) let exist exists(Path(./test_exists_path.txt)) println(File exists after creation: ${exist}) removeIfExists(./test_exists_path.txt, recursive: true) }运行结果File exists before creation: false、File exists after creation: true。copy拷贝文件或目录public func copy(sourcePath: Path | String, to!: Path | String, overwrite!: Bool false): Unit当前支持的拷贝类型包括目录Directory、常规文件Regular file、符号链接SymbolicLink。overwrite默认为false若目标位置已存在且未开启覆盖模式抛出 FSException。从源码实现看stdlib/libs/std/fs/common.cjcopy的完整行为如下常规文件目标存在且overwrite false时抛异常overwrite true时要求目标也必须是常规文件否则抛异常随后调用File.copy。目录目标存在且overwrite false时抛异常覆盖模式下目标必须是目录随后调用Directory.copy。目录拷贝采用队列驱动的广度优先遍历copyDirectory/walkAndCopy见 stdlib/libs/std/fs/directory.cj逐个创建子目录并拷贝文件。符号链接目标存在且overwrite true时会先删除旧目标再读取链接目标并重新创建链接。源与目标为同一路径时抛出FSExceptionrefer to the same path。其他文件类型如设备文件抛出 unsupported file type 异常。说明若目标位置已存在且开启覆盖模式要求源路径与目标路径对应的类型保持一致例如源路径为目录类型则目标路径也需为目录类型不可为文件类型类型不一致时将抛出 FSException 异常。示例见 fs_package_funcs.mdimport std.fs.* main(): Unit { removeIfExists(./test_copy_source.txt, recursive: true) removeIfExists(./test_copy_target.txt, recursive: true) var data: ArrayByte [67, 111, 112, 121] // Copy File.writeTo(./test_copy_source.txt, data) copy(Path(./test_copy_source.txt), to: Path(./test_copy_target.txt), overwrite: false) if (exists(./test_copy_target.txt)) { let content File.readFrom(./test_copy_target.txt) println(File copied successfully, content: ${content}) } else { println(File copy failed) } removeIfExists(./test_copy_source.txt, recursive: true) removeIfExists(./test_copy_target.txt, recursive: true) }运行结果File copied successfully, content: [67, 111, 112, 121]。rename重命名文件或目录public func rename(sourcePath: Path | String, to!: Path | String, overwrite!: Bool false): Unit将sourcePath指定的文件或目录重命名为to给定的名称。sourcePath必须是现有路径如果to已存在则行为由overwrite决定为true时先删除现有文件或目录再执行重命名为false时抛出异常。源码还做了同路径检查与存在性预检stdlib/libs/std/fs/common.cjif (Path(sourcePath) Path(to)) { throw FSException(Invalid argument: sourcePath and to refer to the same path ...) } if (exists(to) !overwrite) { throw FSException(Cannot rename to ${to}: destination path already exists and overwrite is false.) }注意当overwrite为true时rename的一个隐含行为是删除目标位置的原有文件或目录如果目标位置是目录将会递归删除目录内的所有内容需要谨慎使用。底层通过原生接口CJ_FS_Rename调用操作系统 rename操作系统执行失败时抛出 FSException。remove 与 removeIfExists删除文件或目录public func remove(path: Path | String, recursive!: Bool false): Unit public func removeIfExists(path: Path | String, recursive!: Bool false): Boolremove删除文件或目录。目标是文件夹时可通过recursive选择是否递归删除默认false。如果指定目录不存在或删除失败抛出 FSException。底层调用CJ_FS_Remove并透传递归标志stdlib/libs/std/fs/common.cj。removeIfExists先判断目标是否存在存在则执行remove并返回true不存在返回false。该函数是 std.fs 示例代码中最常用的清理残留工具几乎所有示例都以removeIfExists(...)开头避免上次运行残留导致创建失败。两个函数都遵循删除失败抛 FSException路径为空或含空字符抛 IllegalArgumentException。OpenMode文件打开模式OpenMode 是File构造时指定的读写权限枚举。源码中的注释直接对应 POSIX 打开标志stdlib/libs/std/fs/file.cj枚举值对应系统打开标志行为ReadO_RDONLY只读打开文件不存在时抛出 FSExceptionWriteO_WRONLY \| O_CREAT \| O_TRUNC只写打开文件存在则截断为零字节不存在则创建AppendO_WRONLY \| O_CREAT \| O_APPEND追加写入文件不存在则创建ReadWriteO_RDWR \| O_CREAT读写打开文件不存在则创建注意ReadWrite 模式不会使文件被截断为零字节大小。OpenMode实现了ToString与EquatableOpenMode提供toString()、operator 、operator !toString()返回枚举名Read/Write/Append/ReadWrite。File文件的打开、读写与截断File 是文件操作的核心类声明如下public class File : Resource IOStream Seekable { public init(path: String, mode: OpenMode) public init(path: Path, mode: OpenMode) }父类型为 Resource、IOStream 与 Seekable。从源码看stdlib/libs/std/fs/file.cjFile对象会默认打开对应的文件构造时检查父目录是否存在并通过openFile()依据_openMode完成系统调用。注意创建的File对象会默认打开对应的文件当使用结束后需要及时调用close()关闭文件否则会造成资源泄露。File类还实现了~init()析构函数见 stdlib/libs/std/fs/file.cj会在对象销毁时自动关闭底层句柄但这不能替代显式close()的最佳实践。File 的静态便捷方法静态方法签名行为File.createcreate(path: Path/String): File创建指定路径文件并返回只写模式的 File 实例上级目录不存在或文件已存在时抛 FSExceptionFile.readFromreadFrom(path: Path/String): ArrayByte一次性读取文件全部内容以字节数组返回File.writeTowriteTo(path: Path/String, buffer: ArrayByte): Unit以覆盖方式写入文件存在则先截断为零字节不存在则创建File.appendToappendTo(path: Path/String, buffer: ArrayByte): Unit以追加方式写入文件不存在则创建File.createTempcreateTemp(directoryPath: Path/String): File在指定目录下创建临时文件文件名为tmpFileXXXXXX形式不使用的临时文件应手动删除File 的属性与实例方法属性fileDescriptor: FileDescriptor获取文件描述符文件句柄信息。info: FileInfo获取文件元数据信息。length: Int64获取文件头至文件尾的数据字节数通过getsize()实时获取。实例方法方法说明canRead()/canWrite()判断当前 File 对象是否可读/可写由创建时的 openMode 决定文件关闭后返回 falseisClosed()/close()判断是否已关闭 / 关闭文件read(buffer: ArrayByte): Int64从文件读出数据到 buffer返回读取字节数文件读完返回 0buffer 为空抛 IllegalArgumentExceptionwrite(buffer: ArrayByte)将 buffer 数据写入文件buffer 为空直接返回写入失败、只写部分、文件已关闭或不可写时抛 FSExceptionseek(sp: SeekPosition): Int64将光标跳转到指定位置返回文件头到新位置的偏移量字节。位置不能位于文件头之前可超过文件末尾但最大偏移量不能超过文件系统允许的最大值一般约为最大文件大小减 4096 字节setLength(length: Int64)将文件截断为指定长度length 大于当前长度时用 0 填充不改变光标位置负数抛 IllegalArgumentExceptionflush()将缓冲区数据写入流。由于File不存在缓冲区该函数没有具体作用源码中为空实现见 stdlib/libs/std/fs/file.cjFile 读写完整示例综合示例见 fs_samples/file_samples.md覆盖四种打开模式与 seek/setLength 组合import std.fs.* import std.io.* main() { let filePath: Path Path(./tempFile.txt) removeIfExists(filePath) // 只写模式写入三遍 123456789\n var file: File File(filePath, Write) let bytes: ArrayByte 123456789\n.toArray() for (_ in 0..3) { file.write(bytes) } file.close() // 追加模式写入 abcdefghi\n file File(filePath, Append) file.write(abcdefghi\n.toArray()) file.close() // 只读模式从偏移 10 处与文件末尾各读 10 字节 file File(filePath, Read) let readBuffer: ArrayByte ArrayByte(10, repeat: 0) file.seek(SeekPosition.Begin(10)) file.read(readBuffer) println(第 10 字节之后的 10 个字节: ${String.fromUtf8(readBuffer)}) file.seek(SeekPosition.End(-10)) file.read(readBuffer) println(文件末尾的 10 个字节: ${String.fromUtf8(readBuffer)}) file.close() // 读写模式截断为空文件再写入新内容 file File(filePath, ReadWrite) file.setLength(0) file.write(文件已被截断为空文件.toArray()) file.seek(SeekPosition.Begin(0)) let allBytes: ArrayByte readToEnd(file) file.close() println(截断后新写入的内容: ${String.fromUtf8(allBytes)}) removeIfExists(filePath) return 0 }运行结果文件创建成功: tempFile.txt 第 10 字节之后的 10 个字节: 123456789 文件末尾的 10 个字节: abcdefghi 截断后新写入的内容: 文件已被截断为空文件SeekPosition位于 std.io 包支持Begin(offset)、Current(offset)、End(offset)三种定位方式示例中SeekPosition.End(-10)表示从文件末尾向前 10 字节。Directory目录的创建、遍历与拷贝Directory 对应文件系统中的目录提供创建、移动、复制、删除、查询属性以及遍历目录等能力。说明非法路径指以下情况之一路径中包含非法字符如空格、制表符、换行符等路径中包含不合法的特殊字符、控制字符路径中包含不存在的目录或文件路径中包含无法访问的目录或文件如权限不足或被锁定。输入路径时应避免非法字符确保路径合法性。创建与临时目录Directory.create(path: Path/String, recursive!: Bool false)创建目录。recursive true时逐级创建路径中不存在的中间目录目录已存在、非递归创建时中间目录不存在、权限不足等都会抛 FSException。从源码看stdlib/libs/std/fs/directory.cj创建前会先去掉尾部分隔符并检查是否已存在。Directory.createTemp(directoryPath: Path/String): Path在指定目录下创建临时目录返回其路径。底层会先对目录做canonicalize并调用原生CJ_FS_CreateTempDir。判断与遍历Directory.isEmpty(path): Bool判断指定目录是否为空路径不存在、路径不是目录或底层接口出错时抛 FSException。Directory.readFrom(path): ArrayFileInfo读取目录下所有子项目的信息返回ArrayFileInfo。子项目在数组中的顺序取决于文件在系统中的排序。源码实现是内部调用walk收集所有条目stdlib/libs/std/fs/directory.cj。Directory.walk(path, f: (FileInfo) - Bool)遍历指定目录下的子项目非递归不包含子目录的子项目对每个子项目执行回调函数。退出条件为遍历结束或回调函数返回false。遍历顺序取决于文件在系统中的排序。底层通过目录句柄逐项读取CJ_FS_GetDirHandleAndFirstFile/CJ_FS_ReadDirHandle见 stdlib/libs/std/fs/directory.cj并在 finally 中关闭句柄。walk回调式遍历的典型用法按名称过滤并删除文件import std.fs.* main(): Unit { removeIfExists(./test_walk_directory, recursive: true) let path Path(./test_walk_directory) Directory.create(path, recursive: true) File.create(./test_walk_directory/abc.txt) File.create(./test_walk_directory/bcd.txt) File.create(./test_walk_directory/cde.txt) File.create(./test_walk_directory/def.txt) // 把名字中带 b 的文件删除 Directory.walk(path) { fileinfo: FileInfo if (fileinfo.name.contains(b)) { remove(fileinfo.path) } return true // 返回 false 会提前终止遍历 } println(查询是否存在 abc.txt 这个文件: ${exists(./test_walk_directory/abc.txt)}) removeIfExists(./test_walk_directory, recursive: true) }运行结果查询是否存在 abc.txt 这个文件: false。Directory 组合操作示例directory_samples.md 演示了目录创建、临时目录、重命名移动与拷贝的完整流程import std.fs.* main() { let testDirPath: Path Path(./testDir) let subDirPath: Path Path(./testDir/subDir) removeIfExists(testDirPath, recursive: true) // 递归创建目录不存在的父目录会一并创建 Directory.create(subDirPath, recursive: true) println(递归创建目录成功: ${subDirPath}) // 创建临时目录 let tempDirPath: Path Directory.createTemp(testDirPath) // 移动并重命名subDir - tempDir/subDir_new let newSubDirPath: Path tempDirPath.join(subDir_new) rename(subDirPath, to: newSubDirPath) // 拷贝回原位置 copy(newSubDirPath, to: subDirPath, overwrite: false) removeIfExists(testDirPath, recursive: true) return 0 }链接HardLink 与 SymbolicLinkHardLink 硬链接HardLink 提供硬链接相关接口仅有一个静态方法public static func create(link: Path | String, to!: Path | String): Unit创建一个新的硬链接到现有路径。如果新路径已存在则不会覆盖源码实现在 stdlib/libs/std/fs/hardlink.cj底层调用CJ_FS_CreateHardLink。参数路径为空或含空字符抛 IllegalArgumentException创建失败抛 FSException。SymbolicLink 符号链接SymbolicLink 提供符号链接接口create(link, to!)创建符号链接到现有路径。readFrom(path, recursive! false): Path获取符号链接的目标。recursive true时跟踪指向最终目标的链接并返回目标的全路径false时读取当前目标链接并返回。说明在 Windows 上创建一个目标不存在的符号链接时会创建一个文件符号链接如果目标路径后来被创建为目录则符号链接将不起作用。符号链接的创建与读取示例完整代码见 fs_package_classes.mdimport std.fs.* main(): Unit { removeIfExists(./test_symlink_source.txt, recursive: true) removeIfExists(./test_symlink_target.txt, recursive: true) var data: ArrayByte [83, 121, 109, 98, 111, 108, 105, 99, 76, 105, 110, 107] // SymbolicLink File.writeTo(./test_symlink_source.txt, data) SymbolicLink.create(./test_symlink_target.txt, to: ./test_symlink_source.txt) let targetPath SymbolicLink.readFrom(Path(./test_symlink_target.txt)) println(Symbolic link target: ${targetPath}) removeIfExists(./test_symlink_source.txt, recursive: true) removeIfExists(./test_symlink_target.txt, recursive: true) }运行结果Symbolic link target: ./test_symlink_source.txt。FileInfo文件元数据与权限FileInfo 对应文件系统中的文件元数据文件名、大小、创建时间、修改时间、访问时间、权限、所有者等。说明FileInfo的底层实现没有直接缓存文件属性每次通过FileInfo的 API 都是现场获取最新属性。因此对于同一FileInfo实例如果两次获取属性期间文件实体被其他用户或进程修改或替换后一次获取的可能不是期望的属性。有特殊需求时应通过设置文件权限或加锁来保证。FileInfo可通过FileInfo(path: Path | String)构造或从File.info属性、Directory.readFrom/walk回调中获得。属性属性类型说明pathPath当前文件路径nameString文件名或目录名等价于this.path.fileNameparentDirectoryOptionFileInfo父级目录元数据有父级返回Some(v)否则返回NonesizeInt64文件大小对文件表示单个文件占用磁盘空间大小对目录表示目录内所有文件占用磁盘空间大小creationTime/lastAccessTime/lastModificationTimeDateTime创建时间 / 最后访问时间 / 最后修改时间权限判断与设置方法说明canRead()判断当前用户是否有读取权限文件为读目录为浏览。Windows 下固定返回 true不生效canWrite()判断是否有写入权限文件为写目录为删除/移动/创建内部文件。Windows 下目录权限固定 truecanExecute()判断是否有执行权限文件为执行目录为进入。Windows 下由文件扩展名决定目录固定 trueisReadOnly()判断是否只读。Windows 下目录的删除修改权限固定返回 falseisDirectory()/isRegular()/isSymbolicLink()/isHidden()类型判断目录 / 普通文件 / 软链接 / 隐藏文件setReadable(readable)/setWritable(writable)/setExecutable(executable)设置文件所有者对应权限返回操作是否成功Bool。Linux/macOS 下正常生效Windows 下部分固定返回 false说明权限设置类方法在 Linux/macOS 下可正常使用但如果调用期间FileInfo对应的文件实体被其他用户或进程修改可能因竞争条件Race Condition导致修改不生效以特权用户运行的进程可能绕过此权限设置。FileInfo 相等性operator func (other: FileInfo): Bool用于判断两个FileInfo是否对应同一文件而非内容相同。示例中两个写入相同数据的不同文件比较结果为false。FileDescriptor 与 FSExceptionFileDescriptor 文件句柄FileDescriptor 用于获取文件句柄信息唯一的公开属性是fileHandle: IntNative。文件句柄是操作系统为跟踪文件分配的数据结构在 Unix/Linux 中通常是非负整数文件描述符编号在 Windows 中通常是指向文件对象的指针。可从File.fileDescriptor获取见 stdlib/libs/std/fs/file.cj结构体内部以InvalidHandle初始化文件未打开时为无效句柄。FSException 异常体系FSException 是文件流异常类继承自 IO 流异常类 IOException提供两个构造函数FSException()无提示信息与FSException(message: String)带错误信息。std.fs 中几乎所有文件系统操作失败都会抛出该异常例如路径不存在、权限不足、类型不一致、底层系统调用失败、文件已关闭或不可读写等。源码实现见 stdlib/libs/std/fs/fs_exception.cj。实战组合一个完整的文件管理任务将前文能力组合起来可以实现典型的创建目录 → 写入文件 → 校验 → 清理任务参考 path_samples.md 中的通过 Path 创建文件与目录import std.fs.* main() { let currentDirPath: Path Path(./) let dirPath: Path currentDirPath.join(tempDir) let filePath: Path dirPath.join(tempFile.txt) // 清理上次运行可能残留的目录 removeIfExists(dirPath, recursive: true) // 创建目录 tempDir Directory.create(dirPath) println(目录创建成功: ${dirPath}) // 在 tempDir 下创建文件 tempFile.txt File.create(filePath).close() println(文件创建成功: ${filePath}) // 清理本次运行创建的目录 removeIfExists(dirPath, recursive: true) return 0 }运行结果目录创建成功: ./tempDir 文件创建成功: ./tempDir/tempFile.txt结合canonicalize与Path判等的路径一致性校验模式同一示例文档// 规范化处理冗余路径多个 .、.. 会被解析结果与真实路径一致 let canonicalizedFilePath: Path canonicalize(Path(././././a/./../a/b/../../a/b/c/.././../../a/b/c/d.cj)) if (canonicalizedFilePath canonicalize(filePath)) { println(规范化路径与真实路径一致) }源码结构速查std.fs 包的实现位于 stdlib/libs/std/fs可按需深入阅读common.cj顶层函数copy/exists/rename/remove/removeIfExists的实现与参数校验。path.cjPath结构体、canonicalize、路径分隔符常量与规范化算法。file.cjFile类、OpenMode枚举、FileDescriptor与读写/截断/定位实现。directory.cjDirectory类的创建、遍历walk/readFrom与目录递归拷贝。file_info.cjFileInfo元数据与权限 API。hardlink.cj、symboliclink.cj硬链接与符号链接。utils.cjPathValidator等路径合法性校验工具。native/file_system.h 与 native/file_system_unix.c、native/file_system_win.c跨平台的原生系统调用封装Unix 与 Windows 双实现。总结std.fs 以Path为路径抽象核心通过顶层函数与File、Directory、HardLink、SymbolicLink、FileInfo等类型提供了完整的文件系统编程能力路径的拼接、规范化和真实化join/normalize/canonicalize三者语义各不相同需按需选用文件四种打开模式下的流式读写与截断定位目录的递归创建与回调式遍历以及硬链接、符号链接与元数据权限管理。编写业务代码时务必牢记三点所有文件操作仅对具备权限的路径生效iOS 沙盒尤其受限File对象使用后需及时close()rename(overwrite: true)与递归删除操作具有破坏性应谨慎使用。赞分享编程语言语言运行时标准库垃圾回收并发编程【免费下载链接】cangjie_runtime仓颉编程语言运行时与标准库。项目地址https://gitcode.com/Cangjie/cangjie_runtime点击查看免费下载相关推荐仓颉标准库 std.fs 文件系统类 API 全解析Directory、File 与链接操作实战指南仓颉标准库 std.fs 文件系统类 API 全解析Directory、File 与链接操作实战指南 导读 std.fs file system是仓颉编程编程语言语言运行时标准库垃圾回收并发编程仓颉 std.fs 包详解文件、目录与路径操作的完整 API 与实战指南仓颉 std.fs 包详解文件、目录与路径操作的完整 API 与实战指南 本文基于 CangjieCorpus 语料库中 libs/std/fs 下的官方包文文档知识库教程OpenHarmony仓颉 std.fs Path 实战指南属性解析、路径拼接、规范化与文件目录创建的完整用法仓颉 std.fs Path 实战指南属性解析、路径拼接、规范化与文件目录创建的完整用法 在仓颉Cangjie标准库中 std.fs 包负责文件系统的日文档知识库教程OpenHarmony创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考