本文转自:http://blog.ciznx.com/post/csharprandomnumberandrandomfilename.aspx

在项目中会遇到需要批量生成文件的时候,比如 asp.net 中生成静态文件、在 Winform 项目中命名临时文件等,这时我们考虑使用随机名称,也就不可避免地需要使用到 .Net 提供的 System.Random 类。对实际上,计算机不 可能产生完全随机的数字,所谓的随机数发生器都是通过一定的算法对事先选定的随机种子做复杂的运算,用产生的结果来近似的模拟完全随机数,这种随机数被称 作伪随机数。Random 类自身在 Intellisense 中也表述为“伪随机数”。伪随机数是以相同的概率从一组有限的数字中选取的。所选数字并不具有完全的随机性,但是从实用的角度而言,其随机程度已足够了。

伪随机数的选择是从随机种子开始的,所以为了保证每次得到的伪随机数都足够地“随机”,随机种子的选择就显得非常重要。如果随机种子一样,那么同一个随机数发生器产生 的随机数也会一样。一般地,我们使用同系统时间有关的参数作为随机种子,如果不给 Random 的构造函数传递参数,那 Random 会以当前系统时间由特定算法算得一个种子,这是.net Framework中的随机数发生器默认采用的方法。 也就是说,如果时间相同(纵使时间永远不会相同,但在CPU高速运行的状态下,系统获取到的时间是有可能相同的。),即使使用不同的 Random 实例,由于初始化它们的种子(系统时间)是相同的,所以Random 对象的这些实例产生的随机数仍然是相同的。这一点在实验中得到证实,实验代码如下:

using System;  

    class Program
{
static void Main(string[] args)
{
for (int i = ; i < ; i++)
{
Console.WriteLine(RandomNumber());
}
Console.WriteLine("Press any key to continue...");
Console.ReadLine();
} static int RandomNumber()
{
Random rand = new Random();
return rand.Next();
} }
在控制台输出的结果中,我们可以看到,接连输出的结果会相同,然后再变化,然后继续相同,再变化……即不规律地间歇性地变化。这个问题在 asp.net 程序中尤其明显,因为 asp.net 程序天然是多线程的,经常会遇到高并发,所以如果一个生成文件的操作由很高的并发一起执行,就可能由于生成的文件名相同而造成 IO 错误,或者相互覆盖。所以生成不重复的随机数(即“随机”的随机数)一直是一个受关注的技术话题。
其实 .Net  本身也已经提供了一些类来提供这样的支持,比如 System.Security.Cryptography.RNGCryptoServiceProvider 及 CryptGenRandom() 等

对于随机数的重复部分,有几种方法可以方便地解决。比如上述代码,可以简单地将 rand 对象的声明放在类里,作为类的静态字段来对待,然后在 RandomNumber 方法里调用它,也就是把上述代码中的 RandomNumber 代码改为:

static Random rand = new Random();
static int RandomNumber()
{
return rand.Next();
}

这样就可以解决问题了,这样一样,每次输出的随机数都会不相同:因为 rand 对象只用种子初始化了一次。

在平常的开发中,很多人习惯于将一些零散的方法都集中起来放在一个静态类中(如 Utils),我们希望诸如此类的方法在一个方法中就搞定,而上述方法中将字段 rand 的声明放到了方法的外面,这样破坏了代码的整洁性,在代码重用的时候也容易遗漏,所以还是要考虑把实现这功能的代码放在同一个方法中,这还是要面对这个问题:“如果在相同的时间获得不同的随机种子”。我们知道 Guid 类型的实例是全局不重复的值类型对象,因此使用它可以方便的作为独立的种子,即每次调用方法都使用一个从 Guid 的二进制值转换得到的数字作为种子。示例代码如下:

如果觉得这个办法的效率可能是个问题的话,也可以受此启发,而使用其他类型的实例的 GetHashCode() 的返回值作为种子。
此外,在 System.Security.Cryptography 命名空间中提供了 RNGCryptoServiceProvider类用于提供随机支持,可以用它来作为随机器的初始化种子可以用于生成随机的随机数(具体的例子,请参照 MSDN 的示例代码)

对于上述几种方法,读者您可以自行试验其效率并做对比。

好了,第一个问题解决了,那文件名呢?其实解决了第一个问题,那问题也就解决了一大半了,因为只要在同一时间产生不同的随机数,那即使是多线程也不怕了;不过还有一个问题,文件系统不允许同名的文件,因此除了要保证本次生成的文件名要不相同,还要保证与之前已经存在的文件名不相同。这也不是什么难题,使用 System.IO.File.Exist() 方法即可验证是否已存在相同的文件名,使用一个 while 循环来一直获取随机文件名,直到不与已经存在的文件名相同为止。

