查看源码 file (内核 v10.2)

文件接口模块。

该模块提供了文件系统的接口。

警告

只有通过同一个文件服务器进行文件操作才能保证原子性。在某些操作系统上,例如在 Windows 上重命名现有文件,或者在编写本文时在任何操作系统上执行 write_file_info/2,NIF 或其他操作系统进程可能会观察到某些操作的中间步骤。

关于文件名编码,Erlang 虚拟机可以在两种模式下运行。可以使用函数 native_name_encoding/0 查询当前模式。它返回 latin1utf8

latin1 模式下,Erlang 虚拟机不更改文件名的编码。在 utf8 模式下,文件名可以包含大于 255 的 Unicode 字符,并且虚拟机将文件名来回转换为本机文件名编码(通常为 UTF-8,但在 Windows 上为 UTF-16)。

默认模式取决于操作系统。Windows、MacOS X 和 Android 强制执行一致的文件名编码,因此虚拟机使用 utf8 模式。

在具有透明命名(例如,除 MacOS X 之外的所有 Unix 系统)的操作系统上,如果终端支持 UTF-8,则默认值为 utf8,否则为 latin1。可以使用 +fnl(强制使用 latin1 模式)或 +fnu(强制使用 utf8 模式)在启动 erl 时覆盖默认值。

在具有透明命名的操作系统上,文件名可能会不一致,例如,某些文件以 UTF-8 编码,而另一些文件以 ISO Latin-1 编码。引入了原始文件名的概念,以在 utf8 模式下运行时处理具有不一致命名的文件系统。

原始文件名是指定为二进制文件的文件名。在具有透明命名的系统上,Erlang 虚拟机不会转换指定为二进制文件的文件名。

utf8 模式下运行时,函数 list_dir/1read_link/1 永远不会返回原始文件名。要返回所有文件名(包括原始文件名),请使用函数 list_dir_all/1read_link_all/1

另请参阅 STDLIB 用户指南中的 关于原始文件名的说明 部分。

注意

文件操作过去接受包含空字符(整数值零)的文件名。这会导致名称被截断,并且在某些情况下,原始操作的参数会被混淆。文件名内部包含空字符的文件名现在被拒绝,并将导致原始文件操作失败。

POSIX 错误代码

  • eacces - 权限被拒绝
  • eagain - 资源暂时不可用
  • ebadf - 坏的文件号
  • ebusy - 文件繁忙
  • edquot - 超出磁盘配额
  • eexist - 文件已存在
  • efault - 系统调用参数中的错误地址
  • efbig - 文件太大
  • eintr - 系统调用被中断
  • einval - 无效的参数
  • eio - I/O 错误
  • eisdir - 对目录的非法操作
  • eloop - 符号链接级别过多
  • emfile - 打开的文件过多
  • emlink - 链接过多
  • enametoolong - 文件名太长
  • enfile - 文件表溢出
  • enodev - 没有这样的设备
  • enoent - 没有这样的文件或目录
  • enomem - 内存不足
  • enospc - 设备上没有剩余空间
  • enotblk - 需要块设备
  • enotdir - 不是目录
  • enotsup - 不支持的操作
  • enxio - 没有这样的设备或地址
  • eperm - 不是所有者
  • epipe - 管道损坏
  • erofs - 只读文件系统
  • espipe - 无效的查找
  • esrch - 没有这样的进程
  • estale - 过时的远程文件句柄
  • exdev - 跨设备链接

性能

为了提高性能,建议使用原始文件。

普通文件实际上是一个进程,因此可以用作 I/O 设备(请参阅 io)。因此,当数据写入普通文件时,将数据发送到文件进程会复制所有非二进制的数据。因此,建议以二进制模式打开文件并写入二进制文件。如果文件在另一个节点上打开,或者如果文件服务器作为另一个节点的文件服务器的从属服务器运行,则也会复制二进制文件。

注意

原始文件使用节点主机的文件系统。对于普通文件(非原始),文件服务器用于查找文件,如果节点将其文件服务器作为另一个节点的文件服务器的从属服务器运行,并且另一个节点在其他主机上运行,则它们可能具有不同的文件系统。但是,这很少是一个问题。

可以为 open/2 提供选项 delayed_writeread_ahead 来启用缓存,这将减少操作系统调用的次数,并大大提高小读取和写入的性能。但是,开销不会完全消失,最好将文件操作的数量保持在最低限度。作为一个人为的示例,以下函数在测试时以 2.5 秒写入 4MB

