/** * 打开关闭文件 */ fopen() // 2/4: 2 个必选参数, 4 个参数; fclose() // 1/1; // 打开文件的模式: // 'b' 修饰符可以和模式一起使用以便指定文件是二进制类型的。Windows 系统是区分文本和二进制文件的;如果在 Windows 下没有指定 'b',文件可能会出错;为了是脚本通用,在处理一个二进制文件时最好总是加上 'b'。在 Unix 里(linux,fressbsd,macosx),'b' 没有任何作用 /** * 读取文件 */ // 需先用 fopen() 打开文件才能读取的函数;从文件指针处开始读取 fgetc() // 1/1; 读取一个字符 fgets() // 1/2; 读取一行 fgetss() // 1/3; 读取一行并去除 HMTL 标签 fgetcsv() // 1/5; 读取一行并解析为 csv 字段,返回数组 fread() // 2/2; 读取指定字节的字符 fscanf() // 2/n; 从文件中格式化输入 // 不需要先 fopen() 打开文件的函数 file() // 1/3; 读取整个文件内容到一个数组,文件中一行对应数组中一个元素 file_get_contents() // 1/5; 读取整个文件到一个字符串 readfile() // 1/3; 读入一个文件并写入到输出缓冲。 /** * 写入文件 */ fwrite() / fputs() // 2/3; 写入文件(可安全用于二进制文件), 需先 fopen() fputcvs() // 2/4; 将行格式化为 CSV 并写入文件指针,需先 fopen() file_put_contents() // 2/4; 将字符串整个写入文件 /** * 文件指针 */ ftell() // 1/1; 返回文件指针读/写的位置 fseek() // 2/3; 在文件指针中定位 rewind() // 1/1; 倒回文件指针的位置 /** * 使用 SplFileObject 方法 fgetcsv() 时最后一行后面还会解析出一个数组 * eg: * $it = new SplFileObject('sample.csv'); * while( $arr = $it->fgetcsv() ){ * print_r( $arr) * } */ class CSVFileObjectException extends Exception{ // } class CSVFileObject extends SplFileInfo implements Iterator{ protected $current_line; protected $map; protected $column_cnt; protected $fp; function __construct( $filename, $mode, $use_include_path = FALSE, $context = NULL) { $this->ensure( ! is_readable( $filename), "CSV file {$filename} does not exists or is not readable"); if( is_null( $context)){ $this->fp = @fopen( $filename, $mode, $use_include_path); }else{ $this->fp = @fopen( $filename, $mode, $use_include_path, $context); } $this->ensure( ! $this->fp, "open CSV file {$filename} failure"); parent::__construct( $filename); $this->current_line = 0; $this->map = $this->fgetcsv(); $this->column_cnt = count( $this->map); } /** * 是否抛出异常 */ function ensure( $whether = FALSE, $msg = 'error') { if( $whether){ throw new CSVFileObjectException( $msg); } } function fgetcsv( $delimiter = ',', $enclosure = '"') { return fgetcsv( $this->fp, 1000, $delimiter, $enclosure); } function fgetcsv( $delimiter = ',', $enclosure = '"') { return fgetcsv( $this->fp, 1000, $delimiter, $enclosure); } function rewind() { $this->current_line = 0; rewind( $this->fp); fgets( $this->fp); // skip the column headers,跳过 csv 的头 } function key() { return $this->current_line; } function current() { $fp_loc = ftell( $this->fp); $data = $this->fgetcsv(); fseek( $this->fp, $fp_loc); $cnt = count( $data); // 保证 array_combine() 的参数一致 if( $cnt < $this->column_cnt){ $blank_arr = array_fill( 0, ($this->column_cnt - $cnt), ''); $data = array_merge( $data, $blank_arr); } if( $cnt > $this->column_cnt){ $data = array_slice( $data, 0, $this->column_cnt); } return array_combine( $this->map, $data); } function next() { $this->current_line ++; fgets( $this->fp); // bump the file pointer to the next line,使文件指针向下移动一行 } function valid() { if( feof( $this->fp )){ return FALSE; } $fp_loc = ftell( $this->fp); // 防止最后一行后面解析出一个数组 $data = $this->fgetcsv(); fseek( $this->fp, $fp_loc); return is_array( $data); } } // eg: $file = new CSVFileObject( 'sample.csv', 'r'); foreach( $file as $v){ print_r( $v); }