模塊摘要
文件接口模塊
描述
模塊file提供了文件系統的接口。
在具有線程支持的操作系統上,可以讓文件操作以其自己的線程執行,從而允許其他Erlang進程與文件操作並行地繼續執行。在ERL(1)查看命令行標記 +A。
Erlang虛擬機在一定程度上支持Unicode的文件名。根據VM的啟動方式(使用參數 + fnu或+ fnl),給定的文件名可以包含大於255的字符,VM系統會將文件名來回轉換為本地文件名編碼。
Unicode字符轉換的默認行為取決於底層操作系統/文件系統強制執行一致命名的程度。在確保所有文件名都采用一種或另一種編碼的操作系統上,Unicode是默認值(目前這適用於Windows和MacOSX)。在具有完全透明文件命名的操作系統上(即除MacOSX以外的所有Unix),ISO-latin-1文件命名是默認的。ISO-latin-1默認的原因是文件名不能保證可以根據預期的Unicode編碼進行解釋(即UTF-8),並且不能解碼的文件名只能通過使用“raw文件名“,其他文件名稱為二進制文件。
由於文件名通常不是Erlang中的二進制文件,因此需要轉換需要處理原始文件名的應用程序,這就是為什么文件名的Unicode模式在具有完全透明文件命名的系統上不是默認值。
原始文件名是OTP R14B01中的一項新功能,它允許用戶將完全未解釋的文件名提供給底層操作系統/文件系統。它們以二進制文件形式提供,用戶可以根據環境提供正確的編碼。函數file:native_name_encoding()可用於檢查虛擬機正在工作的編碼。如果該函數返回latin1文件名不會以任何方式轉換為Unicode,如果它是utf8,如果原始文件名要遵循VM的約定(通常也是OS的約定),則應將其編碼為UTF-8。如果您的文件系統具有不一致的文件命名,則使用原始文件名非常有用,其中一些文件以UTF-8編碼命名,而其他文件則不以此命名。當虛擬機處於Unicode文件名模式時,這種混合文件名系統上file:list_dir可能會將文件名作為原始二進制文件返回,因為它們不能被解釋為Unicode文件名。即使虛擬機未以Unicode文件名翻譯模式啟動,原始文件名也可用於提供UTF-8編碼的文件名。
請注意,在Windows上,即使在Windows上,file:native_name_encoding()也會在默認情況下返回utf8,即使在Windows上也是原始文件名的格式,但底層操作系統特定的代碼在小尾數UTF16的限制版本中工作。就Erlang程序員而言,Windows原生Unicode格式是UTF-8 ...
數據類型
deep_list() = [char()| atom()| deep_list() ]
FD()
表示以原始模式打開的文件的文件描述符。
filename() = string()
filename_all() = string()| binary()
io_device() = pid()| FD()
由file: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編碼的字符盡管虛擬機在Unicode文件名模式下啟動,但是不支持UTF-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 = undefined | integer() >= 0,
type = undefined
| device
| directory
| other
| regular
| symlink,
access = undefined
| read
| write
| read_write
| none,
atime = undefined
| file:date_time()
| integer() >= 0,
mtime = undefined
| file:date_time()
| integer() >= 0,
ctime = undefined
| file:date_time()
| integer() >= 0,
mode = undefined | integer() >= 0,
links = undefined | integer() >= 0,
major_device = undefined | integer() >= 0,
minor_device = undefined | integer() >= 0,
inode = undefined | integer() >= 0,
uid = undefined | integer() >= 0,
gid = undefined | integer() >= 0}
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()}
file_info_option() = {time, local} | {time, universal} | {time, posix}
導出
advise(IoDevice, Offset, Length, Advise) -> ok | {error, Reason}
Types:
IoDevice = io_device()
Offset = Length = integer()
Advise = posix_file_advise()
Reason = posix() | badarg
posix_file_advise() = normal
| sequential
| random
| no_reuse
| will_need
| dont_need
advise/4可用於宣布將來以特定模式訪問文件數據的意圖,從而允許操作系統執行適當的優化。
在某些平台上,此功能可能不起作用。
allocate(File, Offset, Length) -> ok | {error, posix()}
Types:
File = io_device()
Offset = Length = integer() >= 0
allocate/3可用於為文件預分配空間。
此功能僅在實現此功能的平台上成功。成功時,為文件預分配空間,但文件大小可能不會更新。這種行為取決於預分配實現。為了保證文件大小更新,必須將文件截斷為新的大小。
change_group(Filename, Gid) -> ok | {error, Reason}
Types:
Filename = name_all()
Gid = integer()
Reason = posix() | badarg
更改文件組。請參閱 write_file_info/2。
change_mode(Filename, Mode) -> ok | {error, Reason}
Types:
Filename = name_all()
Mode = integer()
Reason = posix() | badarg
更改文件的權限。請參閱 write_file_info/2。
change_owner(Filename, Uid) -> ok | {error, Reason}
Types:
Filename = name_all()
Uid = integer()
Reason = posix() | badarg
更改文件的所有者和組。請參閱 write_file_info/2。
change_time(Filename, Mtime) -> ok | {error, Reason}
Types:
Filename = name_all()
Mtime = date_time()
Reason = posix() | badarg
更改文件的修改和訪問時間。請參閱 write_file_info/2。
close(IoDevice) -> ok | {error, Reason}
Types:
IoDevice = io_device()
Reason = posix() | badarg | terminated
關閉IoDevice引用的文件。它通常會返回正常,預計會出現諸如內存不足等嚴重錯誤。
請注意,如果在打開文件時使用了選項delayed_write,則close/1可能會返回舊的寫入錯誤,甚至不會嘗試關閉該文件。見open/2。
consult(Filename) -> {ok, Terms} | {error, Reason}
Types:
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}]}
文件名的編碼可以通過epp(3)中描述的注釋來設置。
copy(Source, Destination) -> {ok, BytesCopied} | {error, Reason}
copy(Source, Destination, ByteCount) -> {ok, BytesCopied} | {error, Reason}
Types:
Source = Destination = io_device() | Filename | {Filename, Modes}
Filename = name_all()
Modes = [mode()]
ByteCount = integer() >= 0 | infinity
BytesCopied = integer() >= 0
Reason = posix() | badarg | terminated
從Source到Destination復制ByteCount字節 。
Source和Destination是指來自例如open/2的文件名或IO設備。 ByteCount默認為infinity,表示無限數量的字節。
Modes模式是可能模式的列表,請參閱open/2,默認為[]。
如果Source和 Destination都指向文件名,那么這些文件分別以[read,binary] 和[write,binary]作為模式列表的預先打開,以優化副本。
如果Source引用一個文件名,則在拷貝之前以讀取模式打開,並在完成時關閉。
如果Destination指向一個文件名,它會在復制之前以模式列表預先以寫入模式打開,並在完成時關閉。
返回{ok,BytesCopied},其中BytesCopied是實際復制的字節數,如果在源上遇到文件結尾,則可能小於ByteCount。如果操作失敗, 則返回{error,Reason}。
典型的錯誤原因:至於open/2,如果一個文件必須打開,以及read/2和write/2。
del_dir(Dir) -> ok | {error, Reason}
Types:
Dir = name_all()
Reason = posix() | badarg
嘗試刪除目錄Dir。該目錄在被刪除之前必須是空的。成功返回ok。
典型的錯誤原因是:
eacces
Dir的父目錄缺少搜索或寫入權限。
eexist
該目錄不是空的。
enoent
該目錄不存在。
enodir
Dir的一個組件不是一個目錄。在某些平台上,取而代之的是返回enoent。
einval
嘗試刪除當前目錄。在某些平台上,eacces被返回。
delete(Filename) -> ok | {error, Reason}
Types:
Filename = name_all()
Reason = posix() | badarg
試圖刪除文件Filename。成功返回ok。
典型的錯誤原因是:
enoent
該文件不存在。
eacces
對該文件或其父母之一缺少權限。
eperm
該文件是一個目錄,用戶不是超級用戶。
enotdir
文件名的一個組件不是一個目錄。在某些平台上,取而代之的是返回enoent。
einval
文件名具有不正確的類型,例如元組。
警告
在未來的版本中,Filename參數的錯誤類型 可能會生成異常。
eval(Filename) -> ok | {error, Reason}
Types:
Filename = name_all()
Reason = posix()
| badarg
| terminated
| system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}
讀取和運算由'.'分隔的Erlang表達式(或',',一系列表達式也是一個表達式),來自 Filename。運算的實際結果不返回;文件中的任何表達式序列都必須存在,因為它的副作用。返回以下內容之一:
ok
該文件被讀取和運算。
{error,atom()}
打開文件或讀取文件時發生錯誤。有關典型錯誤代碼的列表,請參閱open/2。
{error,{Line,Mod,Term}}
解釋文件中的Erlang表達式時發生錯誤。使用format_error/1將三元素元組轉換為錯誤的英文描述。
文件名的編碼可以通過epp(3)中描述的注釋來設置。
eval(Filename, Bindings) -> ok | {error, Reason}
Types:
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(3)關於變量綁定。
file_info(Filename) -> {ok, FileInfo} | {error, Reason}
Types:
Filename = name_all()
FileInfo = file_info()
Reason = posix() | badarg
此功能已過時。 改為使用read_file_info/1,2。
format_error(Reason) -> Chars
Types:
Reason = posix()
| badarg
| terminated
| system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}
Chars = string()
鑒於此模塊中任何函數返回的錯誤原因,請返回英文錯誤的描述性字符串。
get_cwd() -> {ok, Dir} | {error, Reason}
Types:
Dir = filename()
Reason = posix()
返回{ok,Dir},其中Dir 是文件服務器的當前工作目錄。
注意
在極少數情況下,這個函數可能在Unix上失敗。如果當前目錄的父目錄不存在讀取權限,則可能發生這種情況。
典型的錯誤原因是:
eacces
缺少當前目錄的其中一個父項的讀取權限。
get_cwd(Drive) -> {ok, Dir} | {error, Reason}
Types:
Drive = string()
Dir = filename()
Reason = posix() | badarg
驅動器的格式應為“ Letter:”,例如“c:”。返回{ok,Dir}或 {error,Reason},其中Dir 是指定驅動器的當前工作目錄。
該函數在沒有當前驅動器概念的平台(例如Unix)上返回{error,enotsup}。
典型的錯誤原因是:
enotsup
操作系統沒有驅動器的概念。
eacces
該驅動器不存在。
einval
雲端硬盤的格式無效。
list_dir(Dir) -> {ok, Filenames} | {error, Reason}
Types:
Dir = name_all()
Filenames = [filename()]
Reason = posix()
| badarg
| {no_translation, Filename :: unicode:latin1_binary()}
列出目錄中的所有文件,但具有“原始”名稱的文件除外。如果成功,返回 {ok,Filenames}。否則,它返回{error,Reason}。 文件名是目錄中所有文件名稱的列表。名稱沒有排序。
典型的錯誤原因是:
eacces
Dir或其父目錄之一缺少搜索或寫入權限。
enoent
該目錄不存在。
{no_translation,Filename}
Filename是一個二進制,其字符在ISO-latin-1中編碼,VM以參數+ fnue啟動。
list_dir_all(Dir) -> {ok, Filenames} | {error, Reason}
Types:
Dir = name_all()
Filenames = [filename_all()]
Reason = posix() | badarg
列出目錄中的所有文件,包括具有“原始”名稱的文件。如果成功,返回{ok,Filenames}。否則,它返回{error,Reason}。 文件名是目錄中所有文件名稱的列表。名稱沒有排序。
典型的錯誤原因是:
eacces
Dir或其父目錄之一缺少搜索或寫入權限。
enoent
該目錄不存在。
make_dir(Dir) -> ok | {error, Reason}
Types:
Dir = name_all()
Reason = posix() | badarg
嘗試創建目錄Dir。缺少父目錄不能創建。成功返回ok。
典型的錯誤原因是:
eacces
Dir的父目錄缺少搜索或寫入權限。
eexist
已經有一個名為Dir的文件或目錄。
enoent
Dir的一個組件不存在。
enospc
設備上沒有剩余空間。
enotdir
Dir的一個組件不是一個目錄。在某些平台上,取而代之的是返回enoent。
make_link(Existing, New) -> ok | {error, Reason}
Types:
Existing = New = name_all()
Reason = posix() | badarg
在支持鏈接的平台(Unix和Windows)上建立從Existing到 New的硬鏈接。如果鏈接成功創建,該函數返回ok,或 {error,Reason}。在不支持鏈接的平台上,返回{error,enotsup}。
典型的錯誤原因:
eacces
缺少Existing或 New的父目錄的讀取或寫入權限。
eexist
新已經存在。
enosup
該平台不支持硬鏈接。
make_symlink(Existing, New) -> ok | {error, Reason}
Types:
Existing = New = name_all()
Reason = posix() | badarg
在支持符號鏈接(大多數Unix系統和Windows以Vista開頭)的平台上,該函數創建一個文件或目錄Existing的新符號鏈接。 Existing需要不存在。如果鏈接成功創建,該函數返回ok,或{error,Reason}。在不支持符號鏈接的平台上, 返回{error,enotsup}。
典型的錯誤原因:
eacces
缺少Existing或New的父目錄的讀取或寫入權限。
eexist
新已經存在。
enotsup
此平台不支持符號鏈接。
native_name_encoding() -> latin1 | utf8
此函數返回配置的默認文件名編碼以用於原始文件名。通常,提供文件名raw(作為二進制文件)的應用程序應該服從由該函數返回的字符編碼。
默認情況下,VM在文件系統和/或使用完全透明文件命名的操作系統上使用ISO-latin-1文件名編碼。這包括除MacOSX之外的所有Unix版本,其中vfs層強制執行UTF-8文件命名。通過在啟動Erlang時給出實驗選項+ fnu,即使對於那些系統,也可以打開文件名的UTF-8轉換。如果Unicode文件名翻譯生效,只要文件名符合編碼,系統就會照常運行,但會返回未正確編碼為UTF-8的文件名作為原始文件名(即二進制文件)。
在Windows上,該函數默認返回utf8。操作系統使用純粹的Unicode命名方案,文件名總是可以解釋為有效的Unicode。底層Windows操作系統實際上使用小尾數UTF-16編碼文件名的事實可以被Erlang程序員忽略。Windows和MacOSX是虛擬機默認以Unicode文件名模式運行的唯一操作系統。
open(File, Modes) -> {ok, IoDevice} | {error, Reason}
Types:
File = Filename | iodata()
Filename = name_all()
Modes = [mode() | ram]
IoDevice = io_device()
Reason = posix() | badarg | system_limit
以由Modes確定的模式打開文件File,該模式可能包含以下一項或多項內容:
read
該文件必須存在,已打開供閱讀。
write
該文件被打開寫入。如果它不存在,則創建它。如果該文件存在,並且如果寫入未與讀取結合,則該文件將被截斷。
append
該文件將被打開進行寫入,並且如果該文件不存在,該文件將被創建。對使用append打開的文件的每個寫入操作都將在文件末尾進行。
exclusive
如果該文件在寫入時打開,則該文件如果不存在則創建。如果文件存在,打開將返回 {error,eexist}。
警告
此選項不保證在不支持O_EXCL的文件系統上的排他性,例如NFS。除非您知道文件系統支持該選項,否則不要依賴此選項(通常,本地文件系統應該是安全的)。
raw
該raw選項允許一個文件更快的訪問,因為不需要Erlang進程來處理文件。但是,以這種方式打開的文件具有以下限制:
io模塊中的功能無法使用,因為它們只能與Erlang進程通信。相反,使用read/2,read_line/1和 write/2 函數。
特別是如果要在原始文件上使用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
與{Delay_write,Size,Delay}相同,使用Size和 Delay的合理默認值。(大約64 KB,2秒)
{read_ahead, Size}
該選項激活讀取數據緩沖。如果 read/2調用的字節數大大小於Size字節,則對操作系統的讀取操作仍會針對Size 字節塊執行。額外的數據被緩沖並在隨后的read/2調用中返回,從而減少操作系統調用次數,從而提高性能。
所述read_ahead緩沖器也是高度由利用read_line/1在功能原始模式下,為什么建議該選項(出於性能原因)使用該函數訪問原始文件時。
如果read/2調用的大小不小於或大於size字節,則不會獲得性能增益。
read_ahead
同為{read_ahead,Size}有一個合理的默認值大小。(大約64 KB)
compressed
使讀取或寫入gzip壓縮文件成為可能。該壓縮選項必須以組合讀或寫,但不能同時使用。請注意,使用read_file_info/1獲取的文件大小 很可能與可從壓縮文件讀取的字節數不匹配。
{encoding, Encoding}
使文件自動轉換特定(Unicode)編碼中的字符。請注意,提供給file:write或由file:read返回的數據仍然是面向字節的,該選項僅表示數據實際存儲在磁盤文件中的方式。
根據編碼的不同,讀取和寫入數據的方法是首選。latin1的默認編碼意味着使用這個(文件)模塊讀取和寫入數據,因為這里提供的接口使用面向字節的數據,而使用其他(Unicode)編碼使得io(3)模塊的get_chars,get_line和put_chars功能更適合,因為它們可以使用完整的Unicode范圍。
如果數據以無法轉換為指定編碼的格式發送到io_device(),或者數據是以無法應對數據字符范圍的格式返回數據的函數讀取的,則會發生錯誤,並且該文件將被關閉。
編碼的允許值是:
LATIN1
默認編碼。提供給ie file:write的字節按原樣寫入文件,同樣從文件讀取的字節返回到ie file:read。如果使用io(3)模塊進行寫入,則該文件只能處理直至代碼點255(ISO-latin-1范圍)的Unicode字符。
unicode或utf8
在寫入文件或從文件中讀取字符之前,字符會轉換為UTF-8編碼或從UTF-8編碼轉換而來。只要沒有存儲在文件中的數據超出ISO-latin-1范圍(0..255),以這種方式打開的文件就可以使用file:read函數讀取,但如果數據包含Unicode超出該范圍的碼點。該文件最好使用支持Unicode的io(3)模塊中的函數進行讀取 。
在實際存儲到磁盤文件之前,通過任何方式寫入文件的字節都會轉換為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之后,然后設置為正確的編碼進一步閱讀。參見unicode(3)模塊了解BOM的功能。
原始文件不允許使用此選項。
ram
文件必須是iodata()。返回一個fd(),它使文件模塊對內存中的數據進行操作,就像它是一個文件一樣。
返回:
{ok,IoDevice}
該文件已在請求的模式下打開。 IoDevice是對該文件的引用。
{error, Reason}
該文件無法打開。
IoDevice實際上是處理文件的過程的pid。這個過程與最初打開文件的過程相關聯。如果IoDevice鏈接的任何進程終止,則文件將被關閉,進程本身將被終止。從此調用返回的IoDevice可用作IO函數的參數(請參閱 io(3))。
注意
在以前版本的文件,模式都給出一個原子read,write,或read_write,而不是一個列表。出於向后兼容的原因,這仍然是允許的,但不應該用於新代碼。另請注意,模式列表中不允許使用read_write。
典型的錯誤原因:
enoent
該文件不存在。
eacces
缺少權限讀取文件或搜索其中一個父目錄。
eisdir
指定的文件不是常規文件。它可能是一個目錄,一個fifo或一個設備。
enotdir
文件名的一個組件不是一個目錄。在某些平台上,取而代之的是返回enoent。
enospc
設備上沒有剩余空間(如果 指定了寫訪問權限)。
path_consult(Path, Filename) -> {ok, Terms, FullName} | {error, Reason}
Types:
Path = [Dir]
Dir = Filename = name_all()
Terms = [term()]
FullName = filename_all()
Reason = posix()
| badarg
| terminated
| system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}
搜索路徑Path(目錄名稱列表),直到找到文件Filename。如果文件名是絕對文件名,則路徑被忽略。然后從文件中讀取用'.'分隔的Erlang項。返回以下內容之一:
{ok,Terms,FullName}
該文件已成功讀取。FullName是文件的全名。
{error,enoent}
該文件無法在Path中的任何目錄中找到 。
{error,atom()}
打開文件或讀取文件時發生錯誤。有關典型錯誤代碼的列表,請參閱open/2。
{error,{Line,Mod,Term}}
解釋文件中的Erlang項時發生錯誤。使用format_error/1將三元素元組轉換為錯誤的英文描述。
文件名的編碼可以通過epp(3)中描述的注釋來設置。
path_eval(Path, Filename) -> {ok, FullName} | {error, Reason}
Types:
Path = [Dir :: name_all()]
Filename = name_all()
FullName = filename_all()
Reason = posix()
| badarg
| terminated
| system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}
搜索路徑Path(目錄名稱列表),直到找到文件Filename。如果文件名是絕對文件名,則路徑被忽略。然后讀取並運算由'.'分隔的Erlang表達式。(或',',表達式序列也是一個表達式)。運算的實際結果不返回;文件中的任何表達式序列都必須存在,因為它的副作用。返回以下內容之一:
{ok,FullName}
該文件被讀取和運算。FullName是文件的全名。
{error,enoent}
該文件無法在Path中的任何目錄中找到 。
{error,atom()}
打開文件或讀取文件時發生錯誤。有關典型錯誤代碼的列表,請參閱open/2。
{error,{Line,Mod,Term}}
解釋文件中的Erlang表達式時發生錯誤。使用format_error/1將三元素元組轉換為錯誤的英文描述。
文件名的編碼可以通過epp(3)中描述的注釋來設置。
path_open(Path, Filename, Modes) -> {ok, IoDevice, FullName} | {error, Reason}
Types:
Path = [Dir :: name_all()]
Filename = name_all()
Modes = [mode()]
IoDevice = io_device()
FullName = filename_all()
Reason = posix() | badarg | system_limit
搜索路徑Path(目錄名稱列表),直到找到文件Filename。如果文件名是絕對文件名,則路徑被忽略。然后以Modes確定的模式打開文件。返回以下內容之一:
{ok,IoDevice,FullName}
該文件已在請求的模式下打開。 IoDevice是對文件的引用,FullName是文件的全名。
{錯誤,enoent}
該文件無法在Path中的任何目錄中找到 。
{error,atom()}
該文件無法打開。
path_script(Path, Filename) -> {ok, Value, FullName} | {error, Reason}
Types:
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。如果文件名是絕對文件名,則路徑被忽略。然后讀取並運算由'.'分隔的Erlang表達式。(或',',表達式序列也是一個表達式)。返回以下內容之一:
{ok,Value,FullName}
該文件被讀取和運算。全名是文件的全名值的最后一個表達式的值。
{error,enoent}
該文件無法在Path中的任何目錄中找到 。
{error,atom()}
打開文件或讀取文件時發生錯誤。有關典型錯誤代碼的列表,請參閱open/2。
{error,{Line,Mod,Term}}
解釋文件中的Erlang表達式時發生錯誤。使用format_error/1將三元素元組轉換為錯誤的英文描述。
文件名的編碼可以通過epp(3)中描述的注釋來設置。
path_script(Path, Filename) -> {ok, Value, FullName} | {error, Reason}
Types:
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。如果文件名是絕對文件名,則路徑被忽略。然后讀取並運算由'.'分隔的Erlang表達式。(或',',表達式序列也是一個表達式)。返回以下內容之一:
{ok,Value,FullName}
該文件被讀取和運算。全名是文件的全名值的最后一個表達式的值。
{error,enoent}
該文件無法在Path中的任何目錄中找到 。
{error,atom()}
打開文件或讀取文件時發生錯誤。有關典型錯誤代碼的列表,請參閱open / 2。
{error,{Line,Mod,Term}}
解釋文件中的Erlang表達式時發生錯誤。使用format_error/1將三元素元組轉換為錯誤的英文描述。
文件名的編碼可以通過epp(3)中描述的注釋來設置。
path_script(Path, Filename, Bindings) -> {ok, Value, FullName} | {error, Reason}
Types:
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(3)關於變量綁定。
pid2name(Pid) -> {ok, Filename} | undefined
Types:
Filename = filename_all()
Pid = pid()
如果Pid是IO設備,即從open/2返回的pid,則此函數返回文件名,或者更確切地說:
{ok,Filename}
如果此節點的文件服務器不是從屬節點,則該節點的文件服務器將打開文件(這意味着 Pid必須是本地pid),並且該文件未關閉。文件名是字符串格式的文件名。
undefined
在所有其他情況下。
警告
該功能僅用於調試。
position(IoDevice, Location) -> {ok, NewPosition} | {error, Reason}
Types:
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之外的其他編碼打開文件,則一個字節不對應一個字符。在這樣的文件中定位只能通過已知的字符邊界完成,也就是說,通過獲取當前位置,到文件的開始/結尾或其他某些已知位於正確字符邊界的位置(通常超出文件中的字節順序標記,它具有已知的字節大小)。
典型的錯誤原因是:
einval
無論是位置是非法的,或在文件中其偏移量計算為負。請注意,如果結果位置為負值,則結果為錯誤,並且在調用后文件位置未定義。
pread(IoDevice, LocNums) -> {ok, DataL} | eof | {error, Reason}
Types:
IoDevice = io_device()
LocNums = [{Location :: location(), Number :: integer() >= 0}]
DataL = [Data]
Data = string() | binary() | eof
Reason = posix() | badarg | terminated
在一次操作中執行pread/3的序列,這比一次調用它們更有效。返回{ok,[Data,...]}或 {error,Reason},其中每個Data(相應的pread的結果 )可以是列表或二進制文件,具體取決於文件的模式,或者eof,如果請求位置超出了文件結尾。
由於位置是以字節偏移量給出的,因此在處理編碼設置為latin1以外的文件時必須特別小心,因為並非每個字節位置都是此類文件上的有效字符邊界。
pread(IoDevice, Location, Number) -> {ok, Data} | eof | {error, Reason}
Types:
IoDevice = io_device()
Location = location()
Number = integer() >= 0
Data = string() | binary()
Reason = posix() | badarg | terminated
在一次操作中合並position/2和read/2,這比一次調用它們更有效。如果IoDevice已在原始模式下打開,則會有一些限制:位置只允許為整數; 操作后,文件的當前位置未定義。
由於位置是以字節偏移量給出的,因此在處理編碼設置為latin1以外的文件時必須特別小心,因為並非每個字節位置都是此類文件上的有效字符邊界。
pwrite(IoDevice, LocBytes) -> ok | {error, {N, Reason}}
Types:
IoDevice = io_device()
LocBytes = [{Location :: location(), Bytes :: iodata()}]
N = integer() >= 0
Reason = posix() | badarg | terminated
在一次操作中執行一系列pwrite/3,這比一次調用一個更有效。返回ok或{error,{N,Reason}},其中 N是在失敗之前完成的成功寫入次數。
當使用除latin1之外的其他編碼定位文件時,必須注意將位置設置在正確的字符邊界上,詳情請參閱position/2。
read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason}
Types:
IoDevice = io_device() | atom()
Number = integer() >= 0
Data = string() | binary()
Reason = posix()
| badarg
| terminated
| {no_translation, unicode, latin1}
從IoDevice引用的文件讀取Number字節/字符。read/2,pread/3 和read_line/1函數是從原始模式打開的文件讀取的唯一方法(盡管它們也適用於通常打開的文件)。
對於編碼設置為latin1以外的文件,文件中的一個字符可能由多個字節表示。參數Number始終表示從文件中讀取的字符數,為什么在讀取Unicode文件時文件中的位置可能比此數字移動得多。
另外,如果編碼設置為latin1以外的其他值,如果數據包含大於255的字符,則read/3調用將失敗,為什么讀取此類文件時首選io(3)模塊。
該函數返回:
{ok,Data}
如果文件以二進制模式打開,讀取的字節以二進制形式返回,否則以列表形式返回。如果文件結尾已達到,列表或二進制文件將短於請求的字節數。
eof
如果Number> 0和文件結尾已達到,則返回任何可以讀取的內容。
典型的錯誤原因:
ebadf
該文件未打開以供閱讀。
{no_translation,unicode,latin1}
該文件使用另一種編碼而不是latin1打開,並且文件中的數據不能轉換為該函數返回的字節數據。
read_file(Filename) -> {ok, Binary} | {error, Reason}
Types:
Filename = name_all()
Binary = binary()
Reason = posix() | badarg | terminated | system_limit
返回{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}
Types:
Filename = name_all()
Opts = [file_info_option()]
FileInfo = file_info()
Reason = posix() | badarg
檢索有關文件的信息。如果成功則返回 {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 time epoch(1970-01-01 00:00 UTC)之前或之后的秒數。默認是{time,local}。
注意
由於文件時間在大多數操作系統上以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}
Types:
IoDevice = io_device() | atom()
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的行。
該功能可用於以原始模式打開的文件。但是,如果未使用指定的{read_ahead,Size}選項打開文件,則在原始文件上使用它是低效的,這就是為什么在打開面向原始行讀取的文本文件時強烈建議組合raw和{read_ahead,Size}。
如果編碼設置為latin1以外的其他值,如果數據包含大於255的字符,則read_line/1調用將失敗,為什么讀取此類文件時首選io(3)模塊。
該函數返回:
{ok,Data}
返回文件中的一行,包括尾隨LF,但CRLF序列由單個LF替換(參見上文)。
如果文件以二進制模式打開,讀取的字節以二進制形式返回,否則以列表形式返回。
eof
如果在讀取任何內容之前已達到文件結尾,則返回。
{error, Reason}
發生錯誤。
典型的錯誤原因:
ebadf
該文件未打開以供閱讀。
{no_translation,unicode,latin1}
該文件是使用除latin1之外的其他編碼打開的,並且該文件上的數據無法轉換為此函數返回的面向字節的數據。
read_link(Name) -> {ok, Filename} | {error, Reason}
Types:
Name = name_all()
Filename = filename()
Reason = posix() | badarg
如果 Name引用不是“原始”文件名的符號鏈接,則返回{ok,Filename},否則返回{error,Reason} 。在不支持符號鏈接的平台上,返回值將是{error,enotsup}。
典型的錯誤原因:
einval
名稱不引用符號鏈接或引用的文件的名稱不符合預期的編碼。
enoent
該文件不存在。
enotsup
此平台不支持符號鏈接。
read_link_all(Name) -> {ok, Filename} | {error, Reason}
Types:
Name = name_all()
Filename = filename_all()
Reason = posix() | badarg
如果Name引用符號鏈接 ,則返回{ok,Filename},否則 返回{ error,Reason}。在不支持符號鏈接的平台上,返回值將是{error,enotsup}。
請注意,文件名可以是列表或二進制文件。
典型的錯誤原因:
einval
名稱不是指符號鏈接。
enoent
該文件不存在。
enotsup
此平台不支持符號鏈接。
read_link_info(Name) -> {ok, FileInfo} | {error, Reason}
read_link_info(Name, Opts) -> {ok, FileInfo} | {error, Reason}
Types:
Name = name_all()
Opts = [file_info_option()]
FileInfo = file_info()
Reason = posix() | badarg
這個函數的作用類似於read_file_info/1,2,除了如果Name是一個符號鏈接,關於該鏈接的信息將在file_info記錄中返回並且該記錄的類型字段將被設置為 符號鏈接。
如果Name不是符號鏈接,則此函數返回與read_file_info/1完全相同的結果。在不支持符號鏈接的平台上,此函數始終等效於read_file_info/1。
rename(Source, Destination) -> ok | {error, Reason}
Types:
Source = Destination = name_all()
Reason = posix() | badarg
嘗試將文件Source重命名為Destination。它可用於在目錄之間移動文件(和目錄),但僅指定目標是不夠的。目標文件名也必須指定。例如,如果bar是普通文件,而foo和baz是目錄,則重命名(“foo / bar”,“baz”)會返回錯誤,但重命名(“foo / bar”,“baz / bar”)會成功。如果成功則返回ok。
注意
在大多數平台上不允許重命名打開的文件(請參閱下面的eacces)。
典型的錯誤原因:
eacces
缺少源或目標的父目錄的讀或寫權限。在某些平台上,如果Source或Destination處於打開狀態,則會出現此錯誤 。
eexist
目的地不是空目錄。在某些平台上,當源和目標不是同一類型時也會給出。
einval
Source是根目錄,或者Destination是Source的子目錄。
eisdir
目的地是一個目錄,但Source不是。
enoent
來源不存在。
enotdir
Source是一個目錄,但Destination不是。
exdev
源和目標位於不同的文件系統上。
script(Filename) -> {ok, Value} | {error, Reason}
Types:
Filename = name_all()
Value = term()
Reason = posix()
| badarg
| terminated
| system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}
讀取和運算由'.'分隔的Erlang表達式。(或',',表達式序列也是表達式),來自文件。返回以下之一:
{ok,Value}
該文件被讀取和運算。值是最后一個表達式的值。
{error,atom()}
打開文件或讀取文件時發生錯誤。有關典型錯誤代碼的列表,請參見open/2。
{error,{Line,Mod,Term}}
解釋文件中的Erlang表達式時發生錯誤。使用format_error/1將三元素元組轉換為錯誤的英文描述。
文件名的編碼可以通過epp(3)中描述的注釋來設置。
script(Filename, Bindings) -> {ok, Value} | {error, Reason}
Types:
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(3)。
set_cwd(Dir) -> ok | {error, Reason}
Types:
Dir = name()
Reason = posix() | badarg | no_translation
將文件服務器的當前工作目錄設置為Dir。如果成功則返回ok。
典型的錯誤原因是:
enoent
該目錄不存在。
enotdir
Dir的一個組件不是一個目錄。在某些平台上,返回enoent。
eacces
沒有目錄或其父目錄的權限。
badarg
Dir有一個不正確的類型,比如元組。
no_translation
Dir是一個二進制,其字符以ISO-latin-1編碼,VM以參數+ fnue開始。
警告
在未來的版本中,Dir 參數的錯誤類型可能會生成異常。
sync(IoDevice) -> ok | {error, Reason}
Types:
IoDevice = io_device()
Reason = posix() | badarg | terminated
確保操作系統(而不是Erlang運行時系統)保存的任何緩沖區都寫入磁盤。在某些平台上,此功能可能不起作用。
典型的錯誤原因是:
enospc
沒有足夠的空間來寫入文件。
datasync(IoDevice) -> ok | {error, Reason}
Types:
IoDevice = io_device()
Reason = posix() | badarg | terminated
確保操作系統(而不是Erlang運行時系統)保存的任何緩沖區都寫入磁盤。在許多方面,它類似於fsync,但不需要更新文件的某些元數據,如訪問時間。在某些平台上,此功能可能不起作用。
訪問數據庫或日志文件的應用程序通常會寫入一個小小的數據片段(例如,日志文件中的一行),然后立即調用fsync()以確保寫入的數據物理存儲在硬盤上。不幸的是,fsync()將始終啟動兩個寫操作:一個用於新寫入的數據,另一個用於更新存儲在inode中的修改時間。如果修改時間不是事務概念的一部分,則可以使用fdatasync()來避免不必要的inode磁盤寫入操作。
僅在某些POSIX系統中可用。此調用會導致在未實現fdatasync系統調用的系統中調用fsync()或無效。
truncate(IoDevice) -> ok | {error, Reason}
Types:
IoDevice = io_device()
Reason = posix() | badarg | terminated
截斷在當前位置由IoDevice引用的文件。如果成功則返回ok,否則{error,Reason}。
sendfile(Filename, Socket) -> {ok, integer() >= 0} | {error, inet:posix() | closed | badarg | not_owner}
Types:
Filename = name_all()
Socket = inet:socket()
將文件Filename發送到Socket。如果成功則返回{ok,BytesSent},否則返回{error,Reason}。
sendfile(RawFile, Socket, Offset, Bytes, Opts) ->
{ok, integer() >= 0} |
{error, inet:posix() | closed | badarg | not_owner}
Types:
RawFile = fd()
Socket = inet:socket()
Offset = Bytes = integer() >= 0
Opts = [sendfile_option()]
sendfile_option() = {chunk_size, integer() >= 0}
從偏移量開始,從RawFile引用的文件發送字節到套接字。如果成功則返回{ok,BytesSent},否則返回{error,Reason}。如果字節設置為0,則發送給定偏移后的所有數據。
必須使用原始標志打開使用的文件,並且調用sendfile的進程必須是套接字的控制進程。請參見gen_tcp:controlling_process/2
如果使用的操作系統不支持sendfile,則使用file:read和gen_tcp:send的Erlang fallback。
選項列表可以包含以下選項:
chunk_size
erlang fallback用於發送數據的塊大小。如果使用fallback功能,則應將其設置為適合系統內存的值。默認值是20 MB。
在具有線程支持的操作系統上,建議使用異步線程。看命令行標記 +A在ERL(1) 。如果無法使用sendfile的異步線程,則建議為套接字上的發送緩沖區使用相對較小的值。否則,Erlang虛擬機可能會失去一些軟實時保證。要使用哪種大小取決於操作系統/硬件和應用程序的要求。
write(IoDevice, Bytes) -> ok | {error, Reason}
Types:
IoDevice = io_device() | atom()
Bytes = iodata()
Reason = posix() | badarg | terminated
將字節寫入IoDevice引用的文件 。此功能是寫入以原始模式打開的文件的唯一方式(盡管它也適用於通常打開的文件)。如果成功則返回ok ,否則返回{error,Reason}。
如果使用設置為latin1以外的編碼打開文件,寫入的每個字節都可能導致實際寫入文件的幾個字節,因為字節范圍0..255可能表示1到4個字節之間的任何值,具體取決於值和UTF編碼類型。
典型的錯誤原因是:
ebadf
該文件未打開以進行寫入。
enospc
設備上沒有剩余空間。
write_file(Filename, Bytes) -> ok | {error, Reason}
Types:
Filename = name_all()
Bytes = iodata()
Reason = posix() | badarg | terminated | system_limit
將iodata的內容寫入文件Filename。如果文件不存在,則創建該文件。如果存在,則先前的內容被覆蓋。返回ok,或者{error,Reason}。
典型的錯誤原因是:
enoent
文件名的一個組件不存在。
enodir
文件名的一個組件不是一個目錄。在某些平台上,取而代之的是返回enoent。
enospc
設備上沒有剩余空間。
eacces
缺少寫入文件或搜索其中一個父目錄的權限。
eisdir
指定的文件是一個目錄。
write_file(Filename, Bytes, Modes) -> ok | {error, Reason}
Types:
Filename = name_all()
Bytes = iodata()
Modes = [mode()]
Reason = posix() | badarg | terminated | system_limit
與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必須是自1970年1月1日00:00 UTC之前或之前的秒數。默認是{time,local}。
如果給出了以下字段,則從記錄中使用。
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 - IO錯誤
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)仍然存在問題。
為了提高性能,建議使用原始文件。原始文件使用節點主機的文件系統。對於普通文件(非原始文件),文件服務器用於查找文件,如果節點正在將其文件服務器作為從屬節點運行到其他節點,並且其他節點在其他主機上運行,則它們可能具有不同的文件系統。這很少是一個問題,但你現在已經受到警告。
普通文件實際上是一個進程,因此它可以用作IO設備(請參閱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).
在每次調用file:write/2之前,以下功能相當的函數將1024個條目收集到128個32字節二進制文件列表中, 並在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主機上,盡可能使用分散輸出(在一個操作中寫入一組緩沖區)。通過這種方式file:write(FD,[Bin1,Bin2 | Bin3])將寫入二進制文件的內容,而不會復制數據,除了可能在操作系統內核深處。
對於原始文件,pwrite/2和pread/2被高效地實現。文件驅動程序只對整個操作調用一次,並且列表迭代在文件驅動程序中完成。
選項delayed_write和read_ahead到 file:open/2使文件驅動程序緩存數據減少操作系統調用的數量。上面示例中的函數 create_file/2需要60秒,而不使用delayed_write選項,速度較慢2.6倍。
而且,作為一個非常糟糕的例子,create_file_slow/2上面沒有raw,binary和delayed_write選項,也就是它調用file:open(Name,[write]),這個作業需要1分20秒,這比慢3.5倍比第一個例子慢150倍,比優化的create_file/2慢150倍。
警告
如果使用io模塊訪問打開的文件時發生錯誤,則處理該文件的進程將退出。如果一個進程稍后嘗試訪問它,死文件進程可能會掛起。這將在未來的版本中修復。