create_file_slow(Name) ->
    {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
    create_file_slow_1(Fd, 4 bsl 20),
    file:close(Fd).

create_file_slow_1(_Fd, 0) ->
    ok;
create_file_slow_1(Fd, M) ->
    ok = file:write(Fd, <<0>>),
    create_file_slow_1(Fd, M - 1).

以下功能等效的代码每次调用 write/2 写入 128 字节,因此在 0.08 秒内完成相同的工作,速度快约 30 倍

create_file(Name) ->
    {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
    create_file_1(Fd, 4 bsl 20),
    file:close(Fd),
    ok.

create_file_1(_Fd, 0) ->
    ok;
create_file_1(Fd, M) when M >= 128 ->
    ok = file:write(Fd, <<0:(128)/unit:8>>),
    create_file_1(Fd, M - 128);
create_file_1(Fd, M) ->
    ok = file:write(Fd, <<0:(M)/unit:8>>),
    create_file_1(Fd, M - 1).

在写入数据时,写入二进制列表通常比写入整数列表更有效。无需在写入之前展平深层列表。在 Unix 主机上,尽可能使用散布输出,该输出在一个操作中写入一组缓冲区。通过这种方式,write(FD, [Bin1, Bin2 | Bin3]) 写入二进制文件的内容,而根本不复制数据,除非可能在操作系统内核的深处。

警告

如果在使用模块 io 访问打开的文件时发生错误,则处理该文件的进程将退出。如果进程稍后尝试访问已死的进程,则该进程可能会挂起。这将在未来的版本中修复。

另请参阅

filename

摘要

类型

必须表示有效的日期和时间。

一个文件描述符,表示以 raw 模式打开的文件。

file API 函数返回的文件名。

file API 函数返回的文件名。

open/2 返回的 IO 设备。

处理 I/O 协议的进程。

用作 file API 函数输入的受限文件名。

用作 file API 函数输入的文件名。

一个原子,其名称来自 Unix 中使用的 POSIX 错误代码以及大多数 C 编译器的运行时库。

函数

advise/4 可用于声明未来以特定模式访问文件数据的意图,从而允许操作系统执行适当的优化。

allocate/3 可用于为文件预分配空间。

更改文件的组。请参阅 write_file_info/2

更改文件的权限。请参阅 write_file_info/2

更改文件的所有者。请参阅 write_file_info/2

更改文件的所有者和组。请参阅 write_file_info/2

更改文件的修改时间和访问时间。请参阅 write_file_info/2

更改文件的修改时间和上次访问时间。请参阅 write_file_info/2

关闭 IoDevice 引用的文件。它大多返回 ok,除了某些严重的错误,例如内存不足。

Filename 读取以 . 分隔的 Erlang 术语。返回以下内容之一

Source 复制 ByteCount 字节到 DestinationSourceDestination 指的是文件名或 IO 设备,例如,来自 open/2

确保操作系统(而不是 Erlang 运行时系统)保留的任何缓冲区都写入磁盘。它在许多方面类似于 fsync,但它不会更新文件的某些元数据,例如访问时间。在某些平台上,此函数不起作用。

尝试删除目录 Dir。该目录必须为空才能删除。如果成功,则返回 ok

删除文件或目录 File。如果 File 是一个目录,则首先递归删除其内容。返回

尝试删除文件 Filename。如果成功,则返回 ok

Filename 读取和评估以 .(或 ,,表达式序列也是一个表达式)分隔的 Erlang 表达式。不会返回评估的结果;文件中的任何表达式序列都必须存在以产生副作用。

eval/1 相同,但在求值时使用变量绑定 Bindings。有关变量绑定的信息,请参阅 erl_eval

给定此模块中任何函数返回的错误原因,返回描述错误的英文字符串。

返回 {ok, Dir},其中 Dir 是文件服务器的当前工作目录。

返回 {ok, Dir}{error, Reason},其中 Dir 是指定驱动器的当前工作目录。

列出目录中的所有文件,除了原始文件名的文件。如果成功,则返回 {ok, Filenames},否则返回 {error, Reason}Filenames 是目录中所有文件的名称列表。这些名称未排序。

列出目录中的所有文件,包括具有原始文件名的文件。如果成功,则返回 {ok, Filenames},否则返回 {error, Reason}Filenames 是目录中所有文件的名称列表。这些名称未排序。

尝试创建目录 Dir。不会创建缺失的父目录。如果成功,则返回 ok

在支持链接的平台(Unix 和 Windows)上,创建从 ExistingNew 的硬链接。如果成功创建了链接,则此函数返回 ok,否则返回 {error, Reason}。在不支持链接的平台上,返回 {error,enotsup}

在支持符号链接的平台(大多数 Unix 系统和从 Vista 开始的 Windows)上,创建指向文件或目录 Existing 的符号链接 NewExisting 不需要存在。如果成功创建了链接,则返回 ok,否则返回 {error, Reason}。在不支持符号链接的平台上,返回 {error, enotsup}

返回文件名编码模式。如果它是 latin1,系统不会转换任何文件名。如果它是 utf8,则文件名会来回转换为本机文件名编码(通常为 UTF-8,但在 Windows 上为 UTF-16)。

Modes 确定的模式打开文件 File,其中 Modes 可以包含以下一个或多个选项

搜索路径 Path(目录名称列表),直到找到文件 Filename。如果 Filename 是绝对文件名,则忽略 Path。然后从文件中读取以 . 分隔的 Erlang 项。

搜索路径 Path(目录名称列表),直到找到文件 Filename。如果 Filename 是绝对文件名,则忽略 Path。然后从文件中读取并计算以 .(或 ,,表达式序列也是一个表达式)分隔的 Erlang 表达式。不返回求值结果;文件中任何表达式序列都必须用于其副作用。

搜索路径 Path(目录名称列表),直到找到文件 Filename。如果 Filename 是绝对文件名,则忽略 Path。然后以 Modes 确定的模式打开文件。

搜索路径 Path(目录名称列表),直到找到文件 Filename。如果 Filename 是绝对文件名,则忽略 Path。然后从文件中读取并计算以 .(或 ,,表达式序列也是一个表达式)分隔的 Erlang 表达式。

path_script/2 相同,但在求值时使用变量绑定 Bindings。有关变量绑定的信息,请参阅 erl_eval

IoDevice 引用的文件的位置设置为 Location。如果成功,则返回 {ok, NewPosition}(作为绝对偏移量),否则返回 {error, Reason}Location 是以下之一

在一个操作中执行一系列 pread/3,这比一次调用一个效率更高。返回 {ok, [Data, ...]}{error, Reason},其中每个 Data(对应 pread 的结果)要么是列表,要么是二进制数据(取决于文件模式),如果请求的位置超出文件末尾,则为 eof

在一个操作中组合 position/2read/2,这比一次调用一个效率更高。

在一个操作中执行一系列 pwrite/3,这比一次调用一个效率更高。返回 ok{error, {N, Reason}},其中 N 是失败前完成的成功写入次数。

在一个操作中组合 position/2write/2,这比一次调用一个效率更高。

IoDevice 引用的文件中读取 Number 个字节/字符。

返回 {ok, Binary},其中 Binary 是一个二进制数据对象,包含 Filename 的内容,如果发生错误,则返回 {error, Reason}

检索有关文件的信息。如果成功,则返回 {ok, FileInfo},否则返回 {error, Reason}

IoDevice 引用的文件中读取一行字节/字符。

如果 Name 指的是非原始文件名的符号链接,则返回 {ok, Filename},否则返回 {error, Reason}。在不支持符号链接的平台上,返回值是 {error,enotsup}

如果 Name 指的是符号链接,则返回 {ok, Filename},否则返回 {error, Reason}。在不支持符号链接的平台上,返回值是 {error,enotsup}

read_file_info/1,2 的工作方式相同,但如果 Name 是符号链接,则有关该链接的信息将返回到 file_info 记录中,并且记录的 type 字段设置为 symlink

尝试将文件 Source 重命名为 Destination。它可以用于在目录之间移动文件(和目录),但仅指定目标是不够的。还必须指定目标文件名。例如,如果 bar 是一个普通文件,foobaz 是目录,则 rename("foo/bar", "baz") 返回错误,但 rename("foo/bar", "baz/bar") 成功。如果成功,则返回 ok

从文件中读取并计算以 .(或 ,,表达式序列也是一个表达式)分隔的 Erlang 表达式。

script/1 相同,但在求值时使用变量绑定 Bindings。有关变量绑定的信息,请参阅 erl_eval

将文件 Filename 发送到 Socket。如果成功,则返回 {ok, BytesSent},否则返回 {error, Reason}

将从 RawFile 引用的文件中,从 Offset 开始的 Bytes 发送到 Socket。如果成功,则返回 {ok, BytesSent},否则返回 {error, Reason}。如果 Bytes 设置为 0,则会发送指定 Offset 之后的所有数据。

将文件服务器的当前工作目录设置为 Dir。如果成功,则返回 ok

确保操作系统(而不是 Erlang 运行时系统)保留的任何缓冲区都写入磁盘。在某些平台上,此函数可能不起作用。

在当前位置截断 IoDevice 引用的文件。如果成功,则返回 ok,否则返回 {error, Reason}

Bytes 写入 IoDevice 引用的文件。此函数是写入以 raw 模式打开的文件的唯一方法(尽管它也适用于正常打开的文件)。如果成功,则返回 ok,否则返回 {error, Reason}

iodataBytes 的内容写入文件 Filename。如果文件不存在,则创建该文件。如果文件存在,则会覆盖先前的内容。如果成功,则返回 ok,否则返回 {error, Reason}

write_file/2 相同,但采用第三个参数 Modes(可能的模式列表),请参阅 open/2。模式标志 binarywrite 是隐式的,因此不应使用它们。

更改文件信息。如果成功,则返回 ok,否则返回 {error, Reason}

类型

-type date_time() :: calendar:datetime().

必须表示有效的日期和时间。

此类型的链接

deep_list()

查看源 (未导出)
-type deep_list() :: [char() | atom() | deep_list()].
此类型的链接

delete_option()

查看源代码 (未导出)
-type delete_option() :: raw.
-type fd() :: file_descriptor().

一个文件描述符,表示以 raw 模式打开的文件。

-type file_info() ::
          #file_info{size :: non_neg_integer() | undefined,
                     type :: device | directory | other | regular | symlink | undefined,
                     access :: read | write | read_write | none | undefined,
                     atime :: file:date_time() | non_neg_integer() | undefined,
                     mtime :: file:date_time() | non_neg_integer() | undefined,
                     ctime :: file:date_time() | non_neg_integer() | undefined,
                     mode :: non_neg_integer() | undefined,
                     links :: non_neg_integer() | undefined,
                     major_device :: non_neg_integer() | undefined,
                     minor_device :: non_neg_integer() | undefined,
                     inode :: non_neg_integer() | undefined,
                     uid :: non_neg_integer() | undefined,
                     gid :: non_neg_integer() | undefined}.
此类型的链接

file_info_option()

查看源代码 (未导出)
-type file_info_option() :: {time, local} | {time, universal} | {time, posix} | raw.
-type filename() :: string().

file API 函数返回的文件名。

请参阅 name_all/0 类型的文档。

-type filename_all() :: string() | (RawFilename :: binary()).

file API 函数返回的文件名。

请参阅 name_all/0 类型的文档。

-type io_device() :: io_server() | fd().

open/2 返回的 IO 设备。

默认返回 io_server/0,如果给定 raw 选项,则返回 fd/0

-type io_server() :: pid().

处理 I/O 协议的进程。

-type location() ::
          integer() |
          {bof, Offset :: integer()} |
          {cur, Offset :: integer()} |
          {eof, Offset :: integer()} |
          bof | cur | eof.
-type mode() ::
          read | write | append | exclusive | raw | binary |
          {delayed_write, Size :: non_neg_integer(), Delay :: non_neg_integer()} |
          delayed_write |
          {read_ahead, Size :: pos_integer()} |
          read_ahead | compressed | compressed_one |
          {encoding, unicode:encoding()} |
          sync.
-type name() :: string() | atom() | deep_list().

用作 file API 函数输入的受限文件名。

如果虚拟机处于 Unicode 文件名模式,则允许 string/0char/0 大于 255。另请参阅 name_all/0 类型的文档。

-type name_all() :: string() | atom() | deep_list() | (RawFilename :: binary()).

用作 file API 函数输入的文件名。

如果虚拟机处于 Unicode 文件名模式,则允许字符大于 255。RawFilename 是不受 Unicode 转换的文件名,这意味着它可以包含不符合文件系统预期 Unicode 编码的字符(即,即使虚拟机以 Unicode 文件名模式启动,也可能包含非 UTF-8 字符)。空字符(整数值零)在文件名中是不允许的(即使在末尾也不允许)。

-type posix() ::
          eacces | eagain | ebadf | ebadmsg | ebusy | edeadlk | edeadlock | edquot | eexist | efault |
          efbig | eftype | eintr | einval | eio | eisdir | eloop | emfile | emlink | emultihop |
          enametoolong | enfile | enobufs | enodev | enolck | enolink | enoent | enomem | enospc |
          enosr | enostr | enosys | enotblk | enotdir | enotsup | enxio | eopnotsupp | eoverflow |
          eperm | epipe | erange | erofs | espipe | esrch | estale | etxtbsy | exdev.

一个原子,其名称来自 Unix 中使用的 POSIX 错误代码以及大多数 C 编译器的运行时库。

此类型的链接

posix_file_advise()

查看源代码 (未导出)
-type posix_file_advise() :: normal | sequential | random | no_reuse | will_need | dont_need.
此类型的链接

read_file_option()

查看源代码 (未导出)
-type read_file_option() :: raw.
此类型的链接

sendfile_option()

查看源代码 (未导出)
-type sendfile_option() :: {chunk_size, non_neg_integer()} | {use_threads, boolean()}.

函数

链接到此函数

advise(IoDevice, Offset, Length, Advise)

查看源代码 (自 OTP R14B 起)
-spec advise(IoDevice, Offset, Length, Advise) -> ok | {error, Reason}
                when
                    IoDevice :: io_device(),
                    Offset :: integer(),
                    Length :: integer(),
                    Advise :: posix_file_advise(),
                    Reason :: posix() | badarg.

advise/4 可用于声明未来以特定模式访问文件数据的意图,从而允许操作系统执行适当的优化。

在某些平台上,此函数可能不起作用。

链接到此函数

allocate(File, Offset, Length)

查看源代码 (自 OTP R16B 起)
-spec allocate(File, Offset, Length) -> ok | {error, posix()}
                  when File :: io_device(), Offset :: non_neg_integer(), Length :: non_neg_integer().

allocate/3 可用于为文件预分配空间。

此函数仅在提供此功能的平台上成功。

链接到此函数

change_group(Filename, Gid)

查看源
-spec change_group(Filename, Gid) -> ok | {error, Reason}
                      when Filename :: name_all(), Gid :: integer(), Reason :: posix() | badarg.

更改文件的组。请参阅 write_file_info/2

链接到此函数

change_mode(Filename, Mode)

查看源代码 (自 OTP R14B 起)
-spec change_mode(Filename, Mode) -> ok | {error, Reason}
                     when Filename :: name_all(), Mode :: integer(), Reason :: posix() | badarg.

更改文件的权限。请参阅 write_file_info/2

链接到此函数

change_owner(Filename, Uid)

查看源
-spec change_owner(Filename, Uid) -> ok | {error, Reason}
                      when Filename :: name_all(), Uid :: integer(), Reason :: posix() | badarg.

更改文件的所有者。请参阅 write_file_info/2

链接到此函数

change_owner(Filename, Uid, Gid)

查看源
-spec change_owner(Filename, Uid, Gid) -> ok | {error, Reason}
                      when
                          Filename :: name_all(),
                          Uid :: integer(),
                          Gid :: integer(),
                          Reason :: posix() | badarg.

更改文件的所有者和组。请参阅 write_file_info/2

链接到此函数

change_time(Filename, Mtime)

查看源
-spec change_time(Filename, Mtime) -> ok | {error, Reason}
                     when Filename :: name_all(), Mtime :: date_time(), Reason :: posix() | badarg.

更改文件的修改时间和访问时间。请参阅 write_file_info/2

链接到此函数

change_time(Filename, Atime, Mtime)

查看源
-spec change_time(Filename, Atime, Mtime) -> ok | {error, Reason}
                     when
                         Filename :: name_all(),
                         Atime :: date_time(),
                         Mtime :: date_time(),
                         Reason :: posix() | badarg.

更改文件的修改时间和上次访问时间。请参阅 write_file_info/2

-spec close(IoDevice) -> ok | {error, Reason}
               when IoDevice :: io_device(), Reason :: posix() | badarg | terminated.

关闭 IoDevice 引用的文件。它大多返回 ok,除了某些严重的错误,例如内存不足。

请注意,如果在打开文件时使用了 delayed_write 选项,则 close/1 可能会返回旧的写入错误,甚至不会尝试关闭文件。请参阅 open/2

-spec consult(Filename) -> {ok, Terms} | {error, Reason}
                 when
                     Filename :: name_all(),
                     Terms :: [term()],
                     Reason ::
                         posix() |
                         badarg | terminated | system_limit |
                         {Line :: integer(), Mod :: module(), Term :: term()}.

Filename 读取以 . 分隔的 Erlang 术语。返回以下内容之一

  • {ok, Terms} - 文件已成功读取。

  • {error, atom()} - 打开文件或读取文件时发生错误。有关典型错误代码的列表,请参阅 open/2

  • {error, {Line, Mod, Term}} - 在解释文件中的 Erlang 项时发生错误。要将三元素元组转换为错误英文描述,请使用 format_error/1

示例

f.txt:  {person, "kalle", 25}.
        {person, "pelle", 30}.
1> file:consult("f.txt").
{ok,[{person,"kalle",25},{person,"pelle",30}]}

可以使用注释设置 Filename 的编码,如 epp 中所述。

链接到此函数

copy(Source, Destination)

查看源
-spec copy(Source, Destination) -> {ok, BytesCopied} | {error, Reason}
              when
                  Source :: io_device() | Filename | {Filename, Modes},
                  Destination :: io_device() | Filename | {Filename, Modes},
                  Filename :: name_all(),
                  Modes :: [mode()],
                  BytesCopied :: non_neg_integer(),
                  Reason :: posix() | badarg | terminated.

等效于 copy(Source, Destination, infinity)

链接到此函数

copy(Source, Destination, ByteCount)

查看源
-spec copy(Source, Destination, ByteCount) -> {ok, BytesCopied} | {error, Reason}
              when
                  Source :: io_device() | Filename | {Filename, Modes},
                  Destination :: io_device() | Filename | {Filename, Modes},
                  Filename :: name_all(),
                  Modes :: [mode()],
                  ByteCount :: non_neg_integer() | infinity,
                  BytesCopied :: non_neg_integer(),
                  Reason :: posix() | badarg | terminated.

Source 复制 ByteCount 字节到 DestinationSourceDestination 指的是文件名或 IO 设备,例如,来自 open/2

参数 Modes 是可能的模式列表,请参阅 open/2,默认为 []

如果 SourceDestination 都引用文件名,则分别在其模式列表的前面加上 [read, binary][write, binary] 打开文件,以优化复制。

如果 Source 引用文件名,则在复制之前,会将其模式列表的前面加上 read 模式打开,并在完成后关闭。

如果 Destination 引用文件名,则在复制之前,会将其模式列表的前面加上 write 模式打开,并在完成后关闭。

返回 {ok, BytesCopied},其中 BytesCopied 是复制的字节数,如果源上遇到文件结尾,则该值可能小于 ByteCount。如果操作失败,则返回 {error, Reason}

典型的错误原因:如果必须打开文件,则与 open/2 相同,与 read/2write/2 相同。

链接到此函数

datasync(IoDevice)

查看源代码 (自 OTP R14B 起)
-spec datasync(IoDevice) -> ok | {error, Reason}
                  when IoDevice :: io_device(), Reason :: posix() | badarg | terminated.

确保操作系统(而不是 Erlang 运行时系统)保留的任何缓冲区都写入磁盘。它在许多方面类似于 fsync,但它不会更新文件的某些元数据,例如访问时间。在某些平台上,此函数不起作用。

访问数据库或日志文件的应用程序通常会写入一个很小的数据片段(例如,日志文件中的一行),然后立即调用 fsync() 以确保写入的数据已物理存储在硬盘上。不幸的是,fsync() 始终会启动两个写操作:一个用于新写入的数据,另一个用于更新存储在 inode 中的修改时间。如果修改时间不是事务概念的一部分,则可以使用 fdatasync() 来避免不必要的 inode 磁盘写操作。

仅在某些 POSIX 系统中可用,此调用会导致调用 fsync(),或者在不提供 fdatasync() 系统调用的系统中无效。

-spec del_dir(Dir) -> ok | {error, Reason} when Dir :: name_all(), Reason :: posix() | badarg.

尝试删除目录 Dir。该目录必须为空才能删除。如果成功,则返回 ok

典型的错误原因

  • eacces - 缺少 Dir 的父目录的搜索或写入权限。

  • eexist - 该目录不为空。

  • enoent - 该目录不存在。

  • enotdir - Dir 的组件不是目录。在某些平台上,返回 enoent

  • einval - 尝试删除当前目录。在某些平台上,返回 eacces

链接到此函数

del_dir_r(File)

查看源代码 (自 OTP 23.0 起)
-spec del_dir_r(File) -> ok | {error, Reason} when File :: name_all(), Reason :: posix() | badarg.

删除文件或目录 File。如果 File 是一个目录,则首先递归删除其内容。返回

  • ok - 操作完成,没有错误。

  • {error, posix()} - 访问或删除 File 时发生错误。如果无法删除 File 下的某些文件或目录,则无法删除 File,因为它不是空的,并返回 {error, eexist}

-spec delete(Filename) -> ok | {error, Reason} when Filename :: name_all(), Reason :: posix() | badarg.

等效于 delete(Filename, [])

链接到此函数

delete(Filename, Opts)

查看源代码 (自 OTP 24.0 起)
-spec delete(Filename, Opts) -> ok | {error, Reason}
                when Filename :: name_all(), Opts :: [delete_option()], Reason :: posix() | badarg.

尝试删除文件 Filename。如果成功,则返回 ok

如果设置了 raw 选项,则不会调用文件服务器。这在文件服务器尚未注册的早期引导阶段尤其有用,以便仍然能够删除本地文件。

典型的错误原因

  • enoent - 该文件不存在。

  • eacces - 缺少文件或其父级之一的权限。

  • eperm - 该文件是一个目录,并且用户不是超级用户。

  • enotdir - 文件名的组件不是目录。在某些平台上,返回 enoent

  • einval - Filename 的类型不正确,例如元组。

警告

在未来的版本中,参数 Filename 的错误类型可能会生成异常。

-spec eval(Filename) -> ok | {error, Reason}
              when
                  Filename :: name_all(),
                  Reason ::
                      posix() |
                      badarg | terminated | system_limit |
                      {Line :: integer(), Mod :: module(), Term :: term()}.

Filename 读取和评估以 .(或 ,,表达式序列也是一个表达式)分隔的 Erlang 表达式。不会返回评估的结果;文件中的任何表达式序列都必须存在以产生副作用。

返回以下其中一项

  • ok - 已读取并评估该文件。

  • {error, atom()} - 打开文件或读取文件时发生错误。有关典型错误代码的列表,请参阅 open/2

  • {error, {Line, Mod, Term}} - 在解释文件中的 Erlang 表达式时发生错误。要将三元素元组转换为错误的英文描述,请使用 format_error/1

可以使用注释设置 Filename 的编码,如 epp 中所述。

链接到此函数

eval(Filename, Bindings)

查看源
-spec eval(Filename, Bindings) -> ok | {error, Reason}
              when
                  Filename :: name_all(),
                  Bindings :: erl_eval:binding_struct(),
                  Reason ::
                      posix() |
                      badarg | terminated | system_limit |
                      {Line :: integer(), Mod :: module(), Term :: term()}.

eval/1 相同,但在求值时使用变量绑定 Bindings。有关变量绑定的信息,请参阅 erl_eval

链接到此函数

format_error(Reason)

查看源
-spec format_error(Reason) -> Chars
                      when
                          Reason ::
                              posix() |
                              badarg | terminated | system_limit |
                              {Line :: integer(), Mod :: module(), Term :: term()},
                          Chars :: string().

给定此模块中任何函数返回的错误原因,返回描述错误的英文字符串。

-spec get_cwd() -> {ok, Dir} | {error, Reason} when Dir :: filename(), Reason :: posix().

返回 {ok, Dir},其中 Dir 是文件服务器的当前工作目录。

注意

在极少数情况下,此函数在 Unix 上可能会失败。如果当前目录的父目录不存在读取权限,则可能会发生这种情况。

典型的错误原因

  • eacces - 缺少当前目录的父目录之一的读取权限。
-spec get_cwd(Drive) -> {ok, Dir} | {error, Reason}
                 when Drive :: string(), Dir :: filename(), Reason :: posix() | badarg.

返回 {ok, Dir}{error, Reason},其中 Dir 是指定驱动器的当前工作目录。

Drive 的形式应为 Letter:,例如 c:

在没有当前驱动器概念的平台(例如,Unix)上返回 {error, enotsup}

典型的错误原因

  • enotsup - 操作系统没有驱动器的概念。

  • eacces - 该驱动器不存在。

  • einval - Drive 的格式无效。

-spec list_dir(Dir) -> {ok, Filenames} | {error, Reason}
                  when
                      Dir :: name_all(),
                      Filenames :: [filename()],
                      Reason :: posix() | badarg | {no_translation, Filename :: unicode:latin1_binary()}.

列出目录中的所有文件,除了原始文件名的文件。如果成功,则返回 {ok, Filenames},否则返回 {error, Reason}Filenames 是目录中所有文件的名称列表。这些名称未排序。

典型的错误原因

  • eacces - 缺少 Dir 或其父目录之一的搜索或写入权限。

  • enoent - 该目录不存在。

  • {no_translation, Filename} - Filename 是一个以 ISO Latin-1 编码的字符的 binary/0,并且虚拟机以参数 +fnue 启动。

链接到此函数

list_dir_all(Dir)

查看源代码 (自 OTP R16B 起)
-spec list_dir_all(Dir) -> {ok, Filenames} | {error, Reason}
                      when Dir :: name_all(), Filenames :: [filename_all()], Reason :: posix() | badarg.

列出目录中的所有文件,包括带有原始文件名的文件。如果成功,则返回 {ok, Filenames},否则返回 {error, Reason}Filenames 是目录中所有文件的名称列表。这些名称未排序。

典型的错误原因

  • eacces - 缺少 Dir 或其父目录之一的搜索或写入权限。

  • enoent - 该目录不存在。

-spec make_dir(Dir) -> ok | {error, Reason} when Dir :: name_all(), Reason :: posix() | badarg.

尝试创建目录 Dir。不会创建缺失的父目录。如果成功,则返回 ok

典型的错误原因

  • eacces - 缺少 Dir 的父目录的搜索或写入权限。

  • eexist - 名为 Dir 的文件或目录已存在。

  • enoent - Dir 的组件不存在。

  • enospc - 设备上没有剩余空间。

  • enotdir - Dir 的组件不是目录。在某些平台上,返回 enoent

链接到此函数

make_link(Existing, New)

查看源
-spec make_link(Existing, New) -> ok | {error, Reason}
                   when Existing :: name_all(), New :: name_all(), Reason :: posix() | badarg.

在支持链接的平台(Unix 和 Windows)上,创建从 ExistingNew 的硬链接。如果成功创建了链接,则此函数返回 ok,否则返回 {error, Reason}。在不支持链接的平台上,返回 {error,enotsup}

典型的错误原因

  • eacces - 缺少对 ExistingNew 的父目录的读取或写入权限。

  • eexist - New 已经存在。

  • enotsup - 此平台不支持硬链接。

链接到此函数

make_symlink(Existing, New)

查看源
-spec make_symlink(Existing, New) -> ok | {error, Reason}
                      when Existing :: name_all(), New :: name_all(), Reason :: posix() | badarg.

在支持符号链接的平台(大多数 Unix 系统和从 Vista 开始的 Windows)上,创建指向文件或目录 Existing 的符号链接 NewExisting 不需要存在。如果成功创建了链接,则返回 ok,否则返回 {error, Reason}。在不支持符号链接的平台上,返回 {error, enotsup}

典型的错误原因

  • eacces - 缺少对 ExistingNew 的父目录的读取或写入权限。

  • eexist - New 已经存在。

  • enotsup - 此平台不支持符号链接。

  • eperm - 用户没有创建符号链接的权限(Windows 上为 SeCreateSymbolicLinkPrivilege)。

链接到此函数

native_name_encoding()

查看源代码 (自 OTP R14B01 起)
-spec native_name_encoding() -> latin1 | utf8.

返回文件名编码模式。如果为 latin1,则系统不转换文件名。如果为 utf8,则文件名会与本地文件名编码(通常为 UTF-8,但在 Windows 上为 UTF-16)之间来回转换。

-spec open(File, Modes) -> {ok, IoDevice} | {error, Reason}
              when
                  File :: Filename | iodata(),
                  Filename :: name_all(),
                  Modes :: [mode() | ram | directory],
                  IoDevice :: io_device(),
                  Reason :: posix() | badarg | system_limit.

Modes 确定的模式打开文件 File,其中 Modes 可以包含以下一个或多个选项

  • read - 打开文件以进行读取,文件必须存在。

  • write - 打开文件以进行写入。如果文件不存在,则会创建该文件。如果文件存在并且 write 未与 read 组合使用,则会截断该文件。

  • append - 打开文件以进行写入。如果文件不存在,则会创建该文件。每次对以 append 方式打开的文件执行写入操作时,都会在文件末尾进行。

  • exclusive - 打开文件以进行写入。如果文件不存在,则会创建该文件。如果文件存在,则返回 {error, eexist}

    警告

    此选项不保证在不支持 O_EXCL 的文件系统(如 NFS)上的独占性。除非您知道文件系统支持它(一般来说,本地文件系统是安全的),否则请不要依赖此选项。

  • raw - 允许更快地访问文件,因为不需要 Erlang 进程来处理文件。但是,以这种方式打开的文件有以下限制:

    • io 模块中的函数不能使用,因为它们只能与 Erlang 进程通信。而是使用函数 read/2read_line/1write/2
    • 特别是如果要在 raw 文件上使用 read_line/1,建议将此选项与选项 {read_ahead, Size} 结合使用,因为没有缓冲的面向行的 I/O 效率较低。
    • 只有打开该文件的 Erlang 进程才能使用它。
    • 不能使用远程 Erlang 文件服务器。运行 Erlang 节点的计算机必须可以访问文件系统(直接或通过 NFS)。
  • binary - 对文件执行读取操作时返回二进制数据而不是列表。

  • {delayed_write, Size, Delay} - 后续 write/2 调用中的数据会被缓冲,直到缓冲至少 Size 个字节,或者直到最早的缓冲数据达到 Delay 毫秒。然后,所有缓冲数据在一个操作系统调用中写入。在执行其他文件操作(而非 write/2)之前,缓冲数据也会被刷新。

    此选项的目的是通过减少操作系统调用的次数来提高性能。因此,write/2 调用的数据大小必须明显小于 Size,并且不能穿插太多其他文件操作。

    使用此选项时,write/2 调用的结果可能会提前报告为成功,如果发生写入错误,则该错误将报告为下一个文件操作的结果,而该操作不会执行。

    例如,当使用 delayed_write 时,在多次调用 write/2 后,close/1 可能会返回 {error, enospc},因为磁盘上没有足够的空间来存储先前写入的数据。close/1 可能必须再次调用,因为文件仍然处于打开状态。

  • delayed_write - 与 {delayed_write, Size, Delay} 相同,但 SizeDelay 使用合理的默认值(大约 64 KB,2 秒)。

  • {read_ahead, Size} - 激活读取数据缓冲。如果 read/2 调用的字节数明显小于 Size,则仍会针对 Size 字节的块执行对操作系统的读取操作。额外的未读数据会被缓冲,并在后续 read/2 调用中返回,从而减少操作系统调用的次数,提高性能。

    read_ahead 缓冲区也被函数 read_line/1raw 模式下大量使用,因此,当使用该函数访问原始文件时,建议使用此选项(出于性能考虑)。

    如果 read/2 调用的字节数不明显小于,甚至大于 Size 字节,则无法获得性能提升。

  • read_ahead - 与 {read_ahead, Size} 相同,但 Size 使用合理的默认值(大约 64 KB)。

  • compressed - 使读取或写入 gzip 压缩文件成为可能。选项 compressed 必须与 readwrite 组合使用,但不能同时使用。请注意,使用 read_file_info/1 获取的文件大小可能与可以从压缩文件中读取的字节数不匹配。

  • compressed_one - 读取 gzip 压缩文件的一个成员。选项 compressed_one 只能与 read 组合使用。

  • {encoding, Encoding} - 使文件能够自动将字符转换为特定(Unicode)编码,并从中转换。请注意,提供给 write/2 或由 read/2 返回的数据仍然是面向字节的;此选项仅表示数据如何存储在磁盘文件中。

    根据编码的不同,首选不同的读取和写入数据的方法。latin1 的默认编码意味着使用此模块(file)进行数据的读取和写入,因为此处提供的接口使用面向字节的数据。使用其他(Unicode)编码使 io 函数 get_charsget_lineput_chars 更合适,因为它们可以使用完整的 Unicode 范围。

    如果将无法转换为指定编码的格式的数据发送到 io_device/0,或者如果由返回的数据的格式无法处理数据字符范围的函数读取数据,则会发生错误并关闭该文件。

    Encoding 的允许值:

    • latin1 - 默认编码。提供给文件的字节(即 write/2)会“按原样”写入文件。同样,从文件读取的字节(即 read/2)也会“按原样”返回。如果使用模块 io 进行写入,则该文件只能处理代码点不超过 255 的 Unicode 字符(ISO Latin-1 范围)。

    • unicodeutf8 - 字符在写入文件或从文件读取之前会转换为 UTF-8 编码。以这种方式打开的文件可以使用函数 read/2 读取,只要存储在文件上的数据不超过 ISO Latin-1 范围 (0..255),但是如果数据包含超出该范围的 Unicode 代码点,则会发生故障。最好使用 Unicode 感知模块 io 中的函数读取文件。

      通过任何方式写入文件的字节都会转换为 UTF-8 编码,然后存储在磁盘文件中。

    • utf16{utf16,big} - 工作方式类似于 unicode,但转换为大端 UTF-16 而不是 UTF-8。

    • {utf16,little} - 工作方式类似于 unicode,但转换为小端 UTF-16 而不是 UTF-8。

    • utf32{utf32,big} - 工作方式类似于 unicode,但转换为大端 UTF-32 而不是 UTF-8。

    • {utf32,little} - 工作方式类似于 unicode,但转换为小端 UTF-32 而不是 UTF-8。

    可以使用函数 io:setopts/2 “动态”更改文件的编码。因此,可以例如在 latin1 编码中分析文件以获取 BOM,将位置置于 BOM 之外,然后在进一步读取之前设置为正确的编码。有关识别 BOM 的函数,请参阅模块 unicode

    此选项不允许用于 raw 文件。

  • ram - File 必须为 iodata/0。返回一个 fd/0,它使模块 file 能够像操作文件一样操作内存中的数据。

  • sync - 在支持它的平台上,启用 POSIX O_SYNC 同步 I/O 标志或其平台相关的等效项(例如,Windows 上的 FILE_FLAG_WRITE_THROUGH),以便在数据物理写入磁盘之前,对文件的写入操作会被阻止。但是,请注意,此标志的确切语义因平台而异。例如,Linux 或 Windows 都不能保证在调用返回之前也会写入所有文件元数据。对于精确的语义,请检查平台文档的详细信息。在不支持 POSIX O_SYNC 或等效项的平台上,使用 sync 标志会导致 open 返回 {error, enotsup}

  • directory - 允许 open 在目录上工作。

返回:

  • {ok, IoDevice} - 文件以请求的模式打开。IoDevice 是对文件的引用。

  • {error, Reason} - 无法打开文件。

IoDevice 实际上是处理该文件的进程的 pid。此进程会监视最初打开该文件的进程(所有者进程)。如果所有者进程终止,则该文件将关闭,并且该进程本身也会终止。从此调用返回的 IoDevice 可用作 I/O 函数的参数(请参阅 io)。

警告

虽然此函数可用于打开任何文件,但我们不建议将其用于 NFS 挂载的文件、FIFO、设备或类似文件,因为它们可能会导致 IO 线程永远挂起。

如果您的应用程序需要与这些类型的文件进行交互,我们建议将这些部分分解为端口程序。

注意

在之前的 file 版本中,模式被指定为原子 readwriteread_write 中的一个,而不是列表。为了向后兼容,仍然允许这种方式,但不应在新代码中使用。另请注意,read_write 不允许在模式列表中使用。

典型的错误原因

  • enoent - 该文件不存在。

  • eacces - 缺少读取文件或搜索父目录之一的权限。

  • eisdir - 指定的文件是一个目录。

  • enotdir - 文件名的组成部分不是目录,或者如果指定了 directory 模式,则文件名本身不是目录。在某些平台上,会返回 enoent

  • enospc - 设备上没有剩余空间(如果指定了 write 访问权限)。

链接到此函数

path_consult(Path, Filename)

查看源
-spec path_consult(Path, Filename) -> {ok, Terms, FullName} | {error, Reason}
                      when
                          Path :: [Dir],
                          Dir :: name_all(),
                          Filename :: name_all(),
                          Terms :: [term()],
                          FullName :: filename_all(),
                          Reason ::
                              posix() |
                              badarg | terminated | system_limit |
                              {Line :: integer(), Mod :: module(), Term :: term()}.

搜索路径 Path(目录名称列表),直到找到文件 Filename。如果 Filename 是绝对文件名,则忽略 Path。然后从文件中读取以 . 分隔的 Erlang 项。

返回以下其中一项

  • {ok, Terms, FullName} - 文件读取成功。FullName 是文件的完整名称。

  • {error, enoent} - 在 Path 中的任何目录中都找不到该文件。

  • {error, atom()} - 打开文件或读取文件时发生错误。有关典型错误代码的列表,请参阅 open/2

  • {error, {Line, Mod, Term}} - 解释文件中的 Erlang 项时发生错误。使用 format_error/1 将三元素元组转换为错误的英文描述。

Filename 的编码可以通过注释进行设置,如 epp 中所述。

链接到此函数

path_eval(Path, Filename)

查看源
-spec path_eval(Path, Filename) -> {ok, FullName} | {error, Reason}
                   when
                       Path :: [Dir :: name_all()],
                       Filename :: name_all(),
                       FullName :: filename_all(),
                       Reason ::
                           posix() |
                           badarg | terminated | system_limit |
                           {Line :: integer(), Mod :: module(), Term :: term()}.

搜索路径 Path(目录名称列表),直到找到文件 Filename。如果 Filename 是绝对文件名,则忽略 Path。然后从文件中读取并计算以 .(或 ,,表达式序列也是一个表达式)分隔的 Erlang 表达式。不返回求值结果;文件中任何表达式序列都必须用于其副作用。

返回以下其中一项

  • {ok, FullName} - 文件已读取并求值。FullName 是文件的完整名称。

  • {error, enoent} - 在 Path 中的任何目录中都找不到该文件。

  • {error, atom()} - 打开文件或读取文件时发生错误。有关典型错误代码的列表,请参阅 open/2

  • {error, {Line, Mod, Term}} - 解释文件中的 Erlang 表达式时发生错误。使用 format_error/1 将三元素元组转换为错误的英文描述。

Filename 的编码可以通过注释进行设置,如 epp 中所述。

链接到此函数

path_open(Path, Filename, Modes)

查看源
-spec path_open(Path, Filename, Modes) -> {ok, IoDevice, FullName} | {error, Reason}
                   when
                       Path :: [Dir :: name_all()],
                       Filename :: name_all(),
                       Modes :: [mode() | directory],
                       IoDevice :: io_device(),
                       FullName :: filename_all(),
                       Reason :: posix() | badarg | system_limit.

搜索路径 Path(目录名称列表),直到找到文件 Filename。如果 Filename 是绝对文件名,则忽略 Path。然后以 Modes 确定的模式打开文件。

返回以下其中一项

  • {ok, IoDevice, FullName} - 文件以请求的模式打开。IoDevice 是对文件的引用,FullName 是文件的完整名称。

  • {error, enoent} - 在 Path 中的任何目录中都找不到该文件。

  • {error, atom()} - 无法打开文件。

链接到此函数

path_script(Path, Filename)

查看源
-spec path_script(Path, Filename) -> {ok, Value, FullName} | {error, Reason}
                     when
                         Path :: [Dir :: name_all()],
                         Filename :: name_all(),
                         Value :: term(),
                         FullName :: filename_all(),
                         Reason ::
                             posix() |
                             badarg | terminated | system_limit |
                             {Line :: integer(), Mod :: module(), Term :: term()}.

搜索路径 Path(目录名称列表),直到找到文件 Filename。如果 Filename 是绝对文件名,则忽略 Path。然后从文件中读取并计算以 .(或 ,,表达式序列也是一个表达式)分隔的 Erlang 表达式。

返回以下其中一项

  • {ok, Value, FullName} - 文件已读取并求值。FullName 是文件的完整名称,Value 是最后一个表达式的值。

  • {error, enoent} - 在 Path 中的任何目录中都找不到该文件。

  • {error, atom()} - 打开文件或读取文件时发生错误。有关典型错误代码的列表,请参阅 open/2

  • {error, {Line, Mod, Term}} - 解释文件中的 Erlang 表达式时发生错误。使用 format_error/1 将三元素元组转换为错误的英文描述。

Filename 的编码可以通过注释进行设置,如 epp 中所述。

链接到此函数

path_script(Path, Filename, Bindings)

查看源
-spec path_script(Path, Filename, Bindings) -> {ok, Value, FullName} | {error, Reason}
                     when
                         Path :: [Dir :: name_all()],
                         Filename :: name_all(),
                         Bindings :: erl_eval:binding_struct(),
                         Value :: term(),
                         FullName :: filename_all(),
                         Reason ::
                             posix() |
                             badarg | terminated | system_limit |
                             {Line :: integer(), Mod :: module(), Term :: term()}.

path_script/2 相同,但在求值时使用变量绑定 Bindings。有关变量绑定的信息,请参阅 erl_eval

链接到此函数

position(IoDevice, Location)

查看源
-spec position(IoDevice, Location) -> {ok, NewPosition} | {error, Reason}
                  when
                      IoDevice :: io_device(),
                      Location :: location(),
                      NewPosition :: integer(),
                      Reason :: posix() | badarg | terminated.

IoDevice 引用的文件的位置设置为 Location。如果成功,则返回 {ok, NewPosition}(作为绝对偏移量),否则返回 {error, Reason}Location 是以下之一

  • Offset - 与 {bof, Offset} 相同。

  • {bof, Offset} - 绝对偏移量。

  • {cur, Offset} - 从当前位置的偏移量。

  • {eof, Offset} - 从文件末尾的偏移量。

  • bof | cur | eof - 与上面相同,但 Offset 为 0。

请注意,偏移量以字节为单位计数,而不是以字符为单位。如果使用 latin1 以外的其他 encoding 打开文件,则一个字节不对应一个字符。在此类文件中进行定位只能在已知的字符边界上进行。也就是说,可以定位到先前通过获取当前位置检索到的位置、文件的开头/结尾,或者通过其他方式(通常超出文件中具有已知字节大小的字节顺序标记)已知在正确的字符边界上的其他位置。

一个典型的错误原因是

  • einval - Location 非法,或者它被计算为文件中负偏移量。请注意,如果结果位置为负值,则结果为错误,并且在调用后,文件位置未定义。
链接到此函数

pread(IoDevice, LocNums)

查看源
-spec pread(IoDevice, LocNums) -> {ok, DataL} | eof | {error, Reason}
               when
                   IoDevice :: io_device(),
                   LocNums :: [{Location :: location(), Number :: non_neg_integer()}],
                   DataL :: [Data],
                   Data :: string() | binary() | eof,
                   Reason :: posix() | badarg | terminated.

在一个操作中执行一系列 pread/3,这比一次调用一个效率更高。返回 {ok, [Data, ...]}{error, Reason},其中每个 Data(对应 pread 的结果)要么是列表,要么是二进制数据(取决于文件模式),如果请求的位置超出文件末尾,则为 eof

由于位置被指定为字节偏移量,因此在处理 encoding 设置为 latin1 以外的值的文件时,请格外小心,因为并非每个字节位置都是此类文件上的有效字符边界。

链接到此函数

pread(IoDevice, Location, Number)

查看源
-spec pread(IoDevice, Location, Number) -> {ok, Data} | eof | {error, Reason}
               when
                   IoDevice :: io_device(),
                   Location :: location(),
                   Number :: non_neg_integer(),
                   Data :: string() | binary(),
                   Reason :: posix() | badarg | terminated.

在一个操作中组合 position/2read/2,这比一次调用一个效率更高。

仅当 Locationrawram 模式时,才允许为整数。

对于 raw 模式,操作后文件的当前位置未定义;对于 ram 模式,则保持不变。

由于位置被指定为字节偏移量,因此在处理 encoding 设置为 latin1 以外的值的文件时,请格外小心,因为并非每个字节位置都是此类文件上的有效字符边界。

链接到此函数

pwrite(IoDevice, LocBytes)

查看源
-spec pwrite(IoDevice, LocBytes) -> ok | {error, {N, Reason}}
                when
                    IoDevice :: io_device(),
                    LocBytes :: [{Location :: location(), Bytes :: iodata()}],
                    N :: non_neg_integer(),
                    Reason :: posix() | badarg | terminated.

在一个操作中执行一系列 pwrite/3,这比一次调用一个效率更高。返回 ok{error, {N, Reason}},其中 N 是失败前完成的成功写入次数。

当在 encoding 设置为 latin1 以外的值的文件中进行定位时,必须注意将位置设置在正确的字符边界上。有关详细信息,请参阅 position/2

链接到此函数

pwrite(IoDevice, Location, Bytes)

查看源
-spec pwrite(IoDevice, Location, Bytes) -> ok | {error, Reason}
                when
                    IoDevice :: io_device(),
                    Location :: location(),
                    Bytes :: iodata(),
                    Reason :: posix() | badarg | terminated.

在一个操作中组合 position/2write/2,这比一次调用一个效率更高。

仅当 Locationrawram 模式时,才允许为整数。

对于 raw 模式,操作后文件的当前位置未定义;对于 ram 模式,则保持不变。

当在 encoding 设置为 latin1 以外的值的文件中进行定位时,必须注意将位置设置在正确的字符边界上。有关详细信息,请参阅 position/2

链接到此函数

read(IoDevice, Number)

查看源
-spec read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason}
              when
                  IoDevice :: io_device() | io:device(),
                  Number :: non_neg_integer(),
                  Data :: string() | binary(),
                  Reason :: posix() | badarg | terminated | {no_translation, unicode, latin1}.

