我需要将数据放入文件中,因为我的其他函数将文件作为输入。
如何在 Erlang 中创建唯一的文件名?
是否存在诸如 unix“tempfile”之类的东西?
您的意思是只生成实际文件名吗?在这种情况下,最安全的方法是混合使用从 now() 获得的数字和计算机的主机名(如果您有多个节点在做同样的事情)。
就像是:
1> {A,B,C}=now().
{1249,304278,322000}
2> N=node().
nonode@nohost
3> lists:flatten(io_lib:format("~p-~p.~p.~p",[N,A,B,C])).
"nonode@nohost-1249.304278.322000"
4>
你也可以使用TMP = lib:nonl(os:cmd("mktemp")).
或者你可以做
erlang:phash2(make_ref())
快速简便的唯一标识符。最多可用于 2^82 次调用,这对于您的目的来说应该足够了。我发现这比使用节点名称格式化时间戳更容易。
迟到的答案:我刚刚注意到 test_server 模块支持暂存目录,值得一看
我终于遇到了这个问题——而且我的用户混合使用了 Windows 和 Linux 系统,所以老的久经考验的lib:nonl(os:cmd("mktemp"))
方法不再适用了。
所以这就是我处理它的方法,既使用mktemp/1
返回可以使用的文件名的mktemp_dir/1
函数,也使用返回目录的函数(在创建目录之后)。
-spec mktemp(Prefix) -> Result
when Prefix :: string(),
Result :: {ok, TempFile :: file:filename()}
| {error, Reason :: file:posix()}.
mktemp(Prefix) ->
Rand = integer_to_list(binary:decode_unsigned(crypto:strong_rand_bytes(8)), 36),
TempPath = filename:basedir(user_cache, Prefix),
TempFile = filename:join(TempPath, Rand),
Result1 = filelib:ensure_dir(TempFile),
Result2 = file:write_file(TempFile, <<>>),
case {Result1, Result2} of
{ok, ok} -> {ok, TempFile};
{ok, Error} -> Error;
{Error, _} -> Error
end.
和目录版本:
-spec mktemp_dir(Prefix) -> Result
when Prefix :: string(),
Result :: {ok, TempDir :: file:filename()}
| {error, Reason :: file:posix()}.
mktemp_dir(Prefix) ->
Rand = integer_to_list(binary:decode_unsigned(crypto:strong_rand_bytes(8)), 36),
TempPath = filename:basedir(user_cache, Prefix),
TempDir = filename:join(TempPath, Rand),
Result1 = filelib:ensure_dir(TempDir),
Result2 = file:make_dir(TempDir),
case {Result1, Result2} of
{ok, ok} -> {ok, TempDir};
{ok, Error} -> Error;
{Error, _} -> Error
end.
这两者的作用基本相同:我们得到一个高度随机的二进制名称,将其转换为 base36 字符串,并将其附加到操作系统返回给我们的任何内容,作为安全的用户本地临时缓存位置。
当然,在 unix 类型的系统上,我们可以使用filename:join(["/tmp", Prefix, Rand])
,但在 Windows 上不可用/tmp
是这里的重点。
在 OTP 24 中没有file:ensure_dir
. 所以我做了类似的事情:
对于目录:
mktemp_dir(Prefix) ->
Rand = integer_to_list(binary:decode_unsigned(crypto:strong_rand_bytes(8)), 36),
TempDir = filename:basedir(user_cache, Prefix),
[]= os:cmd("mkdir " ++ "\"" ++ TempDir ++ "\""),
{ok, _} = file:list_dir(TempDir),
TempDir.
对于文件:
mktemp(Prefix) ->
Rand = integer_to_list(binary:decode_unsigned(crypto:strong_rand_bytes(8)), 36),
TempDir = filename:basedir(user_cache, Prefix),
TempFile = filename:join(TempDir, Rand),
[]= os:cmd("mkdir " ++ "\"" ++ TempDir ++ "\""),
{ok, _} = file:list_dir(TempDir),
Result = file:write_file(TempFile, <<>>),
case {Result} of
{ok} -> {ok, TempFile};
{Error} -> Error
end.