我正在尝试使用 Erlang 生成一个随机的字母数字ID。
我曾尝试过使用crypto:strong_rand_bytes(Bytes)
来生成一个随机的二进制数据,并尝试将其像 <<"my_unique_random_id">>
一样使用。但是因为随机位不一定是有效的 UTF-8 字符串,所以这种方法行不通,对吗?
我在 Erlang 文档和其他地方寻找其他选项,但没有找到任何有用的信息。请问是否有人可以帮我找到解决方案呢?
这可能取决于您所需的随机性。Erlang的crypto
模块生成的随机数据比random
模块更强(也可以参见[erlang-questions] Yaws security alert - Yaws 1.93和此问题)。如果您想使用strong_rand_bytes
生成ID,则获取其base64可能已足够:
> base64:encode(crypto:strong_rand_bytes(Bytes)).
如果需要的话,您可以将此转换为列表。
get_random_string(Length, AllowedChars) ->
lists:foldl(fun(_, Acc) ->
[lists:nth(random:uniform(length(AllowedChars)),
AllowedChars)]
++ Acc
end, [], lists:seq(1, Length)).
这篇博客文章详细解释了代码的每一行。查看评论获取一些优化技巧。
我准备了一个小模块来完成这个任务
它还使用 crypto:rand_uniform/2
而不是过时的 random:uniform
module(cloud_rnd).
-export([rnd_chars/1, rnd_numbers/1, rnd_chars_numbers/1]).
rnd_chars(L) -> get_rnd(L, chars).
rnd_numbers(L) -> get_rnd(L, numbers).
rnd_chars_numbers(L) -> get_rnd(L, chars_numbers).
get_rnd(L, chars) -> gen_rnd(L, "abcdefghijklmnopqrstuvwxyz");
get_rnd(L, numbers) -> gen_rnd(L, "1234567890");
get_rnd(L, chars_numbers) -> gen_rnd(L, "abcdefghijklmnopqrstuvwxyz1234567890").
gen_rnd(Length, AllowedChars) ->
MaxLength = length(AllowedChars),
lists:foldl(
fun(_, Acc) -> [lists:nth(crypto:rand_uniform(1, MaxLength), AllowedChars)] ++ Acc end,
[], lists:seq(1, Length)
).
Bits = entropy_string:bits(5.0e6, 1.0e12).
83.37013046707142
entropy_string:random_string(Bits).
<<"QDrjGQFGgGjJ4t9r2">>
还有其他预定义的字符集,您也可以指定自己的字符(但出于效率原因,仅支持具有2的幂字符的集合)。最重要的是,在指定的字符串数量中重复的风险是明确的。不再猜测字符串长度。
randchar(N) ->
randchar(N, []).
randchar(0, Acc) ->
Acc;
randchar(N, Acc) ->
randchar(N - 1, [random:uniform(26) + 96 | Acc]).
您可以在此处使用函数uef_bin:random_latin_binary/2
:
https://github.com/DOBRO/uef-lib#uef_binrandom_latin_binary2
Bin = uef_bin:random_latin_binary(Length, any)
接着,如果你需要一个string()
类型:
String = erlang:binary_to_list(Bin)
+
和=
。 - Stratus3Dre:replace(base64:encode(crypto:strong_rand_bytes(Bytes)),"\\W","",[global,{return,binary}]).
- Berzemus