IoDevice 引用的文件中读取 Number 个字节/字符。

函数 read/2pread/3read_line/1 是从以 raw 模式打开的文件中读取的唯一方法(尽管它们也适用于正常打开的文件)。

对于 encoding 设置为 latin1 以外的值的文件,一个字符可以用文件中的多个字节表示。参数 Number 始终表示从文件中读取的字符数,而读取 Unicode 文件时,文件中位置的移动可能远远超过此数字。

此外,如果 encoding 设置为 latin1 以外的值,则如果数据包含大于 255 的字符,则 read/2 调用将失败,这就是为什么在读取此类文件时首选 io:get_chars/3 的原因。

该函数返回

  • {ok, Data} - 如果文件以二进制模式打开,则读取的字节在二进制文件中返回,否则在列表中返回。如果到达文件末尾,则列表或二进制文件比请求的字节数短。

  • eof - 如果 Number>0 并且在读取任何内容之前就到达了文件末尾,则返回。

  • {error, Reason} - 发生错误。

典型的错误原因

  • ebadf - 文件未打开以进行读取。

  • {no_translation, unicode, latin1} - 该文件使用 latin1 以外的其他 encoding 打开,并且文件中的数据无法转换为此函数返回的面向字节的数据。

链接到此函数

read_file(Filename)

