1<?php 2 3/** @file splfileobject.inc 4 * @ingroup SPL 5 * @brief class FileObject 6 * @author Marcus Boerger 7 * @date 2003 - 2009 8 * 9 * SPL - Standard PHP Library 10 */ 11 12/** @ingroup SPL 13 * @brief Object representation for any stream 14 * @author Marcus Boerger 15 * @version 1.1 16 * @since PHP 5.1 17 */ 18class SplFileObject extends SplFileInfo implements RecursiveIterator, SeekableIterator 19{ 20 /** Flag: wheter to suppress new lines */ 21 const DROP_NEW_LINE = 0x00000001; 22 23 private $fp; 24 private $fname; 25 private $line = NULL; 26 private $lnum = 0; 27 private $max_len = 0; 28 private $flags = 0; 29 private $delimiter= ','; 30 private $enclosure= '"'; 31 32 /** 33 * Constructs a new file object 34 * 35 * @param $file_name The name of the stream to open 36 * @param $open_mode The file open mode 37 * @param $use_include_path Whether to search in include paths 38 * @param $context A stream context 39 * @throw RuntimeException If file cannot be opened (e.g. insufficient 40 * access rights). 41 */ 42 function __construct($file_name, $open_mode = 'r', $use_include_path = false, $context = NULL) 43 { 44 $this->fp = fopen($file_name, $open_mode, $use_include_path, $context); 45 if (!$this->fp) 46 { 47 throw new RuntimeException("Cannot open file $file_name"); 48 } 49 $this->fname = $file_name; 50 } 51 52 /** 53 * @return whether the end of the stream is reached 54 */ 55 function eof() 56 { 57 return eof($this->fp); 58 } 59 60 /** increase current line number 61 * @return next line from stream 62 */ 63 function fgets() 64 { 65 $this->freeLine(); 66 $this->lnum++; 67 $buf = fgets($this->fp, $this->max_len); 68 69 return $buf; 70 } 71 72 /** 73 * @param delimiter character used as field separator 74 * @param enclosure end of 75 * @return array containing read data 76 */ 77 function fgetcsv($delimiter = NULL, $enclosure = NULL) 78 { 79 $this->freeLine(); 80 $this->lnum++; 81 switch(fun_num_args()) 82 { 83 case 0: 84 $delimiter = $this->delimiter; 85 case 1: 86 $enclosure = $this->enclosure; 87 default: 88 case 2: 89 break; 90 } 91 return fgetcsv($this->fp, $this->max_len, $delimiter, $enclosure); 92 } 93 94 /** 95 * Set the delimiter and enclosure character used in fgetcsv 96 * 97 * @param delimiter new delimiter, defaults to ',' 98 * @param enclosure new enclosure, defaults to '"' 99 */ 100 function setCsvControl($delimiter = ';', $enclosure = '"') 101 { 102 $this->delimiter = $delimiter; 103 $this->enclosure = $enclosure; 104 } 105 106 /** 107 * @return array(delimiter, enclosure) as used in fgetcsv 108 */ 109 function getCsvControl($delimiter = ',', $enclosure = '"') 110 { 111 return array($this->delimiter, $this->enclosure); 112 } 113 114 /** 115 * @param operation lock operation (LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB) 116 * @retval $wouldblock whether the operation would block 117 */ 118 function flock($operation, &$wouldblock) 119 { 120 return flock($this->fp, $operation, $wouldblock); 121 } 122 123 /** 124 * Flush current data 125 * @return success or failure 126 */ 127 function fflush() 128 { 129 return fflush($this->fp); 130 } 131 132 /** 133 * @return current file position 134 */ 135 function ftell() 136 { 137 return ftell($this->fp); 138 } 139 140 /** 141 * @param pos new file position 142 * @param whence seek method (SEEK_SET, SEEK_CUR, SEEK_END) 143 * @return Upon success, returns 0; otherwise, returns -1. Note that 144 * seeking past EOF is not considered an error. 145 */ 146 function fseek($pos, $whence = SEEK_SET) 147 { 148 return fseek($this->fp, $pos, $whence); 149 } 150 151 /** 152 * @return next char from file 153 * @note a new line character does not increase $this->lnum 154 */ 155 function fgetc() 156 { 157 $this->freeLine(); 158 $c = fgetc($this->fp); 159 if ($c == '\n') { 160 $this->lnum++; 161 } 162 } 163 164 /** Read and return remaining part of stream 165 * @return size of remaining part passed through 166 */ 167 function fpassthru() 168 { 169 return fpassthru($this->fp); 170 } 171 172 /** Get a line from the file and strip HTML tags 173 * @param $allowable_tags tags to keep in the string 174 */ 175 function fgetss($allowable_tags = NULL) 176 { 177 return fgetss($this->fp, $allowable_tags); 178 } 179 180 /** Scan the next line 181 * @param $format string specifying format to parse 182 */ 183 function fscanf($format /* , ... */) 184 { 185 $this->freeLine(); 186 $this->lnum++; 187 return fscanf($this->fp, $format /* , ... */); 188 } 189 190 /** 191 * @param $str to write 192 * @param $length maximum line length to write 193 */ 194 function fwrite($str, $length = NULL) 195 { 196 return fwrite($this->fp, $length); 197 } 198 199 /** 200 * @return array of file stat information 201 */ 202 function fstat() 203 { 204 return fstat($this->fp); 205 } 206 207 /** 208 * @param $size new size to truncate file to 209 */ 210 function ftruncate($size) 211 { 212 return ftruncate($this->fp, $size); 213 } 214 215 /** 216 * @param $flags new flag set 217 */ 218 function setFlags($flags) 219 { 220 $this->flags = $flags; 221 } 222 223 /** 224 * @return current set of flags 225 */ 226 function getFlags() 227 { 228 return $this->flags; 229 } 230 231 /** 232 * @param $max_len set the maximum line length read 233 */ 234 function setMaxLineLen($max_len) 235 { 236 $this->max_len = $max_len; 237 } 238 239 /** 240 * @return current setting for max line 241 */ 242 function getMaxLineLen() 243 { 244 return $this->max_len; 245 } 246 247 /** 248 * @return false 249 */ 250 function hasChildren() 251 { 252 return false; 253 } 254 255 /** 256 * @return false 257 */ 258 function getChildren() 259 { 260 return NULL; 261 } 262 263 /** 264 * Invalidate current line buffer and set line number to 0. 265 */ 266 function rewind() 267 { 268 $this->freeLine(); 269 $this->lnum = 0; 270 } 271 272 /** 273 * @return whether more data can be read 274 */ 275 function valid() 276 { 277 return !$this->eof(); 278 } 279 280 /** 281 * @note Fill current line buffer if not done yet. 282 * @return line buffer 283 */ 284 function current() 285 { 286 if (is_null($this->line)) 287 { 288 $this->line = getCurrentLine(); 289 } 290 return $this->line; 291 } 292 293 /** 294 * @return line number 295 * @note fgetc() will increase the line number when reaing a new line char. 296 * This has the effect key() called on a read a new line will already 297 * return the increased line number. 298 * @note Line counting works as long as you only read the file and do not 299 * use fseek(). 300 */ 301 function key() 302 { 303 return $this->lnum; 304 } 305 306 /** Invalidate current line buffer. 307 */ 308 function next() 309 { 310 $this->freeLine(); 311 } 312 313 /** 314 * @return next line read from file and increase the line counter 315 */ 316 private function readLine() 317 { 318 if ($this->eof()) 319 { 320 $this->freeLine(); 321 throw new RuntimeException("Cannot read from file " . $this->fname); 322 } 323 if ($this->line) { 324 $this->lnum++; 325 } 326 $this->freeLine(); 327 $this->line = fgets($this->fp, $this->max_len); 328 return $this->line; 329 } 330 331 /** 332 * Free the current line buffer and increment the line counter 333 */ 334 private function freeLine() 335 { 336 if ($this->line) { 337 $this->line = NULL; 338 } 339 } 340 341 /* 342 * @note If you DO overload this function key() and current() will increment 343 * $this->lnum automatically. If not then function reaLine() will do 344 * that for you. 345 */ 346 function getCurrentLine() 347 { 348 $this->freeLine(); 349 if ($this->eof()) 350 { 351 throw new RuntimeException("Cannot read from file " . $this->fname); 352 } 353 $this->readLine(); 354 } 355 356 /** 357 * @return current line 358 */ 359 function __toString() 360 { 361 return current(); 362 } 363 364 /** 365 * @param $line_pos Seek to this line 366 */ 367 function seek($line_pos) 368 { 369 $this->rewind(); 370 while($this->lnum < $line_pos && !$this->eof()) 371 { 372 $this->getCurrentLine(); 373 } 374 } 375} 376 377?> 378