stormist
stormist

Reputation: 5905

PHP script to generate a file with random data of given name and size?

Does anyone know of one? I need to test some upload/download scripts and need some really large files generated. I was going to integrate the test utility with my debug script.

Upvotes: 11

Views: 8379

Answers (9)

Aranxo
Aranxo

Reputation: 1183

I took the answer of mgutt and shortened it a bit. Also, his answer has a little bug which I wanted to avoid.

function createRandomFile(string $filename, int $filesize): void
{
    $h = fopen($filename, 'w');
    if (!$h) return;

    for ($i = 0; $i < intdiv($filesize, 1024); $i++) {
        fwrite($h, bin2hex(random_bytes(511)).PHP_EOL);
    }

    fwrite($h, substr(bin2hex(random_bytes(512)), 0, $filesize % 1024));

    fclose($h);
    chmod($filename, 0644);
}

Note: This works only with PHP >= 7. If you really want to run it on lower versions, use openssl_random_pseudo_bytes instead of random_bytes and floor($filesize / 1024) instead of intdiv($filesize, 1024).

Upvotes: 0

kta
kta

Reputation: 20110

I would suggest using a library like Faker to generate test data.

Upvotes: 0

shyammakwana.me
shyammakwana.me

Reputation: 5752

generate_file() from @Marco Demaio caused this below when generating 4GB file.

Warning: str_repeat(): Result is too big, maximum 2147483647 allowed in /home/xxx/test_suite/handler.php on line 38

I found below function from php.net and it's working like charm. I have tested it upto

17.6 TB (see update below)

in less than 3 seconds.

function CreatFileDummy($file_name,$size = 90294967296 ) {   
// 32bits 4 294 967 296 bytes MAX Size
    $f = fopen('dummy/'.$file_name, 'wb');
    if($size >= 1000000000)  {
        $z = ($size / 1000000000);       
        if (is_float($z))  {
            $z = round($z,0);
            fseek($f, ( $size - ($z * 1000000000) -1 ), SEEK_END);
            fwrite($f, "\0");
        }       
        while(--$z > -1) {
            fseek($f, 999999999, SEEK_END);
            fwrite($f, "\0");
        }
    }
    else {
        fseek($f, $size - 1, SEEK_END);
        fwrite($f, "\0");
    }
    fclose($f);

return true;
}

Update:

I was trying to hit 120TB, 1200 TB and more but filesize was limited to 17.6 TB. After some googling I found that it is max_volume_size for ReiserFS file system which was on my server. May be PHP can handle 1200TB also in just few seconds. :)

Upvotes: 2

mgutt
mgutt

Reputation: 6177

generate_file() from "Marco Demaio" is not memory friendly so I created file_rand().

function file_rand($filename, $filesize) {
    if ($h = fopen($filename, 'w')) {
        if ($filesize > 1024) {
            for ($i = 0; $i < floor($filesize / 1024); $i++) {
                fwrite($h, bin2hex(openssl_random_pseudo_bytes(511)) . PHP_EOL);
            }
            $filesize = $filesize - (1024 * $i);
        }
        $mod = $filesize % 2;
        fwrite($h, bin2hex(openssl_random_pseudo_bytes(($filesize - $mod) / 2)));
        if ($mod) {
            fwrite($h, substr(uniqid(), 0, 1));
        }
        fclose($h);
        umask(0000);
        chmod($filename, 0644);
    }
}

As you can see linebreaks are added every 1024 bytes to avoid problems with functions that are limited to 1024-9999 bytes. e.g. fgets() with <= PHP 4.3. And it makes it easier to open the file with an text editor having the same issue with super long lines.

Upvotes: 7

soulmerge
soulmerge

Reputation: 75704

If you want really random data you might want to try this:

$data = '';
for ($byteSize-- >= 0) {
    $data .= chr(rand(0,255));
}

Might take a while, though, if you want large file sizes (as with any random data).

Upvotes: 1

jemfinch
jemfinch

Reputation: 2889

Does the file really need to be random? If so, just read from /dev/urandom on a Linux system:

dd if=/dev/urandom of=yourfile bs=4096 count=1024 # for a 4MB file.

If it doesn't really need to be random, just find some files you have lying around that are the appropriate size, or (alternatively) use tar and make some tarballs of various sizes.

There's no reason this needs to be done in a PHP script: ordinary shell tools are perfectly sufficient to generate the files you need.

Upvotes: 1

Marco Demaio
Marco Demaio

Reputation: 34407

To start you could try something like this:

function generate_file($file_name, $size_in_bytes)
{
   $data = str_repeat(rand(0,9), $size_in_bytes);
   file_put_contents($file_name, $data); //writes $data in a file   
}

This creates file filled up with a random digit (0-9).

Upvotes: 8

zaf
zaf

Reputation: 23244

Why not have a script that streams out random data? The script can take parameters for file size, type etc.

This way you can simulate many scenarios, for example bandwidth throttling, premature file end etc. etc.

Upvotes: 1

Mathew
Mathew

Reputation: 8279

Do you really need so much variation in filesize that you need a PHP script? I'd just create test files of varying sizes via the command line and use them in my unit tests. Unless the filesize itself is likely to cause a bug, it would seem you're over-engineering here...

To create a file in Windows;

fsutil file createnew d:\filepath\filename.txt 1048576

in Linux;

dd if=/dev/zero of=filepath/filename.txt bs=10000000 count=1

if is the file source (in this case nothing), of is the output file, bs is the final filesize, count defines how many blocks you want to copy.

Upvotes: 5

Related Questions