file
file
模块
档案
模块摘要
文件接口模块。
描述
该模块提供了文件系统的接口。
在支持线程的操作系统上,文件操作可以在自己的线程中执行,从而允许其他Erlang进程与文件操作并行地继续执行。参见命令行标志+A
在erl(1)
。
关于文件名编码,Erlang虚拟机可以以两种模式运行。当前模式可以使用函数查询native_name_encoding/0
。它返回latin1
或utf8
。
在latin1
模式中,Erlang虚拟机不会更改文件名的编码。在utf8
模式下,文件名可以包含大于255的Unicode字符,并且VM将文件名来回转换为本地文件名编码(通常是UTF-8,但是Windows上的UTF-16)。
默认模式取决于操作系统。Windows和MacOS X强制执行一致的文件名编码,因此VM使用utf8
模式。
在具有透明命名的操作系统上(例如除MacOS X之外的所有Unix系统),默认情况下utf8
是否终端支持UTF-8 latin1
。启动时可以使用+fnl
(强制latin1
模式)或+fnu
(强制utf8
模式)覆盖默认值erts:erl
。
在具有透明命名的操作系统上,文件可以不一致地命名,例如,某些文件以UTF-8编码,而其他文件则以ISO Latin-1编码。引入原始文件名
的概念是为了在utf8
模式下运行时处理命名不一致的文件系统。
原始文件名
是指定为二进制文件名。Erlang虚拟机不会在具有透明命名的系统上将指定为二进制文件的文件名转换为二进制文件。
当运行utf8
模式,功能list_dir/1
和read_link/1
永远不会返回原文件名。要返回包括原始文件名的所有文件名,请使用函数list_dir_all/1
和read_link_all/1
。
另见Notes About Raw Filenames
STDLIB用户指南中的部分。
数据类型
deep_list() = [char() | atom() |
deep_list()
]
fd()
表示在raw
模式。
filename() = string()
filename_all() = string() | binary()
io_device() = pid() |
fd()
由open/2
;pid()
是处理I/O协议的进程。
name() = string() | atom() |
deep_list()
如果VM处于Unicode文件名模式,string()
并且char()
允许大于255。
name_all() =
string() | atom() |
deep_list()
| (RawFilename :: binary())
如果VM处于Unicode文件名模式,string()
并且char()
允许大于255. RawFilename
是不受Unicode转换限制的文件名,这意味着它可以包含不符合文件系统期望的Unicode编码的字符(即非UTF-尽管虚拟机以Unicode文件名模式启动,但仍有8个字符)。
posix() =
eacces |
eagain |
ebadf |
ebusy |
edquot |
eexist |
efault |
efbig |
eintr |
einval |
eio |
eisdir |
eloop |
emfile |
emlink |
enametoolong |
enfile |
enodev |
enoent |
enomem |
enospc |
enotblk |
enotdir |
enotsup |
enxio |
eperm |
epipe |
erofs |
espipe |
esrch |
estale |
exdev
一个由Unix中使用的POSIX错误代码以及大多数C编译器的运行时库命名的原子。
date_time() = calendar:datetime()
必须表示有效的日期和时间。
file_info() =
#file_info{size = integer() >= 0 | undefined,
type =
device |
directory |
other |
regular |
symlink |
undefined,
access =
read | write | read_write | none | undefined,
atime =
file:date_time()
|
integer() >= 0 |
undefined,
mtime =
file:date_time()
|
integer() >= 0 |
undefined,
ctime =
file:date_time()
|
integer() >= 0 |
undefined,
mode = integer() >= 0 | undefined,
links = integer() >= 0 | undefined,
major_device = integer() >= 0 | undefined,
minor_device = integer() >= 0 | undefined,
inode = integer() >= 0 | undefined,
uid = integer() >= 0 | undefined,
gid = integer() >= 0 | undefined}
location() =
integer() |
{bof, Offset :: integer()} |
{cur, Offset :: integer()} |
{eof, Offset :: integer()} |
bof |
cur |
eof
mode() =
read |
write |
append |
exclusive |
raw |
binary |
{delayed_write,
Size :: integer() >= 0,
Delay :: integer() >= 0} |
delayed_write |
{read_ahead, Size :: integer() >= 1} |
read_ahead |
compressed |
{encoding, unicode:encoding()} |
sync
file_info_option() =
{time, local} | {time, universal} | {time, posix} | raw
出口
advise(IoDevice, Offset, Length, Advise) -> ok | {error, Reason}
类型
advise/4
可用于宣布将来以特定模式访问文件数据的意图,从而允许操作系统执行适当的优化。
在某些平台上,此功能可能不起作用。
allocate(File, Offset, Length) -> ok | {error, posix()}
类型
allocate/3
可用于预分配文件的空间。
此功能仅在提供此功能的平台上成功。成功时,为文件预分配空间,但文件大小可能不会更新。这种行为取决于预分配实现。要保证文件大小已更新,请将文件截断为新大小。
change_group(Filename, Gid) -> ok | {error, Reason}
类型
更改文件组。看write_file_info/2
。
change_mode(Filename, Mode) -> ok | {error, Reason}
类型
更改文件的权限。看write_file_info/2
。
change_owner(Filename, Uid) -> ok | {error, Reason}
类型
更改文件的所有者。看write_file_info/2
。
change_owner(Filename, Uid, Gid) -> ok | {error, Reason}
类型
更改文件的所有者和组。参见write_file_info/2
。
change_time(Filename, Mtime) -> ok | {error, Reason}
类型
更改文件的修改和访问时间。参见write_file_info/2
。
change_time(Filename, Atime, Mtime) -> ok | {error, Reason}
类型
更改文件的修改和上次访问时间。看write_file_info/2
。
close(IoDevice) -> ok | {error, Reason}
类型
关闭由引用的文件IoDevice
。ok
除了一些严重错误(如内存不足)之外,它大部分都会返回。
请注意,如果delayed_write
在打开文件时使用了选项,则close/1
可能会返回旧的写入错误,甚至不会尝试关闭该文件。参见open/2
。
consult(Filename) -> {ok, Terms} | {error, Reason}
类型
阅读由'。'分隔的Erlang术语Filename
。返回以下内容之一:
{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(3)
。
copy(Source, Destination) -> {ok, BytesCopied} | {error, Reason}
copy(Source, Destination, ByteCount) ->
{ok, BytesCopied} | {error, Reason}
类型
ByteCount
从Source
to 复制字节Destination
。Source
例如,Destination
参考文件名或IO设备open/2
。ByteCount
默认为infinity
,表示无限数量的字节。
参数Modes
是可能模式的列表,请参阅open/2
并默认为[]
。
如果同时Source
并Destination
指文件名,文件打开与[read, binary]
和[write, binary]
前置到他们分别列出模式,以优化复制。
如果Source
引用文件名,则read
在复制之前以模式列表前面的模式打开,并在完成时关闭。
如果Destination
引用文件名,则write
在复制之前以模式列表前面的模式打开,并在完成时关闭。
返回{ok, BytesCopied}
,其中BytesCopied
是复制的字节数,可能小于ByteCount
在源上遇到文件结尾的情况。如果操作失败,{error, Reason}
则返回。
典型的错误原因:open/2
如果一个文件必须打开,read/2
以及write/2
。
datasync(IoDevice) -> ok | {error, Reason}
类型
确保操作系统(而非Erlang运行时系统)保存的任何缓冲区都写入磁盘。在很多方面它很类似,fsync
但它并不更新文件的某些元数据,例如访问时间。在某些平台上,此功能不起作用。
访问数据库或日志文件的应用程序通常会写入一个微小的数据片段(例如,日志文件中的一行),然后fsync()
立即调用以确保写入的数据物理存储在硬盘上。不幸的是,fsync()
总是启动两个写操作:一个用于新写入的数据,另一个用于更新存储在其中的修改时间inode
。如果修改时间不是事务概念的一部分,fdatasync()
可用于避免不必要的inode
磁盘写入操作。
只有在某些POSIX系统中才可用,此调用将导致对fsync()
不提供fdatasync()
系统调用的系统的调用或不起作用。
del_dir(Dir) -> ok | {error, Reason}
类型
试图删除目录Dir
。该目录在被删除之前必须是空的。如果成功则返回ok
。
典型错误原因:
eacces
缺少搜索或写入父目录的权限Dir
。
eexist
目录不是空的。
enoent
目录不存在。
enotdir
组件Dir
不是目录。在某些平台上,将返回enoent
。
einval
尝试删除当前目录。在某些平台上,将返回eacces
。
delete(Filename) -> ok | {error, Reason}
类型
尝试删除文件Filename
.返回ok
如果成功的话。
典型错误原因:
enoent
文件不存在。
eacces
对该文件或其父母之一缺少权限。
eperm
该文件是一个目录,用户不是超级用户。
enotdir
文件名的一个组件不是一个目录。在某些平台上,将返回enoent
。
einval
Filename
具有不正确的类型,如元组。
警告
在未来的版本中,参数的错误类型Filename
可能会产生异常。
eval(Filename) -> ok | {error, Reason}
类型
读取和评估由'。'分隔的Erlang表达式。(或',',表达式序列也是一个表达式)Filename
。评估结果不返回;文件中的任何表达式序列都必须存在,因为它的副作用。返回以下内容之一:
ok
文件被读取和评估。
{error, atom()}
打开文件或读取文件时发生错误。有关典型错误代码的列表,请参阅open/2
。
{error, {Line, Mod, Term}}
解释文件中的Erlang表达式时发生错误。要将三元素元组转换为错误的英文描述,请使用format_error/1
。
编码Filename
可以通过注释来设置,如下所述epp(3)
。
eval(Filename, Bindings) -> ok | {error, Reason}
类型
与eval/1
相同,但变量绑定Bindings
用于评估。有关变量绑定的信息,请参阅erl_eval(3)
。
format_error(Reason) -> Chars
类型
鉴于此模块中任何函数返回的错误原因,请返回英文错误的描述性字符串。
get_cwd() -> {ok, Dir} | {error, Reason}
类型
返回{ok, Dir}
,其中Dir
是文件服务器的当前工作目录。
注
在极少数情况下,这个函数可能在Unix上失败。如果当前目录的父目录不存在读取权限,则可能发生这种情况。
一个典型的错误原因是:
eacces
缺少当前目录的其中一个父项的读取权限。
get_cwd(Drive) -> {ok, Dir} | {error, Reason}
类型
返回{ok, Dir}
或{error, Reason}
,其中Dir
是指定驱动器的当前工作目录。
Drive
应该是“ Letter:
” 的形式,例如“c:”。
{error, enotsup}
在没有当前驱动器概念的平台上返回(例如,Unix)。
典型错误原因:
enotsup
操作系统没有驱动器的概念。
eacces
驱动器不存在。
einval
格式Drive
无效。
list_dir(Dir) -> {ok, Filenames} | {error, Reason}
类型
列出目录中的所有文件,但
具有原始文件名的文件除外
。{ok, Filenames}
如果成功则返回,否则{error, Reason}
。Filenames
是目录中所有文件的名称列表。名称没有排序。
典型错误原因:
eacces
Dir
或其某个父目录缺少搜索或写入权限。
enoent
目录不存在。
{no_translation, Filename}
Filename
是以binary()
ISO Latin-1编码的字符,并且VM是以参数启动的+fnue
。
list_dir_all(Dir) -> {ok, Filenames} | {error, Reason}
类型
列出目录中的所有文件,包括具有原始文件名的文件。{ok, Filenames}
如果成功则返回,否则{error, Reason}
。Filenames
是目录中所有文件的名称列表。名称没有排序。
典型错误原因:
eacces
Dir
或其某个父目录缺少搜索或写入权限。
enoent
目录不存在。
make_dir(Dir) -> ok | {error, Reason}
类型
尝试创建目录Dir
。没有
创建缺少父目录。如果成功则返回ok
。
典型错误原因:
eacces
缺少搜索或写入父目录的权限Dir
。
eexist
Dir
已命名的文件或目录已存在。
enoent
一个组件Dir
不存在。
enospc
设备上没有空间。
enotdir
组件Dir
不是目录。在某些平台上,将返回enoent
。
make_link(Existing, New) -> ok | {error, Reason}
类型
使从硬链接Existing
到New
上支撑拉杆(Unix和Windows)平台。ok
如果链接成功创建,则返回此函数,否则返回{error, Reason}
。在不支持链接的平台上,返回{error,enotsup}
。
典型错误原因:
eacces
对于缺失的父目录的读写权限Existing
或New
。
eexist
New
已经存在了。
enotsup
在这个平台上不支持硬链接。
make_symlink(Existing, New) -> ok | {error, Reason}
类型
在支持符号链接(大多数Unix系统和Windows,从Vista开始)的平台上创建符号链接New
到文件或目录Existing
。Existing
不需要存在。返回ok
链接是否成功创建,否则返回{error, Reason}
。在不支持符号链接的平台上,{error, enotsup}
返回。
典型错误原因:
eacces
对于缺失的父目录的读写权限Existing
或New
。
eexist
New
已经存在了。
enotsup
此平台不支持符号链接。
eperm
用户无权创建符号链接(SeCreateSymbolicLinkPrivilege
在Windows上)。
native_name_encoding() -> latin1 | utf8
返回文件名编码模式。如果是latin1
,则系统不转换文件名。如果是这样utf8
,文件名被来回转换为本地文件名编码(通常是UTF-8,但是Windows上的UTF-16)。
open(File, Modes) -> {ok, IoDevice} | {error, Reason}
类型
File
按照确定的模式打开文件,该模式Modes
可以包含一个或多个以下选项:
read
该文件必须存在,已打开供阅读。
write
该文件被打开写入。如果它不存在,则创建它。如果该文件存在并且write
未与之结合read
,则该文件被截断。
append
该文件被打开写入。如果它不存在,则创建它。对打开的文件执行的每个写入操作append
都发生在文件末尾。
exclusive
该文件被打开写入。如果它不存在,则创建。如果文件存在,则返回{error, eexist}
。
警告
此选项不保证文件系统上的排他性不O_EXCL
正确,如NFS。除非您知道文件系统支持它(通常,本地文件系统是安全的),否则不要依赖此选项。
raw
允许更快地访问文件,因为不需要Erlang进程来处理文件。但是,以这种方式打开的文件具有以下限制:
io
模块中的函数不能使用,因为它们只能与Erlang进程通信。相反,使用功能read/2
,read_line/1
以及write/2
。
- 特别是如果
read_line/1
要在raw
文件上使用,建议将此选项与选项结合使用,{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
Size
与Delay
(和大约64 KB,2秒)的{delayed_write, Size, Delay}
合理默认值相同。
{read_ahead, Size}
激活读取数据缓冲。如果read/2
调用的Size
字节数小于字节数,则对操作系统的读操作仍然以Size
字节为单位执行。额外的数据被缓存并在随后的read/2
调用中返回,随着操作系统调用次数的减少而提高性能。
read_ahead
缓冲区也高度使用功能read_line/1
在raw
模式,因此建议该选项(出于性能原因)使用该函数访问原始文件时。
如果read/2
调用大小不显着小于或者甚至大于Size
字节,则不会获得性能增益。
read_ahead
{read_ahead, Size}
一样与合理的默认值Size
(大致约64 KB)。
compressed
使读取或写入gzip压缩文件成为可能。选项compressed
必须与read
或组合write
,但不能同时使用。请注意,使用获取的文件大小read_file_info/1
可能与可以从压缩文件中读取的字节数不匹配。
{encoding, Encoding}
使文件自动转换特定(Unicode)编码中的字符。请注意,提供给still write/2
或由read/2
still 返回的数据是以字节为导向的; 此选项仅表示数据如何存储在磁盘文件中。
根据编码的不同,读取和写入数据的方法是首选。默认编码latin1
意味着使用这个模块(file
)来读写数据,因为这里提供的接口使用面向字节的数据。使用其他(Unicode)的编码使得io(3)
功能get_chars
,get_line
以及put_chars
更合适的,因为它们可以与完整的Unicode范围内工作。
如果数据以io_device()
无法转换为指定编码的格式发送,或者数据以无法应对数据字符范围的格式返回数据的函数读取,则会发生错误,并且文件为关闭。
允许值Encoding
*
latin1
默认编码。提供给文件的字节,即在文件上write/2
“按原样”写入。同样,从文件读取的字节也就是read/2
“按原样”返回。如果使用模块io(3)
进行写入,则文件只能处理代码点255(ISO Latin-1范围)内的Unicode字符。
unicode or utf8
在写入文件或从文件读取字符之前,字符会转换为UTF-8编码或从UTF-8编码转换。read/2
只要没有存储在文件中的数据超出ISO Latin-1范围(0..255),以这种方式打开的文件就可以使用函数读取,但如果数据包含超出该范围的Unicode代码点,则会发生故障。该文件最好用Unicode识别模块中的函数读取io(3)
。
以任何方式写入文件的字节在存储到磁盘文件之前都会转换为UTF-8编码。
utf16 or {utf16,big}
工作就像unicode
,但翻译是从大端的UTF-16而不是UTF-8进行的。
{utf16,little}
作品像unicode
,但翻译是从小端UTF-16而不是UTF-8进行的。
utf32 or {utf32,big}
就像unicode
,但翻译是大端UTF-32,而不是UTF-8。
{utf32,little}
就像unicode
,但翻译是从小终端UTF-32,而不是UTF-8。
编码可以通过使用功能在“即时”更改为一个文件io:setopts/2
。因此,可以使用latin1编码对文件进行分析,例如,将BOM放置在BOM之外,然后在进一步阅读之前将其设置为正确的编码。有关标识物料清单的功能,请参阅模块unicode(3)
。
此选项不允许在raw
档案。
ram
File
必须iodata()
。返回一个fd()
让模块file
对内存中的数据进行操作的模块,就像它是一个文件一样。
sync
在支持它的平台上,启用POSIX O_SYNC
同步I / O标志或其与平台相关的等效标志(例如,FILE_FLAG_WRITE_THROUGH
在Windows上),以便写入文件块直至将数据物理写入磁盘。但是,请注意,此标志的确切语义因平台而异。例如,Linux或Windows都不保证在调用返回之前还写入所有文件元数据。要获得精确的语义,请查看平台文档的详细信息。在不支持POSIX O_SYNC
或同等版本的平台上,使用该sync
标志会导致open
返回{error, enotsup}
。
返回:
{ok, IoDevice}
文件以请求模式打开。IoDevice
是对文件的引用。
{error, Reason}
无法打开该文件。
IoDevice
真的是处理文件的过程的PID。该过程与最初打开文件的过程相关联。如果链接的任何进程IoDevice
终止,则文件关闭,进程本身终止。一个IoDevice
从该调用返回可被用作一个参数,该I/O功能(见io(3)
)。
注
在以前的版本file
,模式进行了指定为原子中的一个read
,write
或,read_write
而不是一个列表。由于向后兼容的原因,这仍然是允许的,但不能用于新代码。另请注意,read_write
模式列表中不允许。
典型错误原因:
enoent
文件不存在。
eacces
缺少读取文件或搜索父目录之一的权限。
eisdir
命名文件不是常规文件。它可以是一个目录,一个FIFO,或者一个设备。
enotdir
文件名的组件不是目录。在一些平台上,enoent
而是返回。
enospc
设备上没有剩余空间(如果write
指定了访问权限)。
path_consult(Path, Filename) ->
{ok, Terms, FullName} | {error, Reason}
类型
搜索路径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(3)
。
path_eval(Path, Filename) -> {ok, FullName} | {error, Reason}
类型
搜索路径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(3)
。
path_open(Path, Filename, Modes) ->
{ok, IoDevice, FullName} | {error, Reason}
类型
搜索路径Path
(目录名称列表),直到Filename
找到文件。如果Filename
是绝对文件名,Path
则忽略。然后以确定的模式打开文件Modes
。
返回下列内容之一:
{ok, IoDevice, FullName}
该文件以请求的模式打开。IoDevice
是对文件的引用,是文件FullName
的全名。
{error, enoent}
该文件不能在任何目录中找到Path
。
{error, atom()}
无法打开该文件。
path_script(Path, Filename) ->
{ok,Value,FullName}{Error,Rational}
类型
搜索路径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(3)
。
path_script(Path, Filename, Bindings) ->
{ok,Value,FullName}{Error,Rational}
类型
与评估中使用path_script/2
的变量绑定相同Bindings
。查看erl_eval(3)
关于变量绑定。
pid2name(Pid) -> {ok, Filename} | undefined
类型
如果Pid
是I/O设备,即返回的pid open/2
,则此函数返回文件名,或者:
{ok, Filename}
如果此节点的文件服务器不是从属节点,则该节点的文件服务器将打开该文件(这意味着该文件Pid
必须是本地pid),并且该文件未关闭。Filename
是扁平字符串格式的文件名。
undefined
在所有其他情况下。
警告
此函数仅用于调试。
position(IoDevice, Location) ->
{ok, NewPosition} | {error, Reason}
类型
设置由IoDevice
to 引用的文件的位置Location
。{ok, NewPosition}
如果成功则返回(如绝对偏移),否则返回{error, Reason}
。Location
是以下之一:
Offset
和{bof, Offset}
。一样。
{bof, Offset}
绝对偏移
{cur, Offset}
从当前位置偏移。
{eof, Offset}
从文件末尾偏移。
bof | cur | eof
与上面的Offset
0 相同。
请注意,偏移量以字节计算,而不是以字符计算。如果该文件是使用其它开encoding
比latin1
,一个字节不对应一个字符。在这样的文件中定位只能对已知的字符边界进行。也就是说,通过获取当前位置,到文件的开始/结尾或通过一些其他方式知道
位于正确字符边界上的某个其他位置(通常超出文件中的字节顺序标记,它具有已知的字节大小)。
一个典型的错误原因是:
einval
要么Location
是非法的,要么是文件中的负偏移。请注意,如果结果位置为负值,则结果为错误,并且在调用之后文件位置未定义。
pread(IoDevice, LocNums) -> {ok, DataL} | eof | {error, Reason}
类型
pread/3
在一个操作中执行一系列操作,比一次调用一个操作更有效。根据文件的模式,或者如果所请求的位置超出文件结尾,则返回{ok, [Data, ...]}
或者{error, Reason}
其中每个Data
对应结果pread
都是列表或二进制eof
文件。
由于位置被指定为字节偏移量,因此在处理encoding
设置为其他内容的文件时要特别小心latin1
,因为并非每个字节位置都是这样的文件上的有效字符边界。
pread(IoDevice, Location, Number) ->
pread(IoDevice, Location, Number) ->
类型
结合position/2
并read/2
在一次操作中,这比打电话给他们一次一个更有效率。如果IoDevice
在raw
模式下打开,则适用一些限制:
Location
只允许为整数。
- 文件的当前位置在操作后未定义。
由于位置被指定为字节偏移量,因此在处理encoding
设置为其他内容的文件时要特别小心latin1
,因为并非每个字节位置都是这样的文件上的有效字符边界。
pwrite(IoDevice, LocBytes) -> ok | {error, {N, Reason}}
类型
pwrite/3
在一个操作中执行一系列操作,比一次调用一个操作更有效。返回ok
或{error, {N, Reason}}
,N
失败之前成功写入的次数在哪里。
当与其他文件定位encoding
比latin1
,一定要小心,要设置一个正确的字符边界上的位置。有关详情,请参阅position/2
。
pwrite(IoDevice, Location, Bytes) -> ok | {error, Reason}
类型
结合position/2
并write/2
在一次操作中,这比打电话给他们一次一个更有效率。如果IoDevice
已在raw
模式下打开,则适用一些限制:
Location
只允许为整数。
- 文件的当前位置在操作后未定义。
当与其他文件定位encoding
比latin1
,一定要小心,要设置一个正确的字符边界上的位置。有关详情,请参阅position/2
。
read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason}
类型
Number
从引用的文件中读取字节/字符IoDevice
。函数read/2
,pread/3
和read_line/1
是从raw
模式打开的文件读取的唯一方法(尽管它们也适用于通常打开的文件)。
对于encoding
设置为其他文件的文件latin1
,一个字符
可以由文件中的多个字节表示。该参数Number
总是表示从文件读取的字符
数,而在读取Unicode文件时,文件中的位置可以移动得比这个数字多得多。
另外,如果encoding
设置为其他值latin1
,则read/3
如果数据包含大于255的字符,则调用将失败,这就是为什么io(3)
在读取此类文件时首选模块的原因。
函数返回:
{ok, Data}
如果文件是以二进制模式打开的,则以二进制方式返回读取的字节,否则返回列表中的字节。如果到达文件末尾,列表或二进制文件的长度将小于请求的字节数。
eof
如果Number>0在读取任何内容之前已达到文件结尾,则返回。
{error, Reason}
发生了一个错误。
典型错误原因:
ebadf
该文件未打开以供阅读。
{no_translation, unicode, latin1}
该文件被打开另一个encoding
比latin1
和文件中的数据不能被转换为面向字节的数据,该函数返回。
read_file(Filename) -> {ok, Binary} | {error, Reason}
类型
返回{ok, Binary}
,其中Binary
是包含内容Filename
或{error, Reason}
发生错误的二进制数据对象。
典型错误原因:
enoent
文件不存在。
eacces
缺少读取文件或搜索父目录之一的权限。
eisdir
命名文件是一个目录。
enotdir
文件名的一个组件不是一个目录。在某些平台上,enoent
将返回。
enomem
文件内容没有足够的内存。
read_file_info(Filename) -> {ok, FileInfo} | {error, Reason}
read_file_info(Filename, Opts) -> {ok, FileInfo} | {error, Reason}
类型
检索有关文件的信息。{ok, FileInfo}
如果成功则返回,否则{error, Reason}
。FileInfo
是一个记录file_info
,在内核包含文件中定义file.hrl
。在调用该函数的模块中包含以下指令:
-include_lib("kernel/include/file.hrl").
时间类型中返回atime
,mtime
和ctime
依赖于设置在时间类型Opts :: {time, Type}
,如下所示:
local
返回当地时间。
universal
返回普遍时间。
posix
返回Unix时间纪元(1970-01-01 00:00 UTC)之前或之前的秒数。
默认是{time, local}
。
如果raw
设置了该选项,则不会调用文件服务器,只会返回有关本地文件的信息。
注
由于文件时间存储在大多数操作系统上的POSIX时间中,因此使用选项查询文件信息会更快posix
。
记录file_info
包含以下字段:
size = integer() >= 0
文件大小(以字节为单位)。
type = device | directory | other | regular | symlink
文件的类型。
access = read | write | read_write | none
当前系统对文件的访问。
atime =date_time()| integer() >= 0
上次文件被读取的时候。
mtime =date_time()| integer() >= 0
上次写文件的时候。
ctime =date_time()| integer() >=0
这段时间的解释取决于操作系统。在Unix上,这是最后一次该文件或被inode
更改。在Windows中,这是创建时间。
mode = 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 = integer() >= 0
指向文件的链接数(对于没有链接概念的文件系统,这总是1)。
major_device = integer() >= 0
标识文件所在的文件系统。在Windows中,数字表示一个驱动器,如下所示:0表示A :, 1表示B :,依此类推。
minor_device = integer() >= 0
只对Unix上的字符设备有效。在所有其他情况下,该字段为零。
inode = integer() >= 0
给出inode
号码。在非Unix文件系统上,该字段为零。
uid = integer() >= 0
表示文件的所有者。在非Unix文件系统上,该字段为零。
gid = integer() >= 0
给出文件所有者属于的组。在非Unix文件系统上,该字段为零。
典型错误原因:
eacces
缺少文件的父目录之一的搜索权限。
enoent
文件不存在。
enotdir
文件名的一个组件不是一个目录。在某些平台上,enoent
将返回。
read_line(IoDevice) -> {ok, Data} | eof | {error, Reason}
类型
从引用的文件中读取一行字节/字符IoDevice
。行被定义为由换行(LF,\n
)字符分隔,但任何回车符(CR,\r
)后跟换行符也被视为单个LF字符(回车被忽略)。该行返回包括
LF,但不包括
任何紧跟着LF的CR。这种行为与行为是一致的io:get_line/2
。如果到达文件末尾没有任何LF结束最后一行,则返回一个没有结尾LF的行。
该功能可用于在raw
模式下打开的文件。但是,raw
如果未使用{read_ahead, Size}
指定的选项打开文件,则在文件上使用它效率低下。因此,组合raw
和{read_ahead, Size}
开口,用于生面向行的读取文本文件时,强烈建议。
如果encoding
设置为其他值latin1
,则read_line/1
如果数据包含大于255的字符,则调用将失败,那么io(3)
读取此类文件时为什么首选模块。
函数返回:
{ok, Data}
返回文件中的一行,包括尾随LF,但CRLF序列由单个LF替换(参见上文)。
如果文件以二进制模式打开,则读取的字节以二进制形式返回,否则以列表形式返回。
eof
如果在读取任何内容之前已达到文件结尾,则返回。
{error, Reason}
发生了一个错误。
典型错误原因:
ebadf
该文件未打开以供阅读。
{no_translation, unicode, latin1}
该文件被打开另一个encoding
比latin1
和文件上的数据不能被转换为面向字节的数据,该函数返回。
read_link(Name) -> {ok, Filename} | {error, Reason}
类型
返回{ok, Filename}
if Name
引用不是原始文件名的符号链接,{error, Reason}
否则返回。在不支持符号链接的平台上,返回值为{error,enotsup}
。
典型错误原因:
einval
Name
不引用符号链接或引用的文件的名称不符合预期的编码。
enoent
文件不存在。
enotsup
此平台不支持符号链接。
read_link_all(Name) -> {ok, Filename} | {error, Reason}
类型
返回{ok, Filename}
if Name
引用符号链接或{error, Reason}
其他。在不支持符号链接的平台上,返回值为{error,enotsup}
。
注意Filename
可以是列表或二进制。
典型错误原因:
einval
Name
不引用符号链接。
enoent
文件不存在。
enotsup
此平台不支持符号链接。
read_link_info(Name) -> {ok, FileInfo} | {error, Reason}
read_link_info(Name, Opts) -> {ok, FileInfo} | {error, Reason}
类型
像read_file_info/1,2
除了如果Name
是符号链接一样工作,关于链接的信息被返回到file_info
记录中并且记录的type
字段被设置为symlink
。
如果raw
设置了该选项,则不会调用文件服务器,只会返回有关本地文件的信息。
如果Name
不是符号链接,则此函数返回与结果相同的结果read_file_info/1
。在不支持符号链接的平台上,此功能始终等同于read_file_info/1
。
rename(Source, Destination) -> ok | {error, Reason}
类型
尝试将文件重命名Source
为Destination
。它可以用来在目录之间移动文件(和目录),但仅仅指定目的地是不够的。目标文件名也必须指定。例如,如果bar
是普通文件,foo
而且baz
是目录,rename("foo/bar", "baz")
则会返回错误,但会rename("foo/bar", "baz/bar")
成功。ok
如果成功则返回。
注
在大多数平台上不允许重命名打开的文件(请参阅eacces
下文)。
典型错误原因:
eacces
对于缺失的父目录的读写权限Source
或Destination
。在某些平台上,如果打开Source
或Destination
打开了此错误。
eexist
Destination
不是一个空目录。在某些平台上,也会给出时间Source
和Destination
不同的类型。
einval
Source
是一个根目录,或者Destination
是一个子目录Source
。
eisdir
Destination
是一个目录,但Source
不是。
enoent
Source
不存在。
enotdir
Source
是一个目录,但Destination
不是。
exdev
Source
和Destination
在不同的文件系统上。
script(Filename) -> {ok, Value} | {error, Reason}
类型
读取和评估由'.'分隔的Erlang表达式。(或',',表达式序列也是一个表达式)。
返回下列内容之一:
{ok, Value}
该文件被读取和评估。Value
是最后一个表达式的值。
{error, atom()}
打开文件或读取文件时发生错误。有关典型错误代码的列表,请参阅open/2
。
{error, {Line, Mod, Term}}
解释文件中的Erlang表达式时发生错误。使用format_error/1
三个元素的元组转换为错误的英文说明。
编码Filename
可以通过注释来设置,如下所述epp(3)
。
script(Filename, Bindings) -> {ok, Value} | {error, Reason}
类型
与评估中使用script/1
的变量绑定相同Bindings
。查看erl_eval(3)
关于变量绑定。
sendfile(Filename, Socket) ->
{ok, integer() >= 0} |
{error, inet:posix()
| closed | badarg | not_owner}
类型
发送文件Filename
到Socket
。{ok, BytesSent}
如果成功则返回,否则{error, Reason}
。
sendfile(RawFile, Socket, Offset, Bytes, Opts) ->
{ok, integer() >= 0} |
{error, inet:posix()
| closed | badarg | not_owner}
类型
发送Bytes
从引用的文件RawFile
的开头Offset
到Socket
。{ok, BytesSent}
如果成功则返回,否则{error, Reason}
。如果在指定发送后Bytes
设置为0
所有数据Offset
。
必须使用该raw
标志打开使用的文件,并且进程调用sendfile
必须是套接字的控制进程。看gen_tcp:controlling_process/2
。
如果使用的操作系统不支持sendfile
,则使用read/2
和gen_tcp:send/2
使用的Erlang回退。
选项列表可以包含以下选项:
chunk_size
Erlang回退用于发送数据的块大小。如果使用后备,请将其设置为适合系统内存的值。默认值是20 MB。
use_threads
指示模拟器使用async
线程池进行sendfile
系统调用。如果您正在运行的操作系统不能正确支持非阻塞sendfile
调用,这会很有用。请注意,使用async
线程可能会使您的系统容易受到客户端缓慢的攻击。如果设置为true
并且没有async
线程可用,则该sendfile
呼叫返回{error,einval}
。在Erlang/OTP 17.0中引入。默认是false
。
set_cwd(Dir) -> ok | {error, Reason}
类型
将文件服务器的当前工作目录设置为Dir
。如果成功则返回ok
。
模块中的函数file
通常将二进制文件视为原始文件名,也就是说,即使二进制文件的编码不一致,它们也会“按原样”传递native_name_encoding()
。但是,该函数期望根据返回的值对二进制文件进行编码native_name_encoding()
。
典型的错误原因是:
enoent
目录不存在。
enotdir
组件Dir
不是目录。在某些平台上,返回enoent
。
eacces
缺少目录或其父目录之一的权限。
badarg
Dir
有一个不正确的类型,比如元组。
no_translation
Dir
是以binary()
ISO-latin-1编码的字符,并且VM使用unicode文件名编码进行操作。
警告
在未来的版本中,参数的错误类型Dir
可能会产生异常。
sync(IoDevice) -> ok | {error, Reason}
类型
确保操作系统(而非Erlang运行时系统)保存的任何缓冲区都写入磁盘。在某些平台上,此功能可能不起作用。
一个典型的错误原因是:
enospc
没有足够的空间来写入文件。
truncate(IoDevice) -> ok | {error, Reason}
类型
截断IoDevice
在当前位置引用的文件。如果成功则返回ok
,否则{error, Reason}
。
write(IoDevice, Bytes) -> ok | {error, Reason}
类型
写入Bytes
由引用的文件IoDevice
。此功能是写入以raw
模式打开的文件的唯一方式(尽管它也适用于通常打开的文件)。如果成功则返回ok
,否则返回{error, Reason}
。
如果文件被打开并encoding
设置为其他内容latin1
,则写入的每个字节都可能导致将很多字节写入文件,因为根据值和UTF编码类型,字节范围0..255可以表示1到4个字节之间的任何内容。
典型错误原因:
ebadf
该文件不会被打开以进行写入。
enospc
设备上没有空间。
write_file(Filename, Bytes) -> ok | {error, Reason}
类型
将iodata
术语的内容写入Bytes
文件Filename
。如果该文件不存在,则会创建该文件。如果存在,则先前的内容被覆盖。ok
如果成功则返回,否则{error, Reason}
。
典型错误原因:
enoent
文件名的组件不存在。
enotdir
文件名的一个组件不是一个目录。在某些平台上,将返回enoent
。
enospc
设备上没有空间。
eacces
缺少写入文件或搜索其中一个父目录的权限。
eisdir
命名文件是一个目录。
write_file(Filename, Bytes, Modes) -> ok | {error, Reason}
类型
与write_file/2
第三个参数相同,但Modes
可能的模式列表请参阅open/2
。该模式的标志binary
和write
是隐含的,所以他们不被使用。
write_file_info(Filename, FileInfo) -> ok | {error, Reason}
write_file_info(Filename, FileInfo, Opts) -> ok | {error, Reason}
类型
更改文件信息。如果成功则返回,否ok
则{error, Reason}
。FileInfo
是一个记录file_info
,在内核包含文件中定义file.hrl
。在调用该函数的模块中包含以下指令:
-include_lib("kernel/include/file.hrl").
时间类型设置于atime
,中mtime
,并ctime
取决于设置的时间类型Opts :: {time, Type}
,如下所示:
local
解释设置为本地的时间。
universal
把它解释为宇宙时间。
posix
必须是自Unix时间纪元以来的秒数,即UTC时间1970-01-01 00:00。
默认是{time, local}
。
如果raw
设置了该选项,则不会调用文件服务器,只会返回有关本地文件的信息。
如果指定了以下字段,则从记录中使用:
atime =date_time()| integer() >= 0
上次读取文件时。
mtime =date_time()| integer() >= 0
上次写文件的时候。
ctime =date_time()| integer() >= 0
在Unix上,为该字段指定的任何值都会被忽略(文件的“ctime”被设置为当前时间)。在Windows上,此字段是为文件设置的新创建时间。
mode = 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 = integer() >= 0
指示文件所有者。非Unix文件系统忽略。
gid = integer() >= 0
提供文件所有者所属的组。非Unix文件系统忽略。
典型错误原因:
eacces
缺少文件的父目录之一的搜索权限。
enoent
文件不存在。
enotdir
文件名的一个组件不是一个目录。在某些平台上,将返回enoent
。
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
-跨域链接
性能
某些操作系统文件操作(例如,一个sync/1
或close/1
一个巨大的文件)可能会阻止其调用线程几秒钟。如果这影响仿真器主线程,则响应时间不再是毫秒数量级,这取决于软实时系统中“软”的定义。
如果设备驱动程序线程池处于活动状态,则文件操作将通过这些线程完成,以便模拟器可以继续执行Erlang进程。不幸的是,由于操作系统需要额外的调度,提供文件操作的时间增加了。
如果设备驱动程序线程池被禁用或大小为0,则大文件读取和写入会被分割为很多较小的文件,这使得模拟器可以在文件操作过程中为其他进程提供服务。这与使用线程池时的效果相同,但开销较大。其他文件操作sync/1
或例如close/1
大文件仍然是个问题。
为了提高性能,建议使用原始文件。原始文件使用节点主机的文件系统。
注
对于普通文件(非原始文件),文件服务器用于查找文件,并且如果节点正在将其文件服务器作为另一个节点的文件服务器的从服务器运行,并且另一个节点在其他某台主机上运行,则它们可以有不同的文件系统。但是,这很少是一个问题。
普通文件实际上是一个进程,因此它可以用作I / O设备(请参阅参考资料io
)。因此,将数据写入普通文件时,将数据发送到文件进程将复制所有不是二进制文件的数据。因此建议以二进制模式打开文件并编写二进制文件。如果文件在另一个节点上打开,或者文件服务器作为另一个节点的文件服务器的从服务器运行,则也会复制二进制文件。
缓存数据以减少文件操作的数量,或者说调用文件驱动程序的次数通常会提高性能。以下函数在测试时在23秒内写入4 MBytes:
create_file_slow(Name, N) when integer(N), N >= 0 ->
{ok, FD} = file:open(Name, [raw, write, delayed_write, binary]),
ok = create_file_slow(FD, 0, N),
ok = ?FILE_MODULE:close(FD),
ok.
create_file_slow(FD, M, M) ->
ok;
create_file_slow(FD, M, N) ->
ok = file:write(FD, <<M:32/unsigned>>),
create_file_slow(FD, M+1, N).
在每次调用之前,以下功能相当的函数将1024个条目收集到128个32字节的二进制文件列表中,write/2
并且在0.52秒内完成相同的工作,速度提高了44倍:
create_file(Name, N) when integer(N), N >= 0 ->
{ok, FD} = file:open(Name, [raw, write, delayed_write, binary]),
ok = create_file(FD, 0, N),
ok = ?FILE_MODULE:close(FD),
ok.
create_file(FD, M, M) ->
ok;
create_file(FD, M, N) when M + 1024 =< N ->
create_file(FD, M, M + 1024, []),
create_file(FD, M + 1024, N
create_file(FD, M, N) ->
create_file(FD, M, N, []).
create_file(FD, M, M, R) ->
ok = file:write(FD, R
create_file(FD, M, N0, R) when M + 8 =< N0 ->
N1 = N0-1, N2 = N0-2, N3 = N0-3, N4 = N0-4,
N5 = N0-5, N6 = N0-6, N7 = N0-7, N8 = N0-8,
create_file(FD, M, N8,
[<<N8:32/unsigned, N7:32/unsigned,
N6:32/unsigned, N5:32/unsigned,
N4:32/unsigned, N3:32/unsigned,
N2:32/unsigned, N1:32/unsigned>> | R]
create_file(FD, M, N0, R) ->
N1 = N0-1,
create_file(FD, M, N1, [<<N1:32/unsigned>> | R]).
注
只相信你自己的基准。如果create_file/2
上面的列表长度增加,它运行速度稍快,但消耗更多的内存并导致更多的内存碎片。这对您的应用程序有多大影响是这个简单的基准测试无法预测的。
如果每个二进制文件的大小增加到64字节,它的运行速度也会稍微快一些,但代码的笨拙是两倍。在当前实现中,大于64字节的二进制文件存储在所有进程共有的内存中,并且在进程之间发送时不会被复制,而这些较小的二进制文件存储在进程堆中,并在发送时像其他任何字段一样进行复制。
所以,二进制大小为68字节,create_file/2
比64字节慢30%,并导致更多的内存碎片。请注意,如果要在进程之间发送二进制文件(例如,非原始文件),结果可能会完全不同。
原始文件实际上是一个端口。将数据写入端口时,编写二进制文件列表非常有效。在写作之前不需要将深度列表弄平。在Unix主机上,尽可能使用分散输出(在一个操作中写入一组缓冲区)。通过这种方式write(FD, [Bin1, Bin2 | Bin3])
写入二进制文件的内容,而不用复制数据,除了操作系统内核中的内核。
对于原始文件,pwrite/2
并pread/2
有效地实施。文件驱动程序只对整个操作调用一次,并且列表迭代在文件驱动程序中完成。
选项delayed_write
和read_ahead
以open/2
使文件的驱动程序缓存数据,以减少操作系统的调用次数。create_file/2
在最近的例子中,这个函数没有选项需要60秒delayed_write
,比2.6倍慢。
作为一个不好的例子,create_file_slow/2
没有选项raw
,binary
并且delayed_write
意味着它的调用open(Name, [write])
需要1分20秒来完成,比第一个例子慢3.5倍,比优化慢150倍create_file/2
。
警告
如果在使用模块访问打开的文件时发生错误io
,处理该文件的进程将退出。如果进程稍后尝试访问,死文件进程可能会挂起。这将在未来的版本中修复。
另见
filename(3)