查看源
-spec read_file(Filename) -> {ok, Binary} | {error, Reason}
                   when
                       Filename :: name_all(),
                       Binary :: binary(),
                       Reason :: posix() | badarg | terminated | system_limit.

等效于 read_file(Filename, [])

链接到此函数

read_file(Filename, Opts)

查看源代码 (自 OTP 27.0 起)
-spec read_file(Filename, Opts) -> {ok, Binary} | {error, Reason}
                   when
                       Filename :: name_all(),
                       Opts :: [read_file_option()],
                       Binary :: binary(),
                       Reason :: posix() | badarg | terminated | system_limit.

返回 {ok, Binary},其中 Binary 是一个二进制数据对象,包含 Filename 的内容,如果发生错误,则返回 {error, Reason}

如果设置了选项 raw,则不会调用文件服务器。

典型的错误原因

  • enoent - 该文件不存在。

  • eacces - 缺少读取文件或搜索父目录之一的权限。

  • eisdir - 指定的文件是一个目录。

  • enotdir - 文件名的组件不是目录。在某些平台上,返回 enoent

  • enomem - 没有足够的内存来存储文件的内容。

链接到此函数

read_file_info(File)

查看源
-spec read_file_info(File) -> {ok, FileInfo} | {error, Reason}
                        when
                            File :: name_all() | io_device(),
                            FileInfo :: file_info(),
                            Reason :: posix() | badarg.

