使用随机数使文件名唯一是安全的

本文关键字:安全 文件名 随机数 唯一 | 更新日期: 2023-09-27 17:57:09

我正在编写一个程序,它基本上处理数据并输出许多文件。它不可能每次使用都产生超过10-20个文件。我只是想知道使用这种方法生成唯一的文件名是否是个好主意?有没有可能rand会选择,比方说x,然后在10个实例中,再次选择x。使用random();是个好主意吗?如有任何意见,我们将不胜感激!

Random rand = new Random ();
int randNo = rand.Next(100000,999999)l
using (var write = new StreamWriter("C:''test" + randNo + ".txt") 
{
// Stuff
}

使用随机数使文件名唯一是安全的

我只是想知道使用这种方法生成唯一的文件名是否是个好主意?

没有。唯一性不是随机性的特性。随机意味着结果值在任何方面都不依赖于以前的状态。这意味着重复是可能的。您可以连续多次获得相同的数字(尽管这不太可能(。

如果您想要唯一的值,请使用GUID:

Guid.NewGuid();

正如下面的评论中所指出的,这个解决方案并不完美。但我认为,这已经足够解决眼前的问题了。其思想是Random被设计为随机的,而Guid被设计为唯一的。从数学上讲,"随机"answers"唯一"是需要解决的非平凡问题。

这两个的实现都不是100%完美的。但关键是要简单地将两者中正确的一个用于预期的功能。

或者,用一个比喻。。。如果你想把钉子钉在一块木头上,是否可以100%保证锤子能成功地做到这一点?不存在。锤子在接触钉子时破碎的可能性为零。但我还是会伸手去拿锤子,而不是陪审团用螺丝刀装东西。

不,这不是在中创建临时文件名的正确方法。网

正确的方法是使用任一路径。GetTempFileName(立即创建文件(或Path。GetRandomFileName(创建高质量的随机名称(。

请注意,RandomGuid.NewGuid()DateTime.Now生成少量文件名并没有太大错误,如其他答案所述,但使用预期用于特定目的的函数会使代码更容易阅读/证明正确性。

如果您想生成一个唯一的值,有一个专门为生成不合格的标识值而设计的工具,即全局唯一标识符(GUID(。

var guid = Guid.NewGuid();

把找出创造这种独特价值的最佳方式的问题留给其他人。

有一个所谓的生日悖论。。。如果你生成一些随机数(任何大于1的数(,遇到"碰撞"的可能性就会增加。。。若您生成sqrt(可能值的数量(值,碰撞的可能性大约为50%。。。所以你有799998个可能的值。。。sqrt(799998(是894…它相当低。。。对你的程序调用45-90次,你有50%的机会发生冲突。

请注意,随机是随机的,如果生成两个随机数,则碰撞的可能性为非零,如果生成numberofpossiblevalues + 1随机数,碰撞的可能性是1。

现在。。。有人会告诉您,Guid.NewGuid将生成始终唯一的值。他们出售非常好的蛇油。正如MSDN中所写,在Guid.NewGuid页面中。。。

新Guid的值将全部为零或等于任何其他Guid的可能性非常低。

机会不是0,它非常(非常(低!在这里,生日悖论激活了。。。现在Microsoft Guid有122位"随机"部分和6位"固定"部分,50%的碰撞几率发生在2.3x10^18左右。这是一个很大的数字!1%的碰撞几率是在3.27x10^17之后……仍然是一个很大的数字!

请注意,Microsoft使用强随机数生成器生成这122位:https://msdn.microsoft.com/en-us/library/bb417a2c-7a58-404f-84dd-6b494ecf0d13#id9

Windows使用加密API(CAPI(和加密API下一代(CNG(中的加密PRNG生成版本4 GUID。

因此,虽然Guid.NewGuid生成的整个Guid不是完全随机的(因为6位是固定的(,但它仍然是完全随机的。

我认为添加日期和;在文件名中创建文件的时间,以确保文件不重复。如果你想让它更加独特,你也可以添加随机数字(在这种情况下,你的10个文件同时保存(。

因此,文件名可能是file06182015112300.txt(显示月、日、年、小时、分钟和秒(

如果你想使用这种格式的文件,并且你知道你不会用完未使用的数字,那么检查你生成的随机数是否已经使用更安全,如下所示:

Random rand = new Random();
string filename = "";
do
{
    int randNo = rand.Next(100000, 999999);
    filename = "C:''test" + randNo + ".txt";
} while (File.Exists(filename));
using (var write = new StreamWriter(filename))
{
//Stuff
}