1<?php 2 3/** 4 * Hoa 5 * 6 * 7 * @license 8 * 9 * New BSD License 10 * 11 * Copyright © 2007-2017, Hoa community. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions are met: 15 * * Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * * Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * * Neither the name of the Hoa nor the names of its contributors may be 21 * used to endorse or promote products derived from this software without 22 * specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE 28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37namespace Hoa\File; 38 39use Hoa\Stream; 40 41/** 42 * Class \Hoa\File\ReadWrite. 43 * 44 * File handler. 45 * 46 * @copyright Copyright © 2007-2017 Hoa community 47 * @license New BSD License 48 */ 49class ReadWrite 50 extends File 51 implements Stream\IStream\In, 52 Stream\IStream\Out 53{ 54 /** 55 * Open a file. 56 * 57 * @param string $streamName Stream name. 58 * @param string $mode Open mode, see the self::MODE_* constants. 59 * @param string $context Context ID (please, see the 60 * \Hoa\Stream\Context class). 61 * @param bool $wait Differ opening or not. 62 */ 63 public function __construct( 64 $streamName, 65 $mode = parent::MODE_APPEND_READ_WRITE, 66 $context = null, 67 $wait = false 68 ) { 69 parent::__construct($streamName, $mode, $context, $wait); 70 71 return; 72 } 73 74 /** 75 * Open the stream and return the associated resource. 76 * 77 * @param string $streamName Stream name (e.g. path or URL). 78 * @param \Hoa\Stream\Context $context Context. 79 * @return resource 80 * @throws \Hoa\File\Exception\FileDoesNotExist 81 * @throws \Hoa\File\Exception 82 */ 83 protected function &_open($streamName, Stream\Context $context = null) 84 { 85 static $createModes = [ 86 parent::MODE_READ_WRITE, 87 parent::MODE_TRUNCATE_READ_WRITE, 88 parent::MODE_APPEND_READ_WRITE, 89 parent::MODE_CREATE_READ_WRITE 90 ]; 91 92 if (!in_array($this->getMode(), $createModes)) { 93 throw new Exception( 94 'Open mode are not supported; given %d. Only %s are supported.', 95 0, 96 [$this->getMode(), implode(', ', $createModes)] 97 ); 98 } 99 100 preg_match('#^(\w+)://#', $streamName, $match); 101 102 if (((isset($match[1]) && $match[1] == 'file') || !isset($match[1])) && 103 !file_exists($streamName) && 104 parent::MODE_READ_WRITE == $this->getMode()) { 105 throw new Exception\FileDoesNotExist( 106 'File %s does not exist.', 107 1, 108 $streamName 109 ); 110 } 111 112 $out = parent::_open($streamName, $context); 113 114 return $out; 115 } 116 117 /** 118 * Test for end-of-file. 119 * 120 * @return bool 121 */ 122 public function eof() 123 { 124 return feof($this->getStream()); 125 } 126 127 /** 128 * Read n characters. 129 * 130 * @param int $length Length. 131 * @return string 132 * @throws \Hoa\File\Exception 133 */ 134 public function read($length) 135 { 136 if (0 > $length) { 137 throw new Exception( 138 'Length must be greater than 0, given %d.', 139 2, 140 $length 141 ); 142 } 143 144 return fread($this->getStream(), $length); 145 } 146 147 /** 148 * Alias of $this->read(). 149 * 150 * @param int $length Length. 151 * @return string 152 */ 153 public function readString($length) 154 { 155 return $this->read($length); 156 } 157 158 /** 159 * Read a character. 160 * 161 * @return string 162 */ 163 public function readCharacter() 164 { 165 return fgetc($this->getStream()); 166 } 167 168 /** 169 * Read a boolean. 170 * 171 * @return bool 172 */ 173 public function readBoolean() 174 { 175 return (bool) $this->read(1); 176 } 177 178 /** 179 * Read an integer. 180 * 181 * @param int $length Length. 182 * @return int 183 */ 184 public function readInteger($length = 1) 185 { 186 return (int) $this->read($length); 187 } 188 189 /** 190 * Read a float. 191 * 192 * @param int $length Length. 193 * @return float 194 */ 195 public function readFloat($length = 1) 196 { 197 return (float) $this->read($length); 198 } 199 200 /** 201 * Read an array. 202 * Alias of the $this->scanf() method. 203 * 204 * @param string $format Format (see printf's formats). 205 * @return array 206 */ 207 public function readArray($format = null) 208 { 209 return $this->scanf($format); 210 } 211 212 /** 213 * Read a line. 214 * 215 * @return string 216 */ 217 public function readLine() 218 { 219 return fgets($this->getStream()); 220 } 221 222 /** 223 * Read all, i.e. read as much as possible. 224 * 225 * @param int $offset Offset. 226 * @return string 227 */ 228 public function readAll($offset = 0) 229 { 230 return stream_get_contents($this->getStream(), -1, $offset); 231 } 232 233 /** 234 * Parse input from a stream according to a format. 235 * 236 * @param string $format Format (see printf's formats). 237 * @return array 238 */ 239 public function scanf($format) 240 { 241 return fscanf($this->getStream(), $format); 242 } 243 244 /** 245 * Write n characters. 246 * 247 * @param string $string String. 248 * @param int $length Length. 249 * @return mixed 250 * @throws \Hoa\File\Exception 251 */ 252 public function write($string, $length) 253 { 254 if (0 > $length) { 255 throw new Exception( 256 'Length must be greater than 0, given %d.', 257 3, 258 $length 259 ); 260 } 261 262 return fwrite($this->getStream(), $string, $length); 263 } 264 265 /** 266 * Write a string. 267 * 268 * @param string $string String. 269 * @return mixed 270 */ 271 public function writeString($string) 272 { 273 $string = (string) $string; 274 275 return $this->write($string, strlen($string)); 276 } 277 278 /** 279 * Write a character. 280 * 281 * @param string $char Character. 282 * @return mixed 283 */ 284 public function writeCharacter($char) 285 { 286 return $this->write((string) $char[0], 1); 287 } 288 289 /** 290 * Write a boolean. 291 * 292 * @param bool $boolean Boolean. 293 * @return mixed 294 */ 295 public function writeBoolean($boolean) 296 { 297 return $this->write((string) (bool) $boolean, 1); 298 } 299 300 /** 301 * Write an integer. 302 * 303 * @param int $integer Integer. 304 * @return mixed 305 */ 306 public function writeInteger($integer) 307 { 308 $integer = (string) (int) $integer; 309 310 return $this->write($integer, strlen($integer)); 311 } 312 313 /** 314 * Write a float. 315 * 316 * @param float $float Float. 317 * @return mixed 318 */ 319 public function writeFloat($float) 320 { 321 $float = (string) (float) $float; 322 323 return $this->write($float, strlen($float)); 324 } 325 326 /** 327 * Write an array. 328 * 329 * @param array $array Array. 330 * @return mixed 331 */ 332 public function writeArray(array $array) 333 { 334 $array = var_export($array, true); 335 336 return $this->write($array, strlen($array)); 337 } 338 339 /** 340 * Write a line. 341 * 342 * @param string $line Line. 343 * @return mixed 344 */ 345 public function writeLine($line) 346 { 347 if (false === $n = strpos($line, "\n")) { 348 return $this->write($line . "\n", strlen($line) + 1); 349 } 350 351 ++$n; 352 353 return $this->write(substr($line, 0, $n), $n); 354 } 355 356 /** 357 * Write all, i.e. as much as possible. 358 * 359 * @param string $string String. 360 * @return mixed 361 */ 362 public function writeAll($string) 363 { 364 return $this->write($string, strlen($string)); 365 } 366 367 /** 368 * Truncate a file to a given length. 369 * 370 * @param int $size Size. 371 * @return bool 372 */ 373 public function truncate($size) 374 { 375 return ftruncate($this->getStream(), $size); 376 } 377} 378