等效于 read_file_info(File, [])

链接到此函数

read_file_info(File, Opts)

查看源代码 (自 OTP R15B 起)
-spec read_file_info(File, Opts) -> {ok, FileInfo} | {error, Reason}
                        when
                            File :: name_all() | io_device(),
                            Opts :: [file_info_option()],
                            FileInfo :: file_info(),
                            Reason :: posix() | badarg.

检索有关文件的信息。如果成功,则返回 {ok, FileInfo},否则返回 {error, Reason}

FileInfo 是一个记录 file_info,在 Kernel 包含文件 file.hrl 中定义。在调用该函数的模块中包含以下指令

-include_lib("kernel/include/file.hrl").

atimemtimectime 中返回的时间类型取决于 Opts :: {time, Type} 中设置的时间类型,如下所示

  • local - 返回本地时间。

  • universal - 返回世界标准时间。

  • posix - 返回自 Unix 时间纪元(即 1970-01-01 00:00 UTC)以来或之前的秒数。

默认值为 {time, local}

如果设置了选项 raw,则不会调用文件服务器,并且仅返回有关本地文件的信息。请注意,这将破坏此模块的原子性保证,因为它可能会与同时调用 write_file_info/1,2 竞争。

当该函数被赋予 I/O 设备而不是文件名时,此选项不起作用。请先使用 raw 模式调用 open/2 以获取文件描述符。