C#产生不重复的随机数并生成随机文件名的更多相关文章

  1. js生成1-100不重复的随机数及生成10个1-100不重复的随机数

    //生成1-100不重复的随机数 var count=100; var a=new Array(); for(var i=0;i<100;i++){ a[i]=i+1; } a.sort(fun ...

  2. 生成随机文件名JS

    export default function (length) { const data = ["0", "1", "2", " ...

  3. C#生成随机验证码

    使用YZMHelper帮助类即可 using System; using System.Web; using System.Drawing; using System.Security.Cryptog ...

  4. [转载][记录]javascript生成不重复的随机数

    参考链接:javascript生成不重复的随机数 项目播放视频,是无序的,有上下两个按钮,所以需要生成1,8不重复的随机数数组,如: ,,,,,,, 然后再split一次,就是数组了. 拿来主义了

  5. 生成N个不重复的随机数(转)

    有25幅作品拿去投票,一次投票需要选16幅,单个作品一次投票只能选择一次.前面有个程序员捅了漏子,忘了把投票入库,有200个用户产生的投票序列为空.那么你会如何填补这个漏子? 当然向上级反映情况.但是 ...

  6. C#生成无重复的随机数

    大一学期末的时候做课程设计时遇到过生成无重复随机数的问题,今天自己也写出来了: static int[] Create_Value() { Random ran = new Random(); //生 ...

  7. java,url长链接生成短链接,短链接生成器,自定义字符串,对字符串md5混合KEY加密,根据短链接获得key值,不重复的随机数,不重复的随机字符串

    java,url长链接生成短链接,短链接生成器,自定义字符串,对字符串md5混合KEY加密,根据短链接获得key值,不重复的随机数,不重复的随机字符串 package com.zdz.test; im ...

  8. Jmeter生成8位不重复的随机数

    jmeter的time函数${__time(,)}  :  默认该公式精确到毫秒级别, 13位数 ${__time(/1000,)}  : 该公式精确到秒级别, 10位数 ${__time(yyyy- ...

  9. 生成count个[0-n)不重复的随机数

    代码来自:https://www.cnblogs.com/ningvsban/p/3590722.html,感觉实现的方式不错(做了一点小小修改) public static ArrayList ge ...

随机推荐

  1. Swift function how to return nil

    这两天在学习Stanford出品的iOS7的课程,这个课程去年也看过,但是看到第3课就不行了,满篇的OC,把人都搞晕了.这段时间因为要写个iOS的App,正好赶上了Swift问世,所以趁着这股劲继续学 ...

  2. maven学习手记 - 1

    学习目标 windows下安装maven环境: 使用命令创建maven项目结构: maven项目编译测试打包安装运行: 在maven项目中使用插件.   在windows下安装maven环境 在win ...

  3. C# 生成XML 多级节点

    直接上代码: 在应用程序中 class Program { //public static JsonServiceClient Service = new JsonServiceClient(Conf ...

  4. 初探Xamarin

    Xamarin是一个基于mono的商业项目,收费,而且贼贵.官网地址是:http://xamarin.com/ 就我个人理解,收费的Xamarin提供一个for visual studio 2010/ ...

  5. 第三次作业,github的基本操作

    chengjiangtao@pc MINGW32 ~$ git config --global user.name "chengjiangtao" chengjiangtao@pc ...

  6. OS X 使用技巧——访问所有的键盘功能

    苹果笔记本电脑和苹果的无线键盘只有一个Delete键,可以删除光标前面的字. 按住Fn键再按Delete键就能删除光标后面的字符. 按住Fn键会把上下方向键的效果变成Page Up / Page Do ...

  7. WinForm-利用Anchor和Dock属性缩放控件

    转自:http://www.cnblogs.com/tianzhiliang/articles/2144692.html 有一点让许多刚接触WinForms编程的开发者感到很棘手,就是在用户调整各种控 ...

  8. WinForm Control - DataGridView

    http://blog.csdn.net/fangxing80/article/details/1561011 .NET 2.0 - WinForm Control - DataGridView 编程 ...

  9. JNA使用

    JNA与C对应的数据类型: 注意:        使用byte[]对应C++中的char* 可以返回函数执行的结果值 一.添加JNA需要的jar包      1.jna.jar      2.plat ...

  10. 剑指offer--21题

    #include "stdafx.h" #include<iostream>using namespace std; void LeftRotateString(cha ...