9

我需要将数据放入文件中,因为我的其他函数将文件作为输入。

如何在 Erlang 中创建唯一的文件名?

是否存在诸如 unix“tempfile”之类的东西?

4

6 回答 6

12

您的意思是只生成实际文件名吗?在这种情况下,最安全的方法是混合使用从 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> 
于 2009-08-03T12:59:14.647 回答
10

你也可以使用TMP = lib:nonl(os:cmd("mktemp")).

于 2009-08-03T15:44:07.023 回答
7

或者你可以做

erlang:phash2(make_ref())

快速简便的唯一标识符。最多可用于 2^82 次调用,这对于您的目的来说应该足够了。我发现这比使用节点名称格式化时间戳更容易。

于 2009-08-06T00:14:31.820 回答
1

迟到的答案:我刚刚注意到 test_server 模块支持暂存目录,值得一看

http://www.erlang.org/doc/man/test_server.html#temp_name-1

于 2009-09-06T15:34:50.190 回答
1

我终于遇到了这个问题——而且我的用户混合使用了 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是这里的重点。

于 2017-08-12T04:36:00.680 回答
0

在 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.
于 2021-06-24T15:15:27.900 回答