注意

由于文件时间在大多数操作系统上以 POSIX 时间存储,因此使用选项 posix 查询文件信息会更快。

记录 file_info 包含以下字段

  • size = non_neg_integer/0 - 文件大小(以字节为单位)。

  • type = device | directory | other | regular - 文件类型。从 read_link_info/1,2 返回时,也可以包含 symlink

  • access = read | write | read_write | none - 当前系统对文件的访问权限。

  • atime = date_time/0 | non_neg_integer/0 - 上次读取文件的时间。

  • mtime = date_time/0 | non_neg_integer/0 - 上次写入文件的时间。

  • ctime = date_time/0 | non_neg_integer/0 - 此时间字段的解释取决于操作系统。在 Unix 上,它是上次更改文件或 inode 的时间。在 Windows 中,它是创建时间。

  • mode = non_neg_integer/0 - 文件权限,为以下位值的总和

    • 8#00400 - 读取权限:所有者

    • 8#00200 - 写入权限:所有者

    • 8#00100 - 执行权限:所有者

    • 8#00040 - 读取权限:组

    • 8#00020 - 写入权限:组

    • 8#00010 - 执行权限:组

    • 8#00004 - 读取权限:其他

    • 8#00002 - 写入权限:其他

    • 8#00001 - 执行权限:其他

    • 16#800 - 在执行时设置用户 ID

    • 16#400 - 在执行时设置组 ID

    在 Unix 平台上,可能会设置上面未列出的其他位。

  • links = non_neg_integer/0 - 指向文件的链接数(对于没有链接概念的文件系统,此值始终为 1)。

  • major_device = non_neg_integer/0 - 标识文件所在的文件系统。在 Windows 中,该数字指示驱动器,如下所示:0 表示 A:,1 表示 B:,依此类推。

  • minor_device = non_neg_integer/0 - 仅对 Unix 上的字符设备有效。在所有其他情况下,此字段为零。

  • inode = non_neg_integer/0 - 提供 inode 编号。在非 Unix 文件系统上,此字段为零。

  • uid = non_neg_integer/0 - 指示文件的所有者。在非 Unix 文件系统上,此字段为零。

  • gid = non_neg_integer/0 - 提供文件所有者所属的组。在非 Unix 文件系统上,此字段为零。

