xref: /PHP-7.0/ext/spl/internal/splfileobject.inc (revision b255b97e)
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 feof($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