file_sorter
file_sorter
模块
file_sorter
模块摘要
档案分类器。
描述
此模块包含对文件进行排序、合并已排序文件和检查文件排序的功能。包含二进制术语的块从文件序列中读取,在内存中进行内部排序,并写入临时文件,临时文件合并后产生一个排序文件作为输出。合并是作为一种优化提供的;当文件已经排序时,合并更快,但是它总是可以进行排序而不是合并。
在文件中,术语由标题和二进制表示。有两个选项定义了文件的术语格式:
{header, HeaderLength}
HeaderLength确定每个二进制文件之前的字节数,并包含二进制文件的长度(以字节为单位)。默认为4。头字节的顺序定义如下:B是仅包含标题的二进制文件大小。Size的二进制值计算为<<Size:HeaderLength/unit:8>> = B...
{format, Format}
期权Format确定应用于二进制文件以创建要排序的项的函数。默认为binary_term,这相当于fun binary_to_term/1.价值binary等于fun(X) -> X end,这意味着二进制文件按原样排序。这是最快的格式。如果Format是term,io:read/2是用来阅读术语的。在这种情况下,只有选项的默认值header是允许的。
期权format
还确定写入排序输出文件的内容:如果Format
是term
,然后io:format/3
被调用来写入每个项,否则将写入以标题为前缀的二进制文件。请注意,所写的二进制文件与已读取的二进制文件相同;应用函数的结果。Format
在条件被分类后被丢弃。使用io
模块比读取和写入二进制文件要慢得多。
其他选择包括:
{order, Order}
缺省值是按升序对条目进行排序,但可以按值降序或指定排序函数Fun进行更改。 排序功能是反对称的,传递的和总的。 如果A在排序中位于B之前,则乐趣(A,B)将返回true,否则为false。 一个典型的排序函数的例子小于或等于= </ 2。 使用排序功能会显着降低排序。 函数keysort,keymerge和keycheck不接受排序功能。
{unique, boolean()}
在排序或合并文件时,==
如果此选项设置为仅输出比较equal()的术语序列的第一个true
。默认为false
,这意味着输出比较相等的所有项。在检查文件的排序时,如果此选项设置为,则检查是否没有任何连续条件比较相等true
。
{tmpdir, TempDirectory}
临时文件的放置目录可以明确选择。缺省值(默认值""
)是将临时文件放在与已排序的输出文件相同的目录中。如果输出是一个函数(见下文),file:get_cwd()
则使用返回的目录。临时文件的名称来源于Erlang nodename(node()
),当前Erlang仿真器(os:getpid()
)的进程标识符以及唯一的整数(erlang:unique_integer([positive])
)。一个典型的名字是fs_mynode@myhost_1763_4711.17
,其中17
是序列号。现有的文件被覆盖。临时文件被删除,除非有一些未被捕获的EXIT
信号出现。
{compressed, boolean()}
临时文件和输出文件可以被压缩。缺省值false
,这意味着编写的文件不会被压缩。不管期权的价值compressed
,压缩文件总是可以读取的。注意,读取和写入压缩文件比读取和写入未压缩文件要慢得多。
{size, Size}
默认情况下,从文件中读取的大约512 * 1024个字节在内部排序。这个选项很少需要。
{no_files, NoFiles}
默认情况下,一次合并16个文件。这种选择很少需要。
作为对文件排序的替代方法,可以指定一个参数的函数作为输入。当用参数调用read
时,假定该函数返回下列任一项:
end_of_input
或者{end_of_input, Value}}
当没有更多的输入时(Value
在下面解释)。
{Objects, Fun}
,其中Objects
是取决于格式的二进制文件或术语列表,并且Fun
是新的输入函数。
任何其他值都会立即作为当前调用的值返回。sort
或keysort
.每个输入函数精确地调用一次。如果发生错误,则使用参数调用最后一个函数。close
的答复被忽略了。
一个参数的函数可以指定为输出。排序或合并输入的结果根据格式以可变长度列表、二进制文件或术语的非空顺序收集。每次使用一个列表调用输出函数,并假设返回一个新的输出函数。任何其他返回值都将立即作为当前对排序或合并函数的调用的值返回。每个输出函数精确地调用一次。当某些输出函数已应用于所有结果或发生错误时,最后一个函数将被用参数调用。close
,并将应答作为对排序或合并函数的当前调用的值返回。
如果将函数指定为输入,而最后一个输入函数返回{end_of_input, Value}
,则调用指定为输出的函数并使用参数。{value, Value}
这使得使用由输入函数计算的值来启动输出函数序列变得非常容易。
例如,考虑对磁盘日志文件上的术语进行排序。将从磁盘日志中读取块并返回二进制文件列表的函数用作输入。这些结果是以一组术语收集的。
sort(Log) ->
{ok, _} = disk_log:open([{name,Log}, {mode,read_only}]),
Input = input(Log, start),
Output = output([]),
Reply = file_sorter:sort(Input, Output, {format,term}),
ok = disk_log:close(Log),
Reply.
input(Log, Cont) ->
fun(close) ->
ok;
(read) ->
case disk_log:chunk(Log, Cont) of
{error, Reason} ->
{error, Reason};
{Cont2, Terms} ->
{Terms, input(Log, Cont2)};
{Cont2, Terms, _Badbytes} ->
{Terms, input(Log, Cont2)};
eof ->
end_of_input
end
end.
output(L) ->
fun(close) ->
lists:append(lists:reverse(L)
(Terms) ->
output([Terms | L])
end.
有关输入和输出函数的更多示例,请参见file_sorter
模块term
格式是用函数实现的。
的可能值Reason
发生错误时返回的内容如下:
bad_object
,{bad_object, FileName}
-应用的格式化功能失败一些二进制,或者键(S)不能从一些长期提取。
{bad_term, FileName}
-io:read/2
没有阅读一些术语。
{file_error, FileName, file:posix()}
-请解释file:posix()
,见file(3)
...
{premature_eof, FileName}
-文件结束时遇到了一些二进制术语。
数据类型
file_name() = file:name()
file_names() = [file:name()]
i_command() = read | close
i_reply() =
end_of_input |
{end_of_input,
value()
} |
{[
object()
],
infun()
} |
input_reply()
infun() = fun((i_command()) ->i_reply())
input() =
file_names()
|
infun()
input_reply() = term()
o_command() = {value,
value()
} | [
object()
] | close
o_reply() =
outfun()
|
output_reply()
object() = term() | binary()
outfun() = fun((o_command()) ->o_reply())
output() =
file_name()
|
outfun()
output_reply() = term()
value() = term()
options() = [
option()
] |
option()
option() =
{compressed, boolean()} |
{header,
header_length()
} |
{format,
format()
} |
{no_files,
no_files()
} |
{order,
order()
} |
{size,
size()
} |
{tmpdir,
tmp_directory()
} |
{unique, boolean()}
format() = binary_term | term | binary |
format_fun()
format_fun() = fun((binary()) -> term())
header_length() = integer() >= 1
key_pos() = integer() >= 1 | [integer() >= 1]
no_files() = integer() >= 1
order() = ascending | descending |
order_fun()
order_fun() = fun((term(), term()) -> boolean())
size() = integer() >= 0
tmp_directory() = [] | file:name()
reason() =
bad_object |
{bad_object,
file_name()
} |
{bad_term,
file_name()
} |
{file_error,
file_name()
,
file:posix() | badarg | system_limit} |
{premature_eof,
file_name()
}
输出
check(FileName) -> Reply
check(FileNames, Options) -> Reply
类型
检查文件是否有条理。如果没有对文件进行排序,则返回第一个无序元素。文件上的第一个项具有第1位置。
check(FileName)
等于check([FileName], [])
...
keycheck(KeyPos, FileName) -> Reply
keycheck(KeyPos, FileNames, Options) -> Reply
类型
检查文件是否有条理。如果没有对文件进行排序,则返回第一个无序元素。文件上的第一个项具有第1位置。
keycheck(KeyPos, FileName)
等于keycheck(KeyPos, [FileName], [])
...
keymerge(KeyPos, FileNames, Output) -> Reply
keymerge(KeyPos, FileNames, Output, Options) -> Reply
类型
在文件上合并元组。假定每个输入文件都按键排序。
keymerge(KeyPos, FileNames, Output)
相当于keymerge(KeyPos, FileNames, Output, [])
。
keysort(KeyPos, FileName) -> Reply
类型
对文件进行元组排序。
keysort(N, FileName)
等于keysort(N, [FileName], FileName)
...
keysort(KeyPos, Input, Output) -> Reply
keysort(KeyPos, Input, Output, Options) -> Reply
类型
对文件进行元组排序。排序是在中提到的元素上执行的KeyPos
。如果两个元组==
在一个元素上比较equal(),KeyPos
则会比较下一个元素。排序稳定。
keysort(N, Input, Output)
等于keysort(N, Input, Output, [])
...
merge(FileNames, Output) -> Reply
merge(FileNames, Output, Options) -> Reply
类型
合并文件上的条款。假设每个输入文件都被排序。
merge(FileNames, Output)
等于merge(FileNames, Output, [])
...
sort(FileName) -> Reply
类型
对文件进行排序。
sort(FileName)
等于sort([FileName], FileName)
...
sort(Input, Output) -> Reply
sort(Input, Output, Options) -> Reply
类型
对文件进行排序。
sort(Input, Output)
等于sort(Input, Output, [])
...