Erlang——文件编程
文件编程
操作函数的函数模块:
- file模块 ,包含文件打开、关闭、读取、写入和目录列表等功能的函数。
- filename模块 ,以平台独立的方式提供了一套操作文件名的函数,支持在不同操作系统上执行相同操作,无需修改代码。
- filelib模块 ,file模块的扩展。提供了一套辅助函数,用于生成文件列表,检验文件类型等操作,大多数代码是基于file模块的函数编写的。
- io模块 ,提供了一系列对已打开的文件进行操作的函数,有可以用于文件中数据的解析以及向文件写入格式化的数据的函数。
读取文件
创建一个文件File,Erlang数据文件如下文件为例进行文件操作,命名为data1.dat。文件内包含一串Erlang数据,是一串多行文本,一块没有经过特别处理的二进制原始数据。
{person,"harry","armstrong",
[{occupation,programmer},
{favoriteLanguage,erlang}]}.
{cat,{name,"moka"},
{owner,"joy"}}.
文本文件以如下文件为例进行文件操作,命名为text.dat。
Everything will be ok!1
Everything will be ok!2
Everything will be ok!3
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
1. 读取全部数据
1) 操作data1.dat文件(读取所有Erlang数据项):
file:consult(File).
假定File指定的文件中包含了一串Erlang的数据项,如果他可以读取文件中所有数据项,则返回{ok,[term]};否则若遇到非Erlang数据项,则返回错误信息{error,Reason}。
PS D:\Erlang6m\first> cd src
PS D:\Erlang6m\first\src> erl
Eshell V10.7 (abort with ^G)
1> file:consult("data1.dat").
{ok,[{person,"harry","armstrong",
[{occupation,programmer},{favoriteLanguage,erlang}]},
{cat,{name,"moka"},{owner,"joy"}}]}
2)操作text.txt文件(读取文档所有数据):
file:open(File, read) -> {ok, IoDevice} | {error, Why}.
尝试打开File进行读取。如果它能打开文件就会返回{ok, IoDevice},否则返回{error, Reason}。IoDevice是一个用来访问文件的I/O对象。(read或[read]都可以)
file:read(IoDevice, Number).
从文件的引用 IoDevice 读取 Number 个字节/字符的数据。
file:close(IoDevice) -> ok | {error, Why}.
关闭IoDevice。
13> {ok, File} = file:open("text.txt",read).
{ok,<0.99.0>}
14> file:read(File,1024 * 1024).
{ok,"Everything will be ok!1\r\nEverything will be ok!2\r\nEverything will be ok!3"}
15> file:close(File).
2. 一次读取一个数据项
如果从文件的数据项中一次读取一项的话,首先用file:open打开文件,然后用file:read读取独立的数据项,直到我们读到文件的末尾,最后使用file:close关闭文件。
io:read(IoDevice, Prompt) -> {ok, Term} | {error,Why} | eof.
从IoDevice读取一个Erlang数据类型Term。如果IoDevice代表一个被打开的文件,Prompt就会被忽略。只有用io:read读取标准输入时,才会用Prompt提供一个提示符。
操作data1.dat文件:
8> {ok,S}=file:open("data1.dat",read).
{ok,<0.93.0>}
9> io:read(S,'').
{ok,{person,"harry","armstrong",
[{occupation,programmer},{favoriteLanguage,erlang}]}}
10> io:read(S,'').
{ok,{cat,{name,"moka"},{owner,"joy"}}}
11> io:read(S,'').
eof
12> file:close(S).
ok
3.一次读取一行
将io:read换为io:get_line。
io:get_line(IoDevice, Prompt)
会一直读取字符,直到遇上换行符或者文件尾。
1)操作data1.dat文件:
PS D:\Erlang6m\first> cd src
PS D:\Erlang6m\first\src> erl
Eshell V10.7 (abort with ^G)
1> {ok,S}=file:open("data1.dat",read).
{ok,<0.79.0>}
2> io:get_line(S,'').
"{person,\"harry\",\"armstrong\",\n"
3> io:get_line(S,'').
" [{occupation,programmer},\n"
4> io:get_line(S,'').
" {favoriteLanguage,erlang}]}.\n"
5> io:get_line(S,'').
"{cat,{name,\"moka\"},\n"
6> io:get_line(S,'').
" {owner,\"joy\"}}.\n"
7> io:get_line(S,'').
eof
8> file:close(S).
ok
2)操作text.txt文件:
9> {ok, File} = file:open("Text.txt",read).
{ok,<0.88.0>}
10>
io:get_line(File,'').
"Everything will be ok!1\n"
11> io:get_line(File,'').
"Everything will be ok!2\n"
12> io:get_line(File,'').
"Everything will be ok!3"
13> io:get_line(File,'').
eof
14> file:close(File).
ok
4.把整个文件的内容读入到一个二进制数据中
file:read_file(File)
把整个文件读入一个二进制数据中,可以使用单个原子操作。是读取文件最快速的一种方法。可以用这个操作把整块文件读入内存,在内存中处理读入的内容,再用file:write_file将新的数据存回到文件中去
1)操作data1.dat文件:
18> file:read_file("data1.dat").
{ok,<<"{person,\"harry\",\"armstrong\",\r\n [{occupation,programmer},\r\n {favoriteLanguage,erl
ang}]}.\r\n{cat,{name,\"m"...>>}
2)操作text.txt文件:
19> file:read_file("text.txt").
{ok,<<"Everything will be ok!1\r\nEverything will be ok!2\r\nEverything will be ok!3">>}
4.随机读取一个文件
从任何想要访问的位置读取文件。可以应用于文件很庞大或他的二进制数据使用了第三方定义的格式等情景。
file:pread(File)
会从IoDevice的第Start字节处(文件里的字节会被编号,所以文件里第一个字节的位置是0,示例文件真正数据编号即从1开始),读取Len个字节的数据。
2> file:pread(S, 12, 34).
{ok,<<"ry\",\"armstrong\",\r\n [{occupation">>}
3> file:pread(S, 0, 4).
{ok,<<"{per">>}
4> file:close(S).
ok
写入文件
1.写入一串Erlang数据项
自定义unconsult函数
file:open(File,write)
用write模式打开一个文件。
io:format(IoDevice,Format,Args)->ok
IoDevice必须是以write模式打开的一个IO设备。Format包含格式化代码的字符串,Args是需要输出的数据项
-export([unconsult/2]).
unconsult(File,L)->
{ok,S}=file:open(File,write),
lists:foreach(fun(X)->io:format(S,"~p.~n",[X]) end,L),
file:close(S).
执行unconsult函数,创建test1.dat文件:
1> c(lib_misc).
{ok,lib_misc}
2> lib_misc:unconsult("test1.dat",[{cats,["yolo","loogi"]},{weather,snowing}]).
ok
3> file:consult("test1.dat").
{ok,[{cats,["yolo","loogi"]},{weather,snowing}]}
2.写入一行数据
1>
{ok,S}=file:open("test2.dat",write).
{ok,<0.79.0>}
2> io:format(S,"~s~n",["Everything will be ok"]).
ok
3> io:format(S,"~s~n",["1123"]).
ok
4> io:format(S,"~s~n",["a good day"]).
ok
5> file:close(S).
ok
当前文件夹下增加test2.dat文件:
Everything will be ok
1123
a good day
3.随机访问模式下写入文件
2> {ok, File} = file:open("Text.txt",[raw,write,binary]).
{ok,{file_descriptor,prim_file,
#{handle => #Ref<0.2146451845.1150943249.146480>,
owner => <0.79.0>,r_ahead_size => 0,
r_buffer => #Ref<0.2146451845.1150943238.146648>}}}
3> file:pwrite(File,10,<<"new">>).
ok
5> file:close(File).
ok
在文件的第10个字节处写入一串新的字符串,会覆盖掉原先的内容
目录操作
list_dir(Dir)
函数用于生成Dir目录下的文件列表
make_dir(Dir)
用来创建一个新的目录
del_dir(Dir)
用来删除目录
6> cd("/first/src").
d:/Erlang6m/first/src
ok
7> file:list_dir(".").
{ok,["app","area_server0.beam","area_server0.erl",
"clock.beam","clock.erl","data1.dat","first.app.src",
"geometry.erl","hong.beam","hong.erl","kaohe","kvs.beam",
"kvs.erl","lib_misc.beam","lib_misc.erl",
"mod_name_server.cfg","mod_name_server.erl",
"name_server.beam","name_server.erl","port","practice",
"scavenge_urls.erl","server1.beam","server1.erl",
"stimer.beam","stimer.erl",
[...]|...]}