典型的错误原因

  • eacces - 缺少文件父目录之一的搜索权限。

  • enoent - 该文件不存在。

  • enotdir - 文件名的组件不是目录。在某些平台上,返回 enoent

链接到此函数

read_line(IoDevice)

查看源
-spec read_line(IoDevice) -> {ok, Data} | eof | {error, Reason}
                   when
                       IoDevice :: io_device() | io:device(),
                       Data :: string() | binary(),
                       Reason :: posix() | badarg | terminated | {no_translation, unicode, latin1}.

IoDevice 引用的文件中读取一行字节/字符。

行被定义为由换行符 (LF, \n) 分隔,但任何回车符 (CR, \r) 后跟换行符也被视为单个 LF 字符(回车符会被静默忽略)。返回的行包括 LF,但不包括任何紧跟 LF 的 CR。此行为与 io:get_line/2 的行为一致。如果到达文件末尾且最后一行没有任何 LF 结尾,则返回没有尾随 LF 的行。

该函数可以用于以 raw 模式打开的文件。但是,如果文件没有指定 {read_ahead, Size} 选项,则在 raw 文件上使用它效率低下。因此,当打开文本文件以进行原始的面向行的读取时,强烈建议组合使用 raw{read_ahead, Size}

如果 encoding 设置为除 latin1 以外的其他值,则如果数据包含大于 255 的字符,则 read_line/1 调用将失败,因此当读取此类文件时,应首选 io:get_line/2

该函数返回

  • {ok, Data} - 返回文件中一行,包括尾随 LF,但 CRLF 序列将被替换为单个 LF(见上文)。

    如果文件以二进制模式打开,则读取的字节将以二进制形式返回,否则以列表形式返回。

  • eof - 如果在读取任何内容之前到达文件末尾,则返回此项。

  • {error, Reason} - 发生错误。

典型的错误原因

  • ebadf - 文件未打开以进行读取。

  • {no_translation, unicode, latin1} - 该文件使用除 latin1 以外的其他 encoding 打开,并且文件中的数据无法转换为此函数返回的面向字节的数据。

-spec read_link(Name) -> {ok, Filename} | {error, Reason}
                   when Name :: name_all(), Filename :: filename(), Reason :: posix() | badarg.

如果 Name 指的是不是原始文件名的符号链接,则返回 {ok, Filename},否则返回 {error, Reason}。在不支持符号链接的平台上,返回值是 {error,enotsup}

典型的错误原因

  • einval - Name 不指向符号链接,或者它指向的文件名不符合预期的编码。

  • enoent - 该文件不存在。

  • enotsup - 此平台不支持符号链接。

链接到此函数

rename(Source, Destination)

查看源
-spec rename(Source, Destination) -> ok | {error, Reason}
                when Source :: name_all(), Destination :: name_all(), Reason :: posix() | badarg.

尝试将文件 Source 重命名为 Destination。它可以用于在目录之间移动文件(和目录),但仅指定目标是不够的。还必须指定目标文件名。例如,如果 bar 是一个普通文件,foobaz 是目录,则 rename("foo/bar", "baz") 返回错误,但 rename("foo/bar", "baz/bar") 成功。如果成功,则返回 ok

注意

在大多数平台上不允许重命名打开的文件(请参见下面的 eacces)。

典型的错误原因

  • eacces - 缺少 SourceDestination 的父目录的读取或写入权限。在某些平台上,如果 SourceDestination 处于打开状态,则会给出此错误。

  • eexist - Destination 不是空目录。在某些平台上,当 SourceDestination 不是同一类型时也会给出此错误。

  • einval - Source 是根目录,或者 DestinationSource 的子目录。

  • eisdir - Destination 是一个目录,但 Source 不是。

  • enoent - Source 不存在。

  • enotdir - Source 是一个目录,但 Destination 不是。

  • exdev - SourceDestination 位于不同的文件系统上。

-spec script(Filename) -> {ok, Value} | {error, Reason}
                when
                    Filename :: name_all(),
                    Value :: term(),
                    Reason ::
                        posix() |
                        badarg | terminated | system_limit |
                        {Line :: integer(), Mod :: module(), Term :: term()}.

从文件中读取并计算以 .(或 ,,表达式序列也是一个表达式)分隔的 Erlang 表达式。

返回以下其中一项

  • {ok, Value} - 读取并评估该文件。Value 是最后一个表达式的值。

  • {error, atom()} - 打开文件或读取文件时发生错误。有关典型错误代码的列表,请参阅 open/2

  • {error, {Line, Mod, Term}} - 解释文件中的 Erlang 表达式时发生错误。使用 format_error/1 将三元素元组转换为错误的英文描述。

Filename 的编码可以通过注释进行设置,如 epp 中所述。

链接到此函数

script(Filename, Bindings)

查看源
-spec script(Filename, Bindings) -> {ok, Value} | {error, Reason}
                when
                    Filename :: name_all(),
                    Bindings :: erl_eval:binding_struct(),
                    Value :: term(),
                    Reason ::
                        posix() |
                        badarg | terminated | system_limit |
                        {Line :: integer(), Mod :: module(), Term :: term()}.

