如何在Erlang中创建临时文件名?

11dmarpk  于 2022-12-08  发布在  Erlang
关注(0)|答案(6)|浏览(142)

I need to put data in a file since my other function takes a file as input.
How do I create a unique filename in Erlang?
Does something like unix "tempfile" exist?

h9a6wy2h

h9a6wy2h1#

你的意思是只生成实际的文件名吗?在这种情况下,最安全的方法是使用从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>
1szpjjfi

1szpjjfi2#

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

umuewwlo

umuewwlo3#

或者你可以
erlang:phash2(make_ref())
一个快速简单的唯一标识符。对于2^82个调用来说是唯一的,这对于你的目的来说应该足够了。我发现这比用节点名格式化时间戳要容易。

798qvoo8

798qvoo84#

迟回答:我刚刚注意到test_server模块,它支持临时目录,值得一看
http://www.erlang.org/doc/man/test_server.html#temp_name-1

93ze6v8z

93ze6v8z5#

I've finally had this problem -- and my user is using a mix of Windows and Linux systems, so the old tried-and-true lib:nonl(os:cmd("mktemp")) method is just not going to cut it anymore.
So here is how I've approached it, both with a mktemp/1 function that returns a filename that can be used and also a mktemp_dir/1 function that returns a directory (after having created it).

-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.

And the directory version:

-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.

Both of these do basically the same thing: we get a strongly random name as a binary, convert that to a base36 string, and append it to whatever the OS returns to us as a safe user-local temporary cache location.
On a unix type system, of course, we could just use filename:join(["/tmp", Prefix, Rand]) but the unavailability of /tmp on Windows is sort of the whole point here.

zazmityj

zazmityj6#

In OTP 24 there is not file:ensure_dir . So I've made something similar:
For directory:

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.

For file:

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.

相关问题