查看源代码 文件 (Elixir v1.16.2)
此模块包含用于操作文件的功能。
其中一些函数是低级函数,允许用户与文件或 IO 设备进行交互,例如 open/2
、copy/3
等。该模块还提供高级函数,这些函数使用文件名,并根据 Unix 变体进行命名。例如,可以使用 cp/3
复制文件,可以使用 rm_rf/1
递归地删除文件和目录。
传递给此模块中函数的路径可以是相对于当前工作目录(由 File.cwd/0
返回)的路径,也可以是绝对路径。shell 约定(例如 ~
)不会自动展开。要使用像 ~/Downloads
这样的路径,可以使用 Path.expand/1
或 Path.expand/2
将路径展开为绝对路径。
编码
为了写入和读取文件,必须使用 IO
模块中的函数。默认情况下,文件以二进制模式打开,这需要使用 IO.binread/2
和 IO.binwrite/2
函数与文件进行交互。开发人员可以在打开文件时传递 :utf8
作为选项,然后必须使用较慢的 IO.read/2
和 IO.write/2
函数,因为它们负责执行适当的转换并提供适当的数据保证。
请注意,在 Elixir 中,作为字符列表给出的文件名始终被视为 UTF-8。具体来说,我们预计 shell 和操作系统已配置为使用 UTF-8 编码。二进制文件名被视为原始数据,并按原样传递给操作系统。
API
此模块中的大多数函数在成功时返回 :ok
或 {:ok, result}
,在失败时返回 {:error, reason}
。这些函数还有以 !
结尾的变体,它们在成功时返回结果(而不是 {:ok, result}
元组),在失败时则引发异常。例如
File.read("hello.txt")
#=> {:ok, "World"}
File.read("invalid.txt")
#=> {:error, :enoent}
File.read!("hello.txt")
#=> "World"
File.read!("invalid.txt")
#=> raises File.Error
一般来说,如果开发人员想要在文件不存在时做出反应,则应使用前者。如果开发人员期望他们的软件在无法读取文件时失败(即,它确实是异常),则应使用后者。
进程和原始文件
每次打开文件时,Elixir 都会生成一个新进程。写入文件等同于向写入文件描述符的进程发送消息。
这意味着文件可以在节点之间传递,消息传递保证它们可以写入网络中的同一个文件。
但是,您可能并不总是想要为此抽象付出代价。在这种情况下,文件可以以 :raw
模式打开。当操作大型文件或在紧凑循环中处理文件时,:read_ahead
和 :delayed_write
选项也很有用。
有关这些选项和其他性能注意事项的更多信息,请查看 :file.open/2
。
在文件中查找
您还可以使用 :file
模块中的任何函数与 Elixir 返回的文件进行交互。例如,要从文件中的特定位置读取,请使用 :file.pread/3
File.write!("example.txt", "Eats, Shoots & Leaves")
file = File.open!("example.txt")
:file.pread(file, 15, 6)
#=> {:ok, "Leaves"}
或者,如果您需要跟踪当前位置,请使用 :file.position/2
和 :file.read/2
:file.position(file, 6)
#=> {:ok, 6}
:file.read(file, 6)
#=> {:ok, "Shoots"}
:file.position(file, {:cur, -12})
#=> {:ok, 0}
:file.read(file, 4)
#=> {:ok, "Eats"}
摘要
函数
设置当前工作目录。
与 cd/1
相同,但如果失败,则引发 File.Error
异常。
将当前目录更改为给定的 path
,执行给定的函数,然后无论是否存在异常都恢复到之前的路径。
更改给定 file
的组 ID gid
指定的组。成功时返回 :ok
,失败时返回 {:error, reason}
。
与 chgrp/2
相同,但在失败时引发 File.Error
异常。否则返回 :ok
。
更改给定 file
的 mode
。
与 chmod/2
相同,但在失败时引发 File.Error
异常。否则返回 :ok
。
更改给定 file
的用户 ID uid
指定的拥有者。成功时返回 :ok
,失败时返回 {:error, reason}
。
与 chown/2
相同,但在失败时引发 File.Error
异常。否则返回 :ok
。
关闭 io_device
引用的文件。它主要返回 :ok
,除了内存不足等严重错误。
将 source
的内容复制到 destination
。
与 copy/3
相同,但在失败时引发 File.CopyError
异常。否则返回 bytes_copied
。
将 source_file
的内容复制到 destination_file
,同时保留其模式。
与 cp/3
相同,但在失败时引发 File.CopyError
异常。否则返回 :ok
。
递归地将 source
中的内容复制到 destination
,同时维护源目录结构和模式。
与 cp_r/3
相同,但在失败时引发 File.CopyError
异常。否则返回已复制文件的列表。
获取当前工作目录。
与 cwd/0
相同,但如果失败,则引发 File.Error
异常。
如果给定的路径是目录,则返回 true
。
如果给定的路径存在,则返回 true
。
为文件 existing
创建硬链接 new
。
与 ln/2
相同,但在失败时引发 File.LinkError
异常。否则返回 :ok
。
为文件或目录 existing
创建符号链接 new
。
与 ln_s/2
相同,但在失败时引发 File.LinkError
异常。否则返回 :ok
。
返回给定目录中的文件列表。
与 ls/1
相同,但在发生错误时引发 File.Error
异常。
与 lstat/2
相同,但直接返回 File.Stat
结构体,或者在返回错误时引发 File.Error
异常。
尝试创建目录 path
。
与 mkdir/1
相同,但在失败时引发 File.Error
异常。否则返回 :ok
。
尝试创建目录 path
。
与 mkdir_p/1
相同,但在失败时引发 File.Error
异常。否则返回 :ok
。
打开给定的 path
。
类似于 open/2
,但期望一个函数作为其最后一个参数。
类似于 open/2
,但在无法打开文件时引发 File.Error
异常。否则返回 IO 设备。
类似于 open/3
,但在无法打开文件时引发 File.Error
异常。
返回 {:ok, binary}
,其中 binary
是一个包含 path
内容的二进制数据对象,或者如果发生错误则返回 {:error, reason}
。
返回给定文件名的内容的二进制数据,或者在发生错误时引发 File.Error
异常。
读取 path
处的符号链接。
与 read_link/1
相同,但直接返回目标,或者在返回错误时引发 File.Error
异常。
如果路径是普通文件,则返回 true
。
将 source
文件重命名为 destination
文件。它可用于在目录之间移动文件(和目录)。如果移动文件,则必须完全指定 destination
文件名,仅指定其目录是不够的。
与 rename/2
相同,但在失败时引发 File.RenameError
异常。否则返回 :ok
。
尝试删除文件 path
。
与 rm/1
相同,但在失败的情况下会引发 File.Error
异常。否则返回 :ok
。
递归地删除给定 path
下的文件和目录。不会跟踪符号链接,而是直接删除它们,不存在的文件将被忽略(即不会导致此函数失败)。
与 rm_rf/1
相同,但在失败的情况下会引发 File.Error
异常,否则返回已删除的文件或目录列表。
尝试删除 path
下的目录。
与 rmdir/1
相同,但在失败的情况下会引发 File.Error
异常。否则返回 :ok
。
与 stat/2
相同,但直接返回 File.Stat
,如果返回错误则引发 File.Error
异常。
为给定 path
返回一个带有给定 modes
的 File.Stream
。
更新给定文件的修改时间 (mtime) 和访问时间 (atime)。
与 touch/2
相同,但在失败的情况下会引发 File.Error
异常。否则返回 :ok
。
将 content
写入文件 path
。
与 write/3
相同,但在失败的情况下会引发 File.Error
异常。否则返回 :ok
。
将给定的 File.Stat
写回文件系统中的给定路径。返回 :ok
或 {:error, reason}
。
与 write_stat/3
相同,但在失败的情况下会引发 File.Error
异常。否则返回 :ok
。
类型
@type encoding_mode() ::
:utf8
| {:encoding,
:latin1
| :unicode
| :utf8
| :utf16
| :utf32
| {:utf16, :big | :little}
| {:utf32, :big | :little}}
@type erlang_time() :: {{year :: non_neg_integer(), month :: 1..12, day :: 1..31}, {hour :: 0..23, minute :: 0..59, second :: 0..59}}
@type io_device() :: :file.io_device()
@type mode() :: :append | :binary | :charlist | :compressed | :delayed_write | :exclusive | :raw | :read | :read_ahead | :sync | :write | {:read_ahead, pos_integer()} | {:delayed_write, non_neg_integer(), non_neg_integer()} | encoding_mode()
@type posix() :: :file.posix()
@type posix_time() :: integer()
@type read_offset_mode() :: {:read_offset, non_neg_integer()}
@type stat_options() :: [{:time, :local | :universal | :posix}]
@type stream_mode() :: encoding_mode() | read_offset_mode() | :append | :compressed | :delayed_write | :trim_bom | {:read_ahead, pos_integer() | false} | {:delayed_write, non_neg_integer(), non_neg_integer()}
函数
设置当前工作目录。
当前工作目录是在 BEAM 中全局设置的。如果多个进程同时更改当前工作目录,这可能会导致竞争条件。要在不更改全局当前工作目录的情况下在给定目录中运行外部命令,请使用 System.cmd/3
和 Port.open/2
的 :cd
选项。
如果成功,则返回 :ok
,否则返回 {:error, reason}
。
@spec cd!(Path.t()) :: :ok
与 cd/1
相同,但如果失败,则引发 File.Error
异常。
@spec cd!(Path.t(), (-> res)) :: res when res: var
将当前目录更改为给定的 path
,执行给定的函数,然后无论是否存在异常都恢复到之前的路径。
当前工作目录在 BEAM 中被临时全局设置。如果多个进程同时更改当前工作目录,这可能会导致竞争条件。要在不更改全局当前工作目录的情况下在给定目录中运行外部命令,请使用 System.cmd/3
和 Port.open/2
的 :cd
选项。
如果检索或更改当前目录失败,则会引发错误。
@spec chgrp(Path.t(), non_neg_integer()) :: :ok | {:error, posix()}
更改给定 file
的组 ID gid
指定的组。成功时返回 :ok
,失败时返回 {:error, reason}
。
@spec chgrp!(Path.t(), non_neg_integer()) :: :ok
与 chgrp/2
相同,但在失败时引发 File.Error
异常。否则返回 :ok
。
@spec chmod(Path.t(), non_neg_integer()) :: :ok | {:error, posix()}
更改给定 file
的 mode
。
成功时返回 :ok
,失败时返回 {:error, reason}
。
权限
文件权限通过将以下八进制模式相加来指定
0o400
- 读取权限:所有者0o200
- 写入权限:所有者0o100
- 执行权限:所有者0o040
- 读取权限:组0o020
- 写入权限:组0o010
- 执行权限:组0o004
- 读取权限:其他0o002
- 写入权限:其他0o001
- 执行权限:其他
例如,将模式设置为 0o755
将赋予所有者写入、读取和执行权限,以及组和其他人读取和执行权限。
@spec chmod!(Path.t(), non_neg_integer()) :: :ok
与 chmod/2
相同,但在失败时引发 File.Error
异常。否则返回 :ok
。
@spec chown(Path.t(), non_neg_integer()) :: :ok | {:error, posix()}
更改给定 file
的用户 ID uid
指定的拥有者。成功时返回 :ok
,失败时返回 {:error, reason}
。
@spec chown!(Path.t(), non_neg_integer()) :: :ok
与 chown/2
相同,但在失败时引发 File.Error
异常。否则返回 :ok
。
关闭 io_device
引用的文件。它主要返回 :ok
,除了内存不足等严重错误。
注意,如果在打开文件时使用了 :delayed_write
选项,close/1
可能会返回旧的写入错误,甚至不会尝试关闭文件。有关详细信息,请参见 open/2
。
@spec copy(Path.t() | io_device(), Path.t() | io_device(), pos_integer() | :infinity) :: {:ok, non_neg_integer()} | {:error, posix()}
将 source
的内容复制到 destination
。
两个参数都可以是使用 open/2
打开的文件名或 IO 设备。 bytes_count
指定要复制的字节数,默认值为 :infinity
。
如果文件 destination
已经存在,它将被 source
中的内容覆盖。
如果成功,则返回 {:ok, bytes_copied}
,否则返回 {:error, reason}
。
与 cp/3
相比,此函数更底层,允许按字节数限制将内容从一个设备复制到另一个设备。另一方面,cp/3
对源和目标进行更广泛的检查,并且还保留复制后的文件模式。
@spec copy!(Path.t() | io_device(), Path.t() | io_device(), pos_integer() | :infinity) :: non_neg_integer()
与 copy/3
相同,但在失败时引发 File.CopyError
异常。否则返回 bytes_copied
。
@spec cp(Path.t(), Path.t(), [{:on_conflict, on_conflict_callback()}]) :: :ok | {:error, posix()}
将 source_file
的内容复制到 destination_file
,同时保留其模式。
source_file
必须是文件或指向文件的符号链接。 destination_file
必须是指向不存在文件的路径。如果两者都是目录,则将返回 {:error, :eisdir}
。
如果函数成功,则返回 :ok
。否则,它将返回 {:error, reason}
。
如果您想将内容从一个 IO 设备复制到另一个设备,或者直接将内容从源复制到目标而不保留模式,请查看 copy/3
。
注意:Unix 类系统中的 cp
命令的行为不同,具体取决于目标是现有目录还是其他目录。我们选择明确禁止复制到目标目录,如果尝试这样做,将返回错误。
选项
:on_conflict
- (自 v1.14.0 起) 当目标中已存在文件时调用。该函数接收source_file
和destination_file
的参数。如果现有文件应该被覆盖,它应该返回true
,否则返回false
。默认回调返回true
。在早期版本中,此回调可以作为第三个参数给出,但现在这种行为已过时。
@spec cp!(Path.t(), Path.t(), [{:on_conflict, on_conflict_callback()}]) :: :ok
与 cp/3
相同,但在失败时引发 File.CopyError
异常。否则返回 :ok
。
@spec cp_r(Path.t(), Path.t(), on_conflict: on_conflict_callback(), dereference_symlinks: boolean() ) :: {:ok, [binary()]} | {:error, posix(), binary()}
递归地将 source
中的内容复制到 destination
,同时维护源目录结构和模式。
如果 source
是文件或指向文件的符号链接,则 destination
必须是指向现有文件、指向现有文件的符号链接或指向不存在文件的路径。
如果 source
是目录或指向目录的符号链接,则 destination
必须是现有 directory
或指向目录的符号链接,或指向不存在目录的路径。
如果源是文件,则将 source
复制到 destination
。如果 source
是目录,则将源内部的内容复制到 destination
目录中。
如果目标中已存在文件,则会调用作为选项给出的可选 on_conflict
回调。有关详细信息,请参见“选项”。
此函数在复制文件时可能会失败,在这种情况下,它会将目标目录处于混乱状态,其中已复制的文件不会被删除。
如果函数成功,则返回 {:ok, files_and_directories}
, files_and_directories
以非特定顺序列出所有复制的文件和目录。否则,它将返回 {:error, reason, file}
。
注意:Unix 类系统中的 cp
命令的行为不同,具体取决于 destination
是现有目录还是其他目录。我们选择明确禁止此行为。如果 source
是 file
且 destination
是目录,则将返回 {:error, :eisdir}
。
选项
:on_conflict
- (自 v1.14.0 起) 当目标中已存在文件时调用。该函数接收source
和destination
的参数。如果现有文件应该被覆盖,它应该返回true
,否则返回false
。默认回调返回true
。在早期版本中,此回调可以作为第三个参数给出,但现在这种行为已过时。:dereference_symlinks
- (自 v1.14.0 起) 默认情况下,此函数会通过创建指向相同位置的符号链接来复制符号链接。如果此选项设置为true
,则会强制对符号链接进行解除引用,并复制其内容。如果解除引用的文件不存在,则操作将失败。默认值为false
。
示例
# Copies file "a.txt" to "b.txt"
File.cp_r("a.txt", "b.txt")
# Copies all files in "samples" to "tmp"
File.cp_r("samples", "tmp")
# Same as before, but asks the user how to proceed in case of conflicts
File.cp_r("samples", "tmp", on_conflict: fn source, destination ->
IO.gets("Overwriting #{destination} by #{source}. Type y to confirm. ") == "y\n"
end)
@spec cp_r!(Path.t(), Path.t(), on_conflict: on_conflict_callback(), dereference_symlinks: boolean() ) :: [binary()]
与 cp_r/3
相同,但在失败时引发 File.CopyError
异常。否则返回已复制文件的列表。
获取当前工作目录。
在极少数情况下,此函数在 Unix 类系统上可能会失败。如果当前目录的父目录不存在读取权限,则可能会发生这种情况。因此,如果成功,则返回 {:ok, cwd}
,否则返回 {:error, reason}
。
@spec cwd!() :: binary()
与 cwd/0
相同,但如果失败,则引发 File.Error
异常。
如果给定的路径是目录,则返回 true
。
此函数会跟踪符号链接,因此如果符号链接指向目录,则返回 true
。
选项
支持的选项是
:raw
- 单个原子,绕过文件服务器,仅检查本地文件
示例
File.dir?("./test")
#=> true
File.dir?("test")
#=> true
File.dir?("/usr/bin")
#=> true
File.dir?("~/Downloads")
#=> false
"~/Downloads" |> Path.expand() |> File.dir?()
#=> true
如果给定的路径存在,则返回 true
。
它可以是普通文件、目录、套接字、符号链接、命名管道或设备文件。对于指向不存在目标的符号链接,返回 false
。
选项
支持的选项是
:raw
- 单个原子,绕过文件服务器,仅检查本地文件
示例
File.exists?("test/")
#=> true
File.exists?("missing.txt")
#=> false
File.exists?("/dev/null")
#=> true
为文件 existing
创建硬链接 new
。
如果成功,则返回 :ok
,否则返回 {:error, reason}
。如果操作系统不支持硬链接,则返回 {:error, :enotsup}
。
与 ln/2
相同,但在失败时引发 File.LinkError
异常。否则返回 :ok
。
为文件或目录 existing
创建符号链接 new
。
如果成功,则返回 :ok
,否则返回 {:error, reason}
。如果操作系统不支持符号链接,则返回 {:error, :enotsup}
。
与 ln_s/2
相同,但在失败时引发 File.LinkError
异常。否则返回 :ok
。
返回给定目录中的文件列表。
隐藏文件不会被忽略,结果也不会被排序。
由于目录被文件系统视为文件,因此它们也包含在返回值中。
如果成功,则返回 {:ok, files}
,否则返回 {:error, reason}
。
与 ls/1
相同,但在发生错误时引发 File.Error
异常。
@spec lstat(Path.t(), stat_options()) :: {:ok, File.Stat.t()} | {:error, posix()}
返回有关 path
的信息。如果文件是符号链接,则将 type
设置为 :symlink
,并返回链接的 File.Stat
结构体。对于任何其他文件,返回与 stat/2
完全相同的返回值。
有关更多详细信息,请参见 :file.read_link_info/2
。
选项
接受的选项包括
:time
- 配置如何返回文件时间戳
:time
的值可以是
:universal
- 以 UTC 返回{date, time}
元组(默认):local
- 使用机器时间返回{date, time}
元组:posix
- 将时间以自纪元以来的整数秒数返回
注意:由于文件时间在大多数操作系统上以 POSIX 时间格式存储,因此使用 time: :posix
选项检索文件信息的速度更快。
@spec lstat!(Path.t(), stat_options()) :: File.Stat.t()
与 lstat/2
相同,但直接返回 File.Stat
结构体,或者在返回错误时引发 File.Error
异常。
尝试创建目录 path
。
不会创建缺失的父目录。如果成功,则返回 :ok
,如果发生错误,则返回 {:error, reason}
。
常见的错误原因包括
:eacces
- 缺少path
父目录的搜索或写入权限:eexist
- 已经存在名为path
的文件或目录:enoent
-path
的一个组件不存在:enospc
- 设备上没有剩余空间:enotdir
-path
的一个组件不是目录;在某些平台上,会返回:enoent
@spec mkdir!(Path.t()) :: :ok
与 mkdir/1
相同,但在失败时引发 File.Error
异常。否则返回 :ok
。
尝试创建目录 path
。
会创建缺失的父目录。如果成功,则返回 :ok
,如果发生错误,则返回 {:error, reason}
。
常见的错误原因包括
:eacces
- 缺少path
父目录的搜索或写入权限:enospc
- 设备上没有剩余空间:enotdir
-path
的一个组件不是目录
@spec mkdir_p!(Path.t()) :: :ok
与 mkdir_p/1
相同,但在失败时引发 File.Error
异常。否则返回 :ok
。
@spec open(Path.t(), [mode() | :ram]) :: {:ok, io_device()} | {:error, posix()}
@spec open(Path.t(), (io_device() -> res)) :: {:ok, res} | {:error, posix()} when res: var
打开给定的 path
。
为了写入和读取文件,必须使用 IO
模块中的函数。默认情况下,文件以 :binary
模式打开,这需要 IO.binread/2
和 IO.binwrite/2
函数与文件进行交互。开发人员可以在打开文件时传递 :utf8
作为选项,然后来自 IO
的所有其他函数都可用,因为它们直接使用 Unicode 数据。
modes_or_function
可以是模式列表或函数。如果它是一个列表,则它被视为模式列表(在下面有文档说明)。如果它是一个函数,则它等效于调用 open(path, [], modes_or_function)
。有关此函数的更多信息,请参见 open/3
的文档。
允许的模式
:binary
- 以二进制模式打开文件,禁用对 Unicode 序列的特殊处理(默认模式)。:read
- 文件必须存在,以供读取打开。:write
- 文件以供写入打开。如果它不存在,则会创建它。如果文件存在,并且写入没有与读取组合,则文件将被截断。
:append
- 文件将以供写入打开,如果它不存在,则会创建它。对以追加模式打开的文件的每次写入操作都将发生在文件末尾。:exclusive
- 文件在以供写入打开时,如果它不存在,则会创建它。如果文件存在,open 将返回{:error, :eexist}
。:charlist
- 当给出此项时,对文件的读取操作将返回字符列表而不是二进制。:compressed
- 使读取或写入 gzip 压缩文件成为可能。compressed 选项必须与读取或写入结合使用,但不能同时使用两者。请注意,通过
stat/1
获得的文件大小很可能与可以从压缩文件中读取的字节数不匹配。:utf8
- 此选项表示数据实际存储在磁盘文件中的方式,并使文件自动将字符转换为 UTF-8 并从 UTF-8 转换。如果数据以无法转换为 UTF-8 的格式发送到文件,或者数据被返回以无法处理数据的字符范围的格式返回数据的函数读取,则会发生错误,并且文件将被关闭。
:delayed_write
,:raw
,:ram
,:read_ahead
,:sync
,{:encoding, ...}
,{:read_ahead, pos_integer}
,{:delayed_write, non_neg_integer, non_neg_integer}
- 有关这些选项的更多信息,请参见:file.open/2
。
此函数返回
{:ok, io_device}
- 文件已以请求的模式打开。io_device
实际上是处理文件的进程的 PID。此进程监控最初打开文件的进程(所有者进程)。如果所有者进程终止,则文件将被关闭,进程本身也将终止。如果与io_device
链接的任何进程终止,则文件将被关闭,进程本身也将终止。从该调用返回的
io_device
可以用作IO
模块函数的参数。{:error, reason}
- 文件无法打开。
示例
{:ok, file} = File.open("foo.tar.gz", [:read, :compressed])
IO.read(file, :line)
File.close(file)
@spec open(Path.t(), [mode() | :ram], (io_device() -> res)) :: {:ok, res} | {:error, posix()} when res: var
类似于 open/2
,但期望一个函数作为其最后一个参数。
文件被打开,作为参数传递给函数,并在函数返回后自动关闭,无论执行函数时是否发生错误。
如果成功,则返回 {:ok, function_result}
,否则返回 {:error, reason}
。
此函数期望文件成功关闭,通常情况如此,除非给出 :delayed_write
选项。因此,我们不建议将 :delayed_write
传递给此函数。
示例
File.open("file.txt", [:read, :write], fn file ->
IO.read(file, :line)
end)
有关可用 modes
的列表,请参见 open/2
。
@spec open!(Path.t(), [mode() | :ram]) :: io_device()
@spec open!(Path.t(), (io_device() -> res)) :: res when res: var
类似于 open/2
,但在无法打开文件时引发 File.Error
异常。否则返回 IO 设备。
有关可用模式的列表,请参见 open/2
。
类似于 open/3
,但在无法打开文件时引发 File.Error
异常。
如果它成功打开文件,则它将在 IO 设备上返回 function
结果。
有关可用 modes
的列表,请参见 open/2
。
返回 {:ok, binary}
,其中 binary
是一个包含 path
内容的二进制数据对象,或者如果发生错误则返回 {:error, reason}
。
常见的错误原因
:enoent
- 文件不存在:eacces
- 缺少读取文件的权限,或缺少搜索其父目录之一的权限:eisdir
- 指定的文件是一个目录:enotdir
- 文件名的一个组件不是目录;在某些平台上,会返回:enoent
:enomem
- 文件的内容没有足够的内存
可以使用 :file.format_error/1
获取错误的描述性字符串。
返回给定文件名的内容的二进制数据,或者在发生错误时引发 File.Error
异常。
读取 path
处的符号链接。
如果 path
存在并且是一个符号链接,则返回 {:ok, target}
,否则返回 {:error, reason}
。
有关更多详细信息,请参见 :file.read_link/1
。
常见的错误原因包括
:einval
- path 不是符号链接:enoent
- path 不存在:enotsup
- 当前平台不支持符号链接
与 read_link/1
相同,但直接返回目标,或者在返回错误时引发 File.Error
异常。
如果路径是普通文件,则返回 true
。
此函数会遵循符号链接,因此如果符号链接指向一个普通文件,则会返回 true
。
选项
支持的选项是
:raw
- 单个原子,绕过文件服务器,仅检查本地文件
示例
File.regular?(__ENV__.file)
#=> true
将 source
文件重命名为 destination
文件。它可用于在目录之间移动文件(和目录)。如果移动文件,则必须完全指定 destination
文件名,仅指定其目录是不够的。
如果成功,则返回 :ok
,否则返回 {:error, reason}
。
注意:Unix 类系统中的 mv
命令的行为不同,具体取决于 source
是文件,而 destination
是现有的目录。我们选择明确禁止此行为。
示例
# Rename file "a.txt" to "b.txt"
File.rename("a.txt", "b.txt")
# Rename directory "samples" to "tmp"
File.rename("samples", "tmp")
与 rename/2
相同,但在失败时引发 File.RenameError
异常。否则返回 :ok
。
尝试删除文件 path
。
如果成功,则返回 :ok
,如果发生错误,则返回 {:error, reason}
。
注意,即使在只读模式下也会删除文件。
常见的错误原因包括
:enoent
- 文件不存在:eacces
- 缺少文件或其父目录之一的权限:eperm
- 文件是一个目录,并且用户不是超级用户:enotdir
- 文件名的一个组件不是目录;在某些平台上,会返回:enoent
:einval
- 文件名类型不正确,例如元组
示例
File.rm("file.txt")
#=> :ok
File.rm("tmp_dir/")
#=> {:error, :eperm}
@spec rm!(Path.t()) :: :ok
与 rm/1
相同,但在失败的情况下会引发 File.Error
异常。否则返回 :ok
。
递归地删除给定 path
下的文件和目录。不会跟踪符号链接,而是直接删除它们,不存在的文件将被忽略(即不会导致此函数失败)。
返回 {:ok, files_and_directories}
,其中包含按无特定顺序删除的所有文件和目录,否则返回 {:error, reason, file}
。
示例
File.rm_rf("samples")
#=> {:ok, ["samples", "samples/1.txt"]}
File.rm_rf("unknown")
#=> {:ok, []}
与 rm_rf/1
相同,但在失败的情况下会引发 File.Error
异常,否则返回已删除的文件或目录列表。
尝试删除 path
下的目录。
如果成功,则返回 :ok
,如果发生错误,则返回 {:error, reason}
。如果目录不为空,则返回 {:error, :eexist}
。
示例
File.rmdir("tmp_dir")
#=> :ok
File.rmdir("non_empty_dir")
#=> {:error, :eexist}
File.rmdir("file.txt")
#=> {:error, :enotdir}
与 rmdir/1
相同,但在失败的情况下会引发 File.Error
异常。否则返回 :ok
。
@spec stat(Path.t(), stat_options()) :: {:ok, File.Stat.t()} | {:error, posix()}
返回有关 path
的信息。如果存在,则返回一个 {:ok, info}
元组,其中 info 是一个 File.Stat
结构体。如果发生错误,则返回 {:error, reason}
,错误原因与 read/1
相同。
选项
接受的选项包括
:time
- 配置如何返回文件时间戳
:time
的值可以是
:universal
- 以 UTC 返回{date, time}
元组(默认):local
- 使用与机器相同的时区返回{date, time}
元组:posix
- 将时间以自纪元以来的整数秒数返回
注意:由于文件时间在大多数操作系统上以 POSIX 时间格式存储,因此使用 time: :posix
选项检索文件信息的速度更快。
@spec stat!(Path.t(), stat_options()) :: File.Stat.t()
与 stat/2
相同,但直接返回 File.Stat
,如果返回错误则引发 File.Error
异常。
@spec stream!(Path.t(), :line | pos_integer() | [stream_mode()]) :: File.Stream.t()
是 File.stream!/3
的简写。
@spec stream!(Path.t(), :line | pos_integer(), [stream_mode()]) :: File.Stream.t()
为给定 path
返回一个带有给定 modes
的 File.Stream
。
流同时实现了 Enumerable
和 Collectable
协议,这意味着它既可以用于读取也可以用于写入。
line_or_bytes
参数配置流式传输时如何读取文件,通过 :line
(默认)或通过给定的字节数。使用 :line
选项时,CRLF 换行符 ("\r\n"
) 将被规范化为 LF ("\n"
)。
与其他文件操作类似,流可以在一个节点中创建并转发到另一个节点。一旦流在另一个节点中打开,将向创建者节点发送请求以生成一个用于文件流式传输的进程。
操作流可能会在打开时因与 File.open!/2
相同的原因而失败。请注意,每次流式传输开始时都会自动打开文件。无需传递 :read
和 :write
模式,因为这些模式由 Elixir 自动设置。
原始文件
由于 Elixir 控制着流文件何时打开,底层设备无法共享,因此为了性能考虑,最好以原始模式打开文件。 因此,如果流在创建它的同一节点中打开并且没有指定编码,Elixir **将** 以 :raw
模式打开流,并使用 :read_ahead
选项。 这意味着流入文件的任何数据必须转换为 iodata/0
类型。 如果你传递,例如,[encoding: :utf8]
或 [encoding: {:utf16, :little}]
在 modes 参数中,底层流将使用 IO.write/2
和 String.Chars
协议来转换数据。 查看 IO.binwrite/2
和 IO.write/2
。
如果流打算在紧密循环中写入,也可以考虑传递 :delayed_write
选项。
字节顺序标记和读取偏移量
如果你在 modes 参数中传递 :trim_bom
,流将在从文件读取时修剪 UTF-8、UTF-16 和 UTF-32 字节顺序标记。
请注意,此函数不会尝试根据 BOM 发现文件编码。 从 Elixir v1.16.0 开始,你还可以传递一个 :read_offset
,该偏移量在枚举流时会被跳过(如果同时提供了 :read_offset
和 :trim_bom
,则会在 BOM 之后跳过偏移量)。
示例
# Read a utf8 text file which may include BOM
File.stream!("./test/test.txt", [:trim_bom, encoding: :utf8])
# Read in 2048 byte chunks rather than lines
File.stream!("./test/test.data", 2048)
查看 Stream.run/1
,了解流入文件的示例。
@spec touch(Path.t(), erlang_time() | posix_time()) :: :ok | {:error, posix()}
更新给定文件的修改时间 (mtime) 和访问时间 (atime)。
如果文件不存在,则会创建该文件。 需要以 UTC 时间表示的日期时间(如 :erlang.universaltime()
返回)或表示 POSIX 时间戳的整数(如 System.os_time(:second)
返回)。
在类 Unix 系统中,更改修改时间可能需要你具有 root
权限或文件的拥有者权限。 具有写入权限可能还不够。 在这些情况下,第一次触摸文件(以创建文件)将成功,但触摸现有文件将失败,并显示 {:error, :eperm}
。
示例
File.touch("/tmp/a.txt", {{2018, 1, 30}, {13, 59, 59}})
#=> :ok
File.touch("/fakedir/b.txt", {{2018, 1, 30}, {13, 59, 59}})
{:error, :enoent}
File.touch("/tmp/a.txt", 1544519753)
#=> :ok
@spec touch!(Path.t(), erlang_time() | posix_time()) :: :ok
与 touch/2
相同,但在失败的情况下会引发 File.Error
异常。否则返回 :ok
。
如果文件不存在,则会创建该文件。 需要以 UTC 时间表示的日期时间(如 :erlang.universaltime()
返回)或表示 POSIX 时间戳的整数(如 System.os_time(:second)
返回)。
示例
File.touch!("/tmp/a.txt", {{2018, 1, 30}, {13, 59, 59}})
#=> :ok
File.touch!("/fakedir/b.txt", {{2018, 1, 30}, {13, 59, 59}})
** (File.Error) could not touch "/fakedir/b.txt": no such file or directory
File.touch!("/tmp/a.txt", 1544519753)
将 content
写入文件 path
。
如果文件不存在,则会创建该文件。 如果文件存在,则会覆盖之前的内容。 如果成功,则返回 :ok
,否则返回 {:error, reason}
。
content
必须是 iodata
(字节列表或二进制)。 为此函数设置编码没有任何效果。
警告:每次调用此函数时,都会打开一个文件描述符,并生成一个新的进程来写入文件。 因此,如果在循环中进行多次写入,则通过 File.open/2
打开文件并使用 IO
中的函数写入文件,将比多次调用此函数具有更好的性能。
常见的错误原因包括
:enoent
- 文件名的某个组成部分不存在:enotdir
- 文件名的一个组件不是目录;在某些平台上,会返回:enoent
:enospc
- 设备上没有剩余空间:eacces
- 缺少写入文件或搜索父目录之一的权限:eisdir
- 指定的文件是一个目录
查看 File.open/2
以了解其他可用选项。
与 write/3
相同,但在失败的情况下会引发 File.Error
异常。否则返回 :ok
。
@spec write_stat(Path.t(), File.Stat.t(), stat_options()) :: :ok | {:error, posix()}
将给定的 File.Stat
写回文件系统中的给定路径。返回 :ok
或 {:error, reason}
。
@spec write_stat!(Path.t(), File.Stat.t(), stat_options()) :: :ok
与 write_stat/3
相同,但在失败的情况下会引发 File.Error
异常。否则返回 :ok
。