我知道PHP
中提供了相当多的内置函数来获取文件的大小,其中一些是:filesize,stat,ftell等等。
我的问题在于ftell
,这非常有趣,它会从文件中返回文件指针的整数值。
是否可以使用ftell
函数获取文件的大小?如果是,那么告诉我怎么做?
情景:
ftell
来计算文件的大小。答案 0 :(得分:12)
fstat
确定没有任何杂技的文件大小:
$f = fopen('file', 'r+');
$stat = fstat($f);
$size = $stat['size'];
使用append(ftell
)标志打开文件时,无法使用 "a"
。此外,您必须首先使用fseek($f, 0, SEEK_END)
搜索文件的末尾。
答案 1 :(得分:2)
ftell()
可以告诉您文件中假定的字节数,但实际 的数量是多少。 Sparse files在磁盘上占用的空间少于寻求结束并告知将返回的值。
答案 2 :(得分:0)
感谢@Phihag,将您的信息与fseek
以及ftell
联系起来,我能够以更好的方式计算尺寸。请参阅此处的代码:http://pastebin.com/7XCqu0WR
<?php
$fp = fopen("/tmp/temp.rock", "a+");
fwrite($fp, "This is the contents");
echo "Time taken to calculate the size by filesize function: ";
$t = microtime(true);
$ts1 = filesize("/tmp/temp.rock") . "\n";
echo microtime(true) - $t . "\n";
echo "Time taken to calculate the size by fstat function:";
$t = microtime(true);
$ts1 = fstat($fp) . "\n";
$size = $ts1["size"];
echo microtime(true) - $t . "\n";
echo "Time taken to calculate the size by fseek and ftell function: ";
$t = microtime(true);
fseek($fp, 0, SEEK_END);
$ts2 = ftell($fp) . "\n";
echo microtime(true) - $t . "\n";
fclose($fp);
/**
OUTPUT:
Time taken to calculate the size by filesize function:2.4080276489258E-5
Time taken to calculate the size by fstat function:2.9802322387695E-5
Time taken to calculate the size by fseek and ftell function:1.2874603271484E-5
*/
?>
答案 3 :(得分:0)
我写了一个基准来改进这个主题,并且为了避免人们争论某种php / cache,我在另一个过程中创建了唯一文件。
这是我毫无疑问要做的新基准。
测试忽略打开和关闭时间,因为用户要求以最快的方式计算已打开文件的大小。 每个测试运行200个文件。
在单独的过程中创建文件的代码是本文的第一条评论。
<?php
class timeIt
{
static private $times = [];
static function new()
{
self::$times[] = hrtime(true);
}
static function stop()
{
self::$times[] = -1;
}
static function dif()
{
$dif = 0;
$sum = 0;
$i = count(self::$times) - 1;
if (self::$times[$i] === -1)
unset(self::$times[$i--]);
for ($i = count(self::$times) - 1; $i > 0; --$i) {
if (self::$times[$i - 1] === -1) {
$sum += $dif;
$dif = 0;
--$i;
continue;
}
$dif += self::$times[$i] - self::$times[$i - 1];
}
return $sum + $dif;
}
static function printNReset()
{
echo "diffTime:" . self::dif() . "\n\n";
self::reset();
}
static function reset()
{
self::$times = [];
}
}
function fseek_size_from_current($handle)
{
$current = ftell($handle);
fseek($handle, 0, SEEK_END);
$size = ftell($handle);
fseek($handle, $current);
return $size;
}
function fseek_size_from_start($handle)
{
fseek($handle, 0, SEEK_END);
$size = ftell($handle);
fseek($handle, 0);
return $size;
}
function uniqueProcessId()
{
return (string) hrtime(true);
}
function getUniqueForeignProcessFiles($quantity, $size)
{
$returnedFilenames = $filenames = [];
while ($quantity--){
$filename = uniqueProcessId();
$filenames[$filename] = $size;
$returnedFilenames[] = __DIR__ . DIRECTORY_SEPARATOR . $filename;
}
$data = base64_encode(json_encode($filenames));
$foreignCgi = __DIR__ . DIRECTORY_SEPARATOR . "createFileByNames.php";
$command = "php $foreignCgi $data";
if (shell_exec($command) !== 'ok')
die("An error ocurred");
return $returnedFilenames;
}
const FILESIZE = 20 * 1024 * 1024;
foreach(getUniqueForeignProcessFiles(200, FILESIZE) as $filename){
$handle = fopen($filename, 'r');
timeIt::new();
$size = fstat($handle)['size'];
timeIt::new();
timeIt::stop();
fclose($handle);
unlink($filename);
}
echo "**fstat**\n";
timeIt::printNReset();
foreach(getUniqueForeignProcessFiles(200, FILESIZE) as $filename){
$handle = fopen($filename, 'r');
timeIt::new();
$size = fseek_size_from_start($handle);
timeIt::new();
timeIt::stop();
fclose($handle);
unlink($filename);
}
echo "**fseek with static/defined**\n";
timeIt::printNReset();
foreach(getUniqueForeignProcessFiles(200, FILESIZE) as $filename){
$handle = fopen($filename, 'r');
timeIt::new();
$size = fseek_size_from_current($handle);
timeIt::new();
timeIt::stop();
fclose($handle);
unlink($filename);
}
echo "**fseek with current offset**\n";
timeIt::printNReset();
foreach(getUniqueForeignProcessFiles(200, FILESIZE) as $filename){
$handle = fopen($filename, 'r');
timeIt::new();
$size = filesize($filename);
timeIt::new();
timeIt::stop();
fclose($handle);
unlink($filename);
}
echo "**filesize after fopen**\n";
timeIt::printNReset();
foreach(getUniqueForeignProcessFiles(200, FILESIZE) as $filename){
timeIt::new();
$size = filesize($filename);
timeIt::new();
timeIt::stop();
unlink($filename);
}
echo "**filesize no fopen**\n";
timeIt::printNReset();
包含20MB文件的结果,时间以纳秒为单位
fstat diffTime:2745700
具有静态/已定义的功能 diffTime:1267400
使用当前偏移量进行搜索 diffTime:983500
打开后的文件大小 diffTime:283052500
文件大小没有打开 diffTime:4259203800
文件大小为1MB,时间以纳秒为单位:
fstat diffTime:1490400
使用静态/已定义的功能 diffTime:706800
使用当前偏移量进行搜索 diffTime:837900
打开后的文件大小 diffTime:22763300
文件大小没有打开 diffTime:216512800
以前,此答案还有另一个基准,我删除了算法,以使此答案更清晰。 该算法使用了由自己的进程创建的文件,并且假设是:
ftell + fseek 是 fstat ['size'] 的时间,一半,即使在另一个函数中,并且两次调用这两个函数。 fstat是 速度较慢,因为它不仅包含文件大小,还包含更多信息, 因此,如果您需要代码旁边的其他信息,请检查 更改,只需坚持使用fstat。
当前基准表明该假设有效,即: **对于1-20 MB的文件,fseek + ftell ++比 fstat 快2-2.8倍。
随时运行您的基准测试并分享您的结果。