php-tail 추가
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace PhpExtended\Tail;
|
||||
|
||||
/**
|
||||
* FileNotFoundException class file.
|
||||
*
|
||||
* This exception represents a target error when the file was designed because
|
||||
* the path it represents is not pointing on a file. This exception is also
|
||||
* thrown if the given path is pointing on a directory or a symlink, or
|
||||
* anything else that is not a file.
|
||||
*
|
||||
* @author Anastaszor
|
||||
*/
|
||||
class FileNotFoundException extends TailException
|
||||
{
|
||||
/**
|
||||
* Builds a new FileNotFoundException object.
|
||||
*
|
||||
* @param string $filename the name of targeted file
|
||||
* @param int $nblines the number of lines that were demanded
|
||||
* @param int $hint an estimation of the line length in that file
|
||||
*/
|
||||
public function __construct($filename, $nblines, $hint)
|
||||
{
|
||||
parent::__construct($filename, $nblines, $hint,
|
||||
strtr('The file "{file}" does not exists.', array('{file}' => $filename)),
|
||||
404
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace PhpExtended\Tail;
|
||||
|
||||
/**
|
||||
* FileTooBigExcepion class file.
|
||||
*
|
||||
* This exception represents a try to read on a file that is larger than the
|
||||
* int max capacity on the system. This exception may occur if the file length
|
||||
* exceeds the INT32 capacity on windows 32 bits systems. It should not occur
|
||||
* on 64 bits php (except if the size is larger than 2^63 bytes)
|
||||
*
|
||||
* @author Anastaszor
|
||||
*/
|
||||
class FileTooBigException extends TailException
|
||||
{
|
||||
/**
|
||||
* Builds a new FileTooBigException object.
|
||||
*
|
||||
* @param string $filename the name of targeted file
|
||||
* @param int $nblines the number of lines that were demanded
|
||||
* @param int $hint an estimation of the line length in that file
|
||||
*/
|
||||
public function __construct($filename, $nblines, $hint)
|
||||
{
|
||||
parent::__construct($filename, $nblines, $hint,
|
||||
strtr('File {filename} is too big to be read.', array('{filename}' => $filename)),
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace PhpExtended\Tail;
|
||||
|
||||
/**
|
||||
* IOException class file.
|
||||
*
|
||||
* This exception represents a read error on targeted file that occured during
|
||||
* the reading process of tail.
|
||||
*
|
||||
* @author Anastaszor
|
||||
*/
|
||||
class IOException extends TailException
|
||||
{
|
||||
/**
|
||||
* Builds a new IOException object.
|
||||
*
|
||||
* @param string $filename the name of targeted file
|
||||
* @param int $nblines the number of lines that were demanded
|
||||
* @param int $hint an estimation of the line length in that file
|
||||
*/
|
||||
public function __construct($filename, $nblines, $hint)
|
||||
{
|
||||
parent::__construct($filename, $nblines, $hint,
|
||||
strtr('Error in reading file {filename}', array('{filename}' => $filename)),
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace PhpExtended\Tail;
|
||||
|
||||
/**
|
||||
* IllegalArgumentException class file.
|
||||
*
|
||||
* This exception is thrown when the number of lines that was asked is negative
|
||||
* or null.
|
||||
*
|
||||
* @author Anastaszor
|
||||
*/
|
||||
class IllegalArgumentException extends TailException
|
||||
{
|
||||
/**
|
||||
* Builds a new IllegalArgumentException object.
|
||||
*
|
||||
* @param string $filename the name of targeted file
|
||||
* @param int $nblines the number of lines that were demanded
|
||||
* @param int $hint an estimation of the line length in that file
|
||||
*/
|
||||
public function __construct($filename, $nblines, $hint)
|
||||
{
|
||||
parent::__construct($filename, $nblines, $hint,
|
||||
strtr('Error in reading file {filename}', array('{filename}' => $filename)),
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace PhpExtended\Tail;
|
||||
|
||||
/**
|
||||
* IllegalOsException class file.
|
||||
*
|
||||
* This exception is thrown when the cheating method to tail a file, i.e.
|
||||
* calling the tail unix function is choosen, but the running operating system
|
||||
* is not supporting that function.
|
||||
*
|
||||
* @author Anastaszor
|
||||
*/
|
||||
class IllegalOsException extends TailException
|
||||
{
|
||||
/**
|
||||
* Builds a new IllegalOsException object.
|
||||
*
|
||||
* @param string $filename the name of targeted file
|
||||
* @param int $nblines the number of lines that were demanded
|
||||
* @param int $hint an estimation of the line length in that file
|
||||
*/
|
||||
public function __construct($filename, $nblines, $hint)
|
||||
{
|
||||
parent::__construct($filename, $nblines, $hint,
|
||||
'You can\'t try to call unix\'s tail function on a non unix system.',
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace PhpExtended\Tail;
|
||||
|
||||
/**
|
||||
* OutputBufferException class file.
|
||||
*
|
||||
* This exception is thrown when the cheating method is called and something
|
||||
* went wrong with the output buffers. This usually means that the output
|
||||
* buffer stack is full, or the ob library is not loaded.
|
||||
*
|
||||
* @author Anastaszor
|
||||
*/
|
||||
class OutputBufferException extends TailException
|
||||
{
|
||||
/**
|
||||
* Builds a new OutputBufferException object.
|
||||
*
|
||||
* @param string $filename the name of targeted file
|
||||
* @param int $nblines the number of lines that were demanded
|
||||
* @param int $hint an estimation of the line length in that file
|
||||
*/
|
||||
public function __construct($filename, $nblines, $hint)
|
||||
{
|
||||
parent::__construct($filename, $nblines, $hint,
|
||||
"Error when using the output buffer.",
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
+512
@@ -0,0 +1,512 @@
|
||||
<?php
|
||||
|
||||
namespace PhpExtended\Tail;
|
||||
|
||||
use PhpExtended\System\OperatingSystem;
|
||||
|
||||
/**
|
||||
* Tail class file.
|
||||
*
|
||||
* This class provides methods that tails given file and return an array with
|
||||
* the wanted final lines of that file.
|
||||
* This class is the equivalent of a `tail -n X filepath` unix command.
|
||||
*
|
||||
* @author Anastaszor
|
||||
* @see http://stackoverflow.com/questions/15025875/what-is-the-best-way-in-php-to-read-last-lines-from-a-file/15025877
|
||||
*/
|
||||
class Tail
|
||||
{
|
||||
/**
|
||||
* If true, the given file should exists. This does not guarantee that
|
||||
* that file will remain existant for as long as the tailing process will
|
||||
* need it to be.
|
||||
*
|
||||
* @var boolean whether the given file exists.
|
||||
*/
|
||||
private $_file_exists = null;
|
||||
|
||||
/**
|
||||
* The path to the file. If it is a relative path, then all the process
|
||||
* for finding files with fopen() will be used, and this library does not
|
||||
* modify any of that configuration.
|
||||
*
|
||||
* @var string the path of targeted file.
|
||||
*/
|
||||
private $_file_path = null;
|
||||
|
||||
/**
|
||||
* Builds a new Tail object on targeted file path. If targeted file path
|
||||
* does not exists, the object will still be correcly constructed. Check
|
||||
* the <code>getFileExists()</code> method to be safe as tailing targeted
|
||||
* file.
|
||||
*
|
||||
* @param string $filepath the targeted file path, may be absolute or
|
||||
* relative, all rules for finding it with fopen will be unchanged.
|
||||
*/
|
||||
public function __construct($filepath)
|
||||
{
|
||||
$this->_file_path = $filepath;
|
||||
$this->_file_exists = is_file($this->_file_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file path that was given to this object.
|
||||
*
|
||||
* @return string the file path of the target.
|
||||
*/
|
||||
public function getFilePath()
|
||||
{
|
||||
return $this->_file_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether target file exists or not.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getFileExists()
|
||||
{
|
||||
return $this->_file_exists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this running system is from an unix family. This is called
|
||||
* only assuming that ALL linux based operating system have the tail -n
|
||||
* command available and in their $PATH, so it can direcly be called by
|
||||
* php's passthru() function.
|
||||
*
|
||||
* @return boolean true if `tail -n` is supported.
|
||||
*/
|
||||
protected function isUnixSystem()
|
||||
{
|
||||
return OperatingSystem::get()->isUnix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides the best way to tail the given file given the environment.
|
||||
*
|
||||
* @param int $nblines the number of lines wanted
|
||||
* @param int $hint a median number of bytes for each line in target file
|
||||
* @param boolean $silent if false, any error will throw an exception. If
|
||||
* true, any error will silently return an empty array.
|
||||
* @return string[] the wanted tailed lines
|
||||
*/
|
||||
public function smart($nblines, $hint = null, $silent = false)
|
||||
{
|
||||
if(!$this->_file_exists)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new FileNotFoundException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
$nblines = (int) $nblines;
|
||||
if($nblines <= 0)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IllegalArgumentException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
$filelength = @filesize($this->_file_path);
|
||||
if($filelength === false)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
if($filelength == 0)
|
||||
return array();
|
||||
if($filelength < 0)
|
||||
{
|
||||
if($this->isUnixSystem())
|
||||
return $this->cheat($nblines, $hint, $silent);
|
||||
|
||||
if($silent) return array();
|
||||
throw new FileTooBigException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
if($nblines <= 2)
|
||||
return $this->single($nblines, $hint, $silent);
|
||||
|
||||
if($filelength <= 10240) // 10kB
|
||||
return $this->naive($nblines, $hint, $silent);
|
||||
|
||||
return $this->dynamic($nblines, $hint, $silent);
|
||||
}
|
||||
|
||||
/**
|
||||
* The naive approach. This will load the whole file into php's buffer
|
||||
* and extract only the last wanted lines.
|
||||
*
|
||||
* @param int $nblines the number of lines wanted
|
||||
* @param int $hint a median number of bytes for each line in target file
|
||||
* @param boolean $silent if false, any error will throw an exception. If
|
||||
* true, any error will silently return an empty array.
|
||||
* @return string[] the wanted tailed lines
|
||||
*/
|
||||
public function naive($nblines, $hint = null, $silent = false)
|
||||
{
|
||||
if(!$this->_file_exists)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new FileNotFoundException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
$nblines = (int) $nblines;
|
||||
if($nblines <= 0)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IllegalArgumentException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
$filedata = file($this->_file_path);
|
||||
if($filedata === false)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
return array_slice($filedata, -$nblines);
|
||||
}
|
||||
|
||||
/**
|
||||
* The cheating approach. This will call the tail unix function and get
|
||||
* the return from it.
|
||||
*
|
||||
* @param int $nblines the number of lines wanted
|
||||
* @param int $hint a median number of bytes for each line in target file
|
||||
* @param boolean $silent if false, any error will throw an exception. If
|
||||
* true, any error will silently return an empty array.
|
||||
* @return string[] the wanted tailed lines
|
||||
*/
|
||||
public function cheat($nblines, $hint = null, $silent = false)
|
||||
{
|
||||
if(!$this->_file_exists)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new FileNotFoundException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
$nblines = (int) $nblines;
|
||||
if($nblines <= 0)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IllegalArgumentException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
if(!$this->isUnixSystem())
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IllegalOsException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
if(!function_exists('ob_start'))
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new OutputBufferException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
if(!ob_start())
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new OutputBufferException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
$returnvar = 0;
|
||||
passthru('tail -n '.$nblines.' '.escapeshellarg($this->_file_path), $returnvar);
|
||||
if($returnvar !== 0)
|
||||
{
|
||||
ob_end_clean();
|
||||
if($silent) return array();
|
||||
throw new TailShellException($this->_file_path, $nblines, $hint, $returnvar);
|
||||
}
|
||||
|
||||
$results = ob_get_clean();
|
||||
if($results === false)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new OutputBufferException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
return array_map('trim', explode("\n", $results));
|
||||
}
|
||||
|
||||
/**
|
||||
* The single byte buffer approach. This will read backward from the end
|
||||
* of the file each char until wanted lines are read.
|
||||
*
|
||||
* @param int $nblines the number of lines wanted
|
||||
* @param int $hint a median number of bytes for each line in target file
|
||||
* @param boolean $silent if false, any error will throw an exception. If
|
||||
* true, any error will silently return an empty array.
|
||||
* @return string[] the wanted tailed lines
|
||||
*/
|
||||
public function single($nblines, $hint = null, $silent = false)
|
||||
{
|
||||
if(!$this->_file_exists)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new FileNotFoundException($nblines, $hint);
|
||||
}
|
||||
|
||||
$nblines = (int) $nblines;
|
||||
if($nblines <= 0)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IllegalArgumentException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
$handle = fopen($this->_file_path, 'r');
|
||||
if($handle === false)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
$linecounter = $nblines;
|
||||
$pos = -2;
|
||||
$beginning = false;
|
||||
$text = array();
|
||||
while($linecounter > 0)
|
||||
{
|
||||
$t = " ";
|
||||
while($t != "\n")
|
||||
{
|
||||
$seek = fseek($handle, $pos, SEEK_END);
|
||||
if($seek === -1)
|
||||
{
|
||||
$beginning = true;
|
||||
break;
|
||||
}
|
||||
$t = fgetc($handle);
|
||||
if($t === false)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
$pos--;
|
||||
}
|
||||
$linecounter--;
|
||||
if($beginning)
|
||||
{
|
||||
$rewind = rewind($handle);
|
||||
if($rewind === false)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
}
|
||||
$data = fgetc($handle);
|
||||
if($data === false)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
$text[$nblines - $linecounter - 1] = $data;
|
||||
if($beginning) break;
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
|
||||
return array_reverse($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* The simple buffer approach. This will read backward from the end of the
|
||||
* file with a fixed size buffer until wanted lines are read.
|
||||
*
|
||||
* @param int $nblines the number of lines wanted
|
||||
* @param int $hint a median number of bytes for each line in target file
|
||||
* @param boolean $silent if false, any error will throw an exception. If
|
||||
* true, any error will silently return an empty array.
|
||||
* @return string[] the wanted tailed lines
|
||||
*/
|
||||
public function simple($nblines, $hint = null, $silent = false)
|
||||
{
|
||||
if(!$this->_file_exists)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new FileNotFoundException($nblines, $hint);
|
||||
}
|
||||
|
||||
$nblines = (int) $nblines;
|
||||
if($nblines <= 0)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IllegalArgumentException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
if($hint === null)
|
||||
{
|
||||
// just assuming that this is text file with 40 char per line as a
|
||||
// median basis. May be larger if it is a log file
|
||||
$hint = 40;
|
||||
if(strrpos($this->_file_path, '.log') === strlen($this->_file_path) - 4)
|
||||
{
|
||||
$hint = 240;
|
||||
}
|
||||
}
|
||||
|
||||
$buffer = 4096;
|
||||
|
||||
return $this->find($nblines, $buffer, $hint, $silent);
|
||||
}
|
||||
|
||||
/**
|
||||
* The dynamic buffer approach. This will read backward from the end of the
|
||||
* file with a fixed size buffer which is proportional to the size of the
|
||||
* wanted chunk of that file.
|
||||
*
|
||||
* @param int $nblines the number of lines wanted
|
||||
* @param int $hint a median number of bytes for each line in target file
|
||||
* @param boolean $silent if false, any error will throw an exception. If
|
||||
* true, any error will silently return an empty array.
|
||||
* @return string[] the wanted tailed lines
|
||||
*/
|
||||
public function dynamic($nblines, $hint = null, $silent = false)
|
||||
{
|
||||
if(!$this->_file_exists)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new FileNotFoundException($nblines, $hint);
|
||||
}
|
||||
|
||||
$nblines = (int) $nblines;
|
||||
if($nblines <= 0)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IllegalArgumentException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
if($hint === null)
|
||||
{
|
||||
// just assuming that this is text file with 40 char per line as a
|
||||
// median basis. May be larger if it is a log file
|
||||
$hint = 40;
|
||||
if(strrpos($this->_file_path, '.log') === strlen($this->_file_path) - 4)
|
||||
{
|
||||
$hint = 240;
|
||||
}
|
||||
}
|
||||
|
||||
$buffer = $hint * $nblines / 10;
|
||||
|
||||
return $this->find($nblines, $buffer, $hint, $silent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the wanted number of lines according to the given buffer
|
||||
* length.
|
||||
*
|
||||
* @param int $nblines the number of lines wanted
|
||||
* @param int $buffer the size of the buffer that will be used to seek
|
||||
* @param int $hint an estimation of the median line length on this file
|
||||
* @param boolean $silent if false, any error will throw an exception.
|
||||
* If true, any error will silently return an empty array.
|
||||
* @return string[] the wanted tailed lines
|
||||
* @throws IOException if any error occur
|
||||
*/
|
||||
protected function find($nblines, $buffer, $hint, $silent)
|
||||
{
|
||||
$lines = $nblines;
|
||||
$f = fopen($this->_file_path, 'r');
|
||||
if($f === false)
|
||||
{
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
$seek = fseek($f, -1, SEEK_END);
|
||||
if($seek === -1)
|
||||
{
|
||||
fclose($f);
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
$read = fread($f, 1);
|
||||
if($read === false)
|
||||
{
|
||||
fclose($f);
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
if($read === "\n") $lines -= 1;
|
||||
|
||||
// faster initialisation
|
||||
$seek = min(ftell($f), $hint * $nblines);
|
||||
$seeked = fseek($f, -$seek, SEEK_CUR);
|
||||
if($seeked === -1)
|
||||
{
|
||||
fclose($f);
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
$chunk = fread($f, $seek);
|
||||
if($chunk === false)
|
||||
{
|
||||
fclose($f);
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
$output = $chunk;
|
||||
$seeked = fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);
|
||||
if($seeked === -1)
|
||||
{
|
||||
fclose($f);
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
$lines -= substr_count($chunk, "\n");
|
||||
|
||||
// while we want more
|
||||
while(ftell($f) > 0 && $lines >= 0)
|
||||
{
|
||||
// figure out how far back we should jump
|
||||
$seek = min(ftell($f), $buffer);
|
||||
|
||||
// do the jump backwards relative to where we are
|
||||
$seeked = fseek($f, -$seek, SEEK_CUR);
|
||||
if($seeked === -1)
|
||||
{
|
||||
fclose($f);
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
// read a chunk and prepend it to out output
|
||||
$chunk = fread($f, $seek);
|
||||
if($chunk === false)
|
||||
{
|
||||
fclose($f);
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
$output = $chunk . $output;
|
||||
|
||||
// jump back to where we started reading
|
||||
$seeked = fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);
|
||||
if($seeked === -1)
|
||||
{
|
||||
fclose($f);
|
||||
if($silent) return array();
|
||||
throw new IOException($this->_file_path, $nblines, $hint);
|
||||
}
|
||||
|
||||
// decrease out line counter
|
||||
$lines -= substr_count($chunk, "\n");
|
||||
}
|
||||
|
||||
fclose($f);
|
||||
|
||||
// while we have too many lines
|
||||
// because the buffer size we might have read too many
|
||||
while($lines++ < 0)
|
||||
{
|
||||
$output = substr($output, strpos($output, "\n") + 1);
|
||||
}
|
||||
|
||||
return explode("\n", str_replace(array("\r\n", "\r"), array("\n", ''), trim($output)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace PhpExtended\Tail;
|
||||
|
||||
/**
|
||||
* TailException class file.
|
||||
*
|
||||
* This is a generic purpose exception for all of that may occur when tailing
|
||||
* a file with this library.
|
||||
*
|
||||
* @author Anastaszor
|
||||
*/
|
||||
class TailException extends \Exception
|
||||
{
|
||||
/**
|
||||
* The path of the file that was given.
|
||||
*
|
||||
* @var string the path of the file.
|
||||
*/
|
||||
private $_filename = null;
|
||||
|
||||
/**
|
||||
* The number of lines that were asked.
|
||||
*
|
||||
* @var int the number of lines.
|
||||
*/
|
||||
private $_nblines = null;
|
||||
|
||||
/**
|
||||
* An estimation of the number of characters per line.
|
||||
*
|
||||
* @var int the median number of characters per line.
|
||||
*/
|
||||
private $_hint = null;
|
||||
|
||||
/**
|
||||
* Builds a new TailException object.
|
||||
*
|
||||
* @param string $filename the name of the file
|
||||
* @param int $nblines the number of lines wanted
|
||||
* @param int $hint an estimation of the median number of characters per line
|
||||
* @param string $message the message of the exception
|
||||
* @param int $code the error code associated to this exception
|
||||
*/
|
||||
public function __construct($filename, $nblines, $hint, $message, $code)
|
||||
{
|
||||
parent::__construct($message, $code);
|
||||
$this->_filename = $filename;
|
||||
$this->_nblines = $nblines;
|
||||
$this->_hint = $hint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file path that was asked.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFilename()
|
||||
{
|
||||
return $this->_filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of lines that was asked.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNblines()
|
||||
{
|
||||
return $this->_nblines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the median number of characters per line that was given, or
|
||||
* calculated, if applicable.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHint()
|
||||
{
|
||||
return $this->_hint;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace PhpExtended\Tail;
|
||||
|
||||
/**
|
||||
* TailShellException class file.
|
||||
*
|
||||
* This exception occurred if the `tail -n` command on an unix shell did not
|
||||
* return the expected result.
|
||||
*
|
||||
* @author Anastaszor
|
||||
*/
|
||||
class TailShellException extends TailException
|
||||
{
|
||||
/**
|
||||
* Builds a new TailShellException object.
|
||||
*
|
||||
* @param string $filename the name of targeted file
|
||||
* @param int $nblines the number of lines that were demanded
|
||||
* @param int $hint an estimation of the line length in that file
|
||||
*/
|
||||
public function __construct($filename, $nblines, $hint)
|
||||
{
|
||||
parent::__construct($filename, $nblines, $hint,
|
||||
strtr('Error in reading file {filename}', array('{filename}' => $filename)),
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user