¿Cómo creo un nombre de archivo temporal en Erlang?
Pregunta
Necesito poner datos en un archivo ya que mi otra función toma un archivo como entrada.
¿Cómo creo un nombre de archivo único en Erlang?
Hace algo así como unix "tempfile" existe?
Solución
¿Quiere decir simplemente generar el nombre de archivo acutal? En ese caso, la forma más segura sería utilizar una combinación de los números que obtiene a partir de ahora () y el nombre de host de su computadora (si tiene varios nodos haciendo lo mismo).
Algo así como:
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>
Otros consejos
También puede usar TMP = lib: nonl (os: cmd (" mktemp ")).
O podrías hacer
erlang:phash2(make_ref())
para un identificador único rápido y fácil. Único para hasta 2 ^ 82 llamadas, lo que debería ser suficiente para sus propósitos. Esto me resulta más fácil que formatear una marca de tiempo con el nombre del nodo para su uso.
Respuesta tardía: acabo de notar el módulo test_server que tiene soporte de directorio temporal, vale la pena echarle un vistazo
Finalmente tuve este problema, y ??mi usuario está usando una combinación de sistemas Windows y Linux, por lo que el viejo y probado lib: nonl (os: cmd (" mktemp "))
el método ya no lo va a cortar más.
Entonces, así es como lo he abordado, tanto con una función mktemp / 1
que devuelve un nombre de archivo que se puede usar como también una función mktemp_dir / 1
que devuelve un directorio (después de haberlo creado).
-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.
Y la versión del directorio:
-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.
Ambos hacen básicamente lo mismo: obtenemos un nombre fuertemente aleatorio como binario, lo convertimos en una cadena base36 y lo agregamos a lo que el sistema operativo nos devuelve como una ubicación de caché temporal local segura para el usuario.
En un sistema de tipo unix, por supuesto, podríamos usar filename: join ([" / tmp " ;, Prefix, Rand])
pero la falta de disponibilidad de / tmp
en Windows es una especie de punto completo aquí.