Java中的Random.nextBytes(byte [])行为

时间:2018-07-02 09:05:14

标签: java random

问题是,为什么在单独的方法调用中获取相同数量的字节的行为会返回不同的字节,这取决于在单个方法调用中调用5000个字节还是在长度为1的字节数组中进行5000个方法调用。

以下面的示例为例:在终端上打印21而不是5000,(5000除以256得出〜19,这很可能使21个匹配是简单的巧合)。

Random rand = new Random(0);
byte tmp1[] = new byte[5000];
rand.nextBytes(tmp1);
rand = new Random(0);
byte tmp2[] = new byte[5000];
byte tmp3[] = new byte[1];
for(int i = 0; i < 5000;i++)
{
    rand.nextBytes(tmp3);
    tmp2[i] =tmp3[0];
}
int matches = 0;
for(int i = 0; i < 5000;i++)
{
    if(tmp1[i] == tmp2[i])
    {
        matches++;
    }
}
System.out.println(matches);

更重要的是,无论是否调用一次长度为5000的数组还是两次为长度2500的数组,都可以通过任何方法对其进行破解以生成相同的字节。

编辑:下面的帖子完美地解决了问题,一次接收4个字节完全可以解决问题。 测试代码如下,返回4000:

                Random rand1 = new Random(0);
                byte tmp11[] = new byte[4000];
                rand1.nextBytes(tmp11);
                rand1 = new Random(0);
                byte tmp22[] = new byte[4000];
                byte tmp33[] = new byte[4];
                for(int i = 0; i < 1000;i++)
                {
                    rand1.nextBytes(tmp33);
                    for(int a = 0; a < 4;a++)
                    {
                        tmp22[(i*4)+a] = tmp33[a];
                    }
                }
                int matches1 = 0;
                for(int i = 0; i < 4000;i++)
                {
                    if(tmp11[i] == tmp22[i])
                    {
                        matches1++;
                    }
                }
                System.out.println(matches1);

2 个答案:

答案 0 :(得分:3)

那是因为java使用nextInt()填充字节并将该int值的其他3个字节添加到数组中。基本上,从随机生成器收到的每个int都填充数组的4个字节。我将添加一个示例。

这首先是Javadoc:

  

nextBytes方法由Random类实现,就像通过以下方式实现一样:

 public void nextBytes(byte[] bytes) {    for (int i = 0; i <
 bytes.length; )
      for (int rnd = nextInt(), n = Math.min(bytes.length - i, 4);
           n-- > 0; rnd >>= 8)
       bytes[i++] = (byte)rnd; 
 }

因此,为了展示该示例,我们可以做:

      Random rand = new Random(0);
      rand.nextBytes(tmp1);
      System.out.println(tmp1[0]);
      System.out.println(tmp1[4]);
      rand = new Random(0);
      rand.nextBytes(tmp3);
      System.out.println(tmp3[0]);
      rand.nextBytes(tmp3);
      System.out.println(tmp3[0]);

打印: 96 56 96 56,因为int的大小为4。基本上,它得到一个int(即4个字节),并将其添加到字节数组中的位置0、1、2、3。当您用byte [1]调用它时,它将获得相同的int值,并将相同的字节添加到值0,但int的其他3个字节将丢失。这就是为什么您会变得不一致。您得到的数字21只是巧合。

答案 1 :(得分:0)

由于Java的Random是伪随机数生成器,因此每次调用调用任何next方法时,它的内部“状态”都会前进,即,可能会返回一个可能与前一个不同的伪随机数。结合对nextBytes的描述,该描述指出它为目标字节数组中的每4个字节构造了一次调用nextInt的目标字节数组,从而导致代码的结果不同。