script/1 相同,但在求值时使用变量绑定 Bindings。有关变量绑定的信息,请参阅 erl_eval

链接到此函数

sendfile(Filename, Socket)

查看源代码 (自 OTP R15B 起)
-spec sendfile(Filename, Socket) ->
                  {ok, non_neg_integer()} | {error, inet:posix() | closed | badarg | not_owner}
                  when
                      Filename :: name_all(),
                      Socket ::
                          inet:socket() |
                          socket:socket() |
                          fun((iolist()) -> ok | {error, inet:posix() | closed}).

将文件 Filename 发送到 Socket。如果成功,则返回 {ok, BytesSent},否则返回 {error, Reason}

链接到此函数

sendfile(RawFile, Socket, Offset, Bytes, Opts)

查看源代码 (自 OTP R15B 起)
-spec sendfile(RawFile, Socket, Offset, Bytes, Opts) ->
                  {ok, non_neg_integer()} | {error, inet:posix() | closed | badarg | not_owner}
                  when
                      RawFile :: fd(),
                      Socket ::
                          inet:socket() |
                          socket:socket() |
                          fun((iolist()) -> ok | {error, inet:posix() | closed}),
                      Offset :: non_neg_integer(),
                      Bytes :: non_neg_integer(),
                      Opts :: [sendfile_option()].

将从 RawFile 引用的文件中,从 Offset 开始的 Bytes 发送到 Socket。如果成功,则返回 {ok, BytesSent},否则返回 {error, Reason}。如果 Bytes 设置为 0,则会发送指定 Offset 之后的所有数据。

使用的文件必须使用 raw 标志打开,并且调用 sendfile 的进程必须是套接字的控制进程。请参阅 gen_tcp:controlling_process/2 或模块 socket level otp 套接字选项 controlling_process

如果使用的操作系统不支持非阻塞 sendfile,则会使用 Erlang 回退,该回退使用 read/2gen_tcp:send/2

选项列表可以包含以下选项:

  • chunk_size - Erlang 回退用来发送数据的块大小。如果使用回退,请将其设置为一个可以舒适地容纳在系统内存中的值。默认值为 20 MB。
-spec set_cwd(Dir) -> ok | {error, Reason}
                 when
                     Dir :: name() | EncodedBinary,
                     EncodedBinary :: binary(),
                     Reason :: posix() | badarg | no_translation.

将文件服务器的当前工作目录设置为 Dir。如果成功,则返回 ok

模块 file 中的函数通常将二进制文件视为原始文件名,也就是说,即使二进制文件的编码与 native_name_encoding() 不一致,也会“按原样”传递它们。但是,此函数期望二进制文件根据 native_name_encoding/0 返回的值进行编码。

典型的错误原因是:

  • enoent - 该目录不存在。

  • enotdir - Dir 的组件不是目录。在某些平台上,返回 enoent

  • eacces - 缺少目录或其父目录之一的权限。

  • badarg - Dir 具有不正确的类型,例如元组。

  • no_translation - Dir 是一个使用 ISO-latin-1 编码的字符的 binary/0,而 VM 正在使用 unicode 文件名编码进行操作。

警告

在未来的版本中,参数 Dir 的错误类型可能会生成异常。

-spec sync(IoDevice) -> ok | {error, Reason}
              when IoDevice :: io_device(), Reason :: posix() | badarg | terminated.

确保操作系统(而不是 Erlang 运行时系统)保留的任何缓冲区都写入磁盘。在某些平台上,此函数可能不起作用。

一个典型的错误原因是

  • enospc - 没有足够的空间来写入文件。
链接到此函数

truncate(IoDevice)

查看源
-spec truncate(IoDevice) -> ok | {error, Reason}
                  when IoDevice :: io_device(), Reason :: posix() | badarg | terminated.

在当前位置截断 IoDevice 引用的文件。如果成功,则返回 ok,否则返回 {error, Reason}

链接到此函数

write(IoDevice, Bytes)

查看源
-spec write(IoDevice, Bytes) -> ok | {error, Reason}
               when
                   IoDevice :: io_device() | io:device(),
                   Bytes :: iodata(),
                   Reason :: posix() | badarg | terminated.

Bytes 写入 IoDevice 引用的文件。此函数是写入以 raw 模式打开的文件的唯一方法(尽管它也适用于正常打开的文件)。如果成功,则返回 ok,否则返回 {error, Reason}

如果使用除 latin1 以外的其他 encoding 打开文件,则写入的每个字节都可能导致向文件写入多个字节,因为字节范围 0..255 可以表示一个到四个字节之间的任何内容,具体取决于值和 UTF 编码类型。如果要将 unicode:chardata/0 写入 IoDevice,则应改用 io:put_chars/2

典型的错误原因

  • ebadf - 文件未打开以进行写入。

  • enospc - 设备上没有剩余空间。

链接到此函数

write_file(Filename, Bytes)

查看源
-spec write_file(Filename, Bytes) -> ok | {error, Reason}
                    when
                        Filename :: name_all(),
                        Bytes :: iodata(),
                        Reason :: posix() | badarg | terminated | system_limit.

iodataBytes 的内容写入文件 Filename。如果文件不存在,则创建该文件。如果文件存在,则会覆盖先前的内容。如果成功,则返回 ok,否则返回 {error, Reason}

典型的错误原因

  • enoent - 文件名的组件不存在。

  • enotdir - 文件名的组件不是目录。在某些平台上,返回 enoent

  • enospc - 设备上没有剩余空间。

  • eacces - 缺少写入文件或搜索其父目录之一的权限。

  • eisdir - 指定的文件是一个目录。

链接到此函数

write_file(Filename, Bytes, Modes)

查看源
-spec write_file(Filename, Bytes, Modes) -> ok | {error, Reason}
                    when
                        Filename :: name_all(),
                        Bytes :: iodata(),
                        Modes :: [mode()],
                        Reason :: posix() | badarg | terminated | system_limit.

write_file/2 相同,但采用第三个参数 Modes(可能的模式列表),请参阅 open/2。模式标志 binarywrite 是隐式的,因此不应使用它们。

链接到此函数

write_file_info(Filename, FileInfo)

查看源
-spec write_file_info(Filename, FileInfo) -> ok | {error, Reason}
                         when
                             Filename :: name_all(), FileInfo :: file_info(), Reason :: posix() | badarg.

等效于 write_file_info(Filename, FileInfo, [])

链接到此函数

write_file_info(Filename, FileInfo, Opts)

查看源代码 (自 OTP R15B 起)
-spec write_file_info(Filename, FileInfo, Opts) -> ok | {error, Reason}
                         when
                             Filename :: name_all(),
                             Opts :: [file_info_option()],
                             FileInfo :: file_info(),
                             Reason :: posix() | badarg.

更改文件信息。如果成功,则返回 ok,否则返回 {error, Reason}

FileInfo 是一个记录 file_info,在 Kernel 包含文件 file.hrl 中定义。在调用该函数的模块中包含以下指令

-include_lib("kernel/include/file.hrl").

atimemtimectime 中设置的时间类型取决于 Opts :: {time, Type} 中设置的时间类型,如下所示:

  • local - 将设置的时间解释为本地时间。

  • universal - 将其解释为世界标准时间。

  • posix - 必须是自 Unix 时间纪元(即 1970-01-01 00:00 UTC)以来或之前的秒数。

默认值为 {time, local}

如果设置了 raw 选项,则不会调用文件服务器,并且仅返回有关本地文件的信息。

如果指定了以下字段,则使用该记录中的以下字段:

  • atime = date_time/0 | non_neg_integer/0 - 上次读取文件的时间。

  • mtime = date_time/0 | non_neg_integer/0 - 上次写入文件的时间。

  • ctime = date_time/0 | non_neg_integer/0 - 在 Unix 上,为此字段指定的任何值都将被忽略(文件的“ctime”将设置为当前时间)。在 Windows 上,此字段是要为文件设置的新创建时间。

  • mode = non_neg_integer/0 - 文件权限,为以下位值的总和

    • 8#00400 - 读取权限:所有者

    • 8#00200 - 写入权限:所有者

    • 8#00100 - 执行权限:所有者

    • 8#00040 - 读取权限:组

    • 8#00020 - 写入权限:组

    • 8#00010 - 执行权限:组

    • 8#00004 - 读取权限:其他

    • 8#00002 - 写入权限:其他

    • 8#00001 - 执行权限:其他

    • 16#800 - 执行时设置用户 ID

    • 16#400 - 执行时设置组 ID

    在 Unix 平台上,可能会设置上面未列出的其他位。

  • uid = 非负整数 - 指示文件所有者。在非 Unix 文件系统中被忽略。

  • gid = 非负整数 - 给出文件所有者所属的组。在非 Unix 文件系统中被忽略。

典型的错误原因

  • eacces - 缺少文件父目录之一的搜索权限。

  • enoent - 该文件不存在。

  • enotdir - 文件名的组件不是目录。在某些平台上,返回 enoent