2009-08-03 8 views

Répondre

12

Voulez-vous dire simplement générer le nom de fichier acutal? Dans ce cas, le moyen le plus sûr serait d'utiliser un mélange des numéros que vous obtenez maintenant() et le nom d'hôte de votre ordinateur (si vous avez plusieurs nœuds faisant la même chose).

Quelque chose comme:

1> {A,B,C}=now(). 
{1249,304278,322000} 
2> N=node(). 
[email protected] 
3> lists:flatten(io_lib:format("~p-~p.~p.~p",[N,A,B,C])). 
"[email protected]" 
4> 
+4

Comme tout le monde ne le sait pas: les appels à erlang: now() garantissent des résultats uniques à chaque fois. Propriété assez utile ... – viraptor

+0

Oui, très utile. Il y a une autre chose qui est très utile avec cette façon de générer une référence; vous obtenez le nom de noeud qui est très utile si vous voulez d'abord vous assurer que l'identifiant est toujours unique (vous pouvez le traiter comme une référence locale) et le second pour savoir d'où vient la référence. Dans notre système (avec n nœuds dans le cluster et les données partagées, etc.), nous pouvons facilement trouver les journaux et les informations dont nous avons besoin à propos d'un travail en utilisant cet identifiant seulement (Node + Time). –

+0

Il échouera si un tel fichier existe déjà. erlang: now() ne peut pas garantir que le fichier n'existe pas. –

9

Vous pouvez également utiliser TMP = lib:nonl(os:cmd("mktemp")).

+2

Légèrement plus laide, mais 'string: strip (os: cmd (" mktemp "), à droite, $ \ n)' peut éviter cette nouvelle ligne invisible ennuyante qui sera généralement renvoyée à la fin. – zxq9

+1

Version plus courte: 'lib: nonl (os: cmd (" mktemp "))'. –

+0

Bien que cela fonctionne, il dépend de la plate-forme. –

6

Ou vous pourriez faire

erlang:phash2(make_ref())

pour un indentifier rapide et facile unique. Unique pour jusqu'à 2^82 appels, ce qui devrait être suffisant pour vos besoins. Je trouve cela plus facile que de mettre en forme un horodatage avec un nom de noeud à utiliser.

1

réponse tardive: Je viens de remarquer le module test_server qui a un support de répertoire scratch, en valeur un regard

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

+0

Il ne garantit pas que ce fichier n'existera pas à temps, vous essaierez de créer ce fichier. Donc ce n'est pas sécurisé. C'est pourquoi il y a 'mkstemp' dans' stdlib.h'. 'mktemp' de GNU coreutils utilise l'appel' mkstemp' en interne. –

0

J'ai enfin eu ce problème - et mon utilisateur utilise un mélange de Windows et Systèmes Linux, donc la vieille méthode éprouvée lib:nonl(os:cmd("mktemp")) ne va tout simplement plus la couper.

Voici donc comment je l'ai abordé, à la fois avec une fonction mktemp/1 qui retourne un nom de fichier qui peut être utilisé et aussi une fonction mktemp_dir/1 qui retourne un répertoire (après l'avoir créé).

-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 = file:ensure_dir(TempFile), 
    Result2 = file:write_file(TempFile, <<>>), 
    case {Result1, Result2} of 
     {ok, ok} -> {ok, TempFile}; 
     {ok, Error} -> Error; 
     {Error, _} -> Error 
    end. 

Et la version du répertoire:

-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 = file:ensure_dir(TempDir), 
    Result2 = file:make_dir(TempDir), 
    case {Result1, Result2} of 
     {ok, ok} -> {ok, TempDir}; 
     {ok, Error} -> Error; 
     {Error, _} -> Error 
    end. 

Ces deux font essentiellement la même chose: nous obtenons un nom fortement aléatoire comme binaire, convertir en une chaîne de base36, et l'ajouter à tout le système d'exploitation nous revient en tant qu'emplacement de cache temporaire local-utilisateur sécurisé.

Sur un système de type Unix, bien sûr, nous pourrions simplement utiliser filename:join(["/tmp", Prefix, Rand]) mais l'indisponibilité de /tmp sur Windows est en quelque sorte le point entier ici.

Questions connexes