PHP读取考勤文本文件入库遇ID长度问题求优化方案
考勤系统:优化考勤文本数据读取与入库代码
我正在完成学校的考勤系统项目,现有一份考勤文本文件,内容格式如下(每行核心字段为id、date、time,其余字段可忽略):
2042 2018-03-08 17:03:25 27 0 15 0 26059 2018-03-08 17:04:30 27 0 15 0 259 2018-03-08 17:04:34 27 0 15 0 240 2018-03-08 17:05:20 27 1 15 0 26152 2018-03-08 17:05:26 27 1 15 0 152 2018-03-08 17:05:28 27 1 15 0 24073 2018-03-08 17:06:05 27 1 15 0 263 2018-03-08 17:08:12 27 1 15 0 2194 2018-03-08 17:08:27 27 1 15 0 26116 2018-03-08 17:09:47 27 1 15 0 2616 2018-03-08 17:09:51 27 1 15 0
我尝试了如下代码实现读取文件并将数据存入数据库,但因ID长度不一致,有时无法正确获取ID,请求优化代码:
$lines = file(base_url()."./assets/uploads/".$filename); while (!feof($lines)){ preg_match("'^(.{10})(.{2})(.*)$'",$lines,$n); $data3 = array( 'id' => trim(substr($lines, 1,8)), 'time' => trim(substr($lines, 20, 9)), 'desig_date' => trim(substr($lines, 9, 11)), 'file' => $filename ); $this->Attendance->savedata($data3); }
问题分析
你的核心问题在于用固定长度截取字段——原代码假设ID、日期、时间的长度是固定的,但从考勤数据来看,ID长度从4位(2042)到5位(26059)不等,固定截取必然会导致ID或后续字段读取错误。另外,file()函数返回的是行数组,feof()是用于文件指针的函数,用它遍历数组完全错误,会导致逻辑异常。
优化后的代码
我们换用正则匹配字段格式的方式,彻底解决长度不一致的问题,同时修正遍历逻辑:
// 拼接完整文件路径 $filePath = base_url() . "./assets/uploads/" . $filename; // 读取文件,自动忽略换行符和空行 $lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); // 遍历每一行数据 foreach ($lines as $line) { // 去掉行首尾的空白字符 $line = trim($line); if (empty($line)) continue; // 正则匹配:数字ID、YYYY-MM-DD日期、HH:MM:SS时间 if (preg_match('/^(\d+)\s+(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})/', $line, $matches)) { $data3 = array( 'id' => $matches[1], // 匹配到的第一个分组:ID(任意长度数字) 'desig_date' => $matches[2], // 第二个分组:日期 'time' => $matches[3], // 第三个分组:时间 'file' => $filename ); // 存入数据库 $this->Attendance->savedata($data3); } else { // 可选:记录解析失败的行,方便排查问题 log_message('error', '无法解析的考勤数据行:' . $line); } }
优化点说明
- 修正文件读取逻辑:
file()函数添加FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES参数,自动处理换行符和空行,减少后续冗余代码。 - 替换遍历方式:用
foreach遍历行数组,替代错误的feof()判断,逻辑更清晰且符合PHP数组操作规范。 - 基于格式匹配字段:正则表达式
/^(\d+)\s+(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})/会精准匹配:- 第一个连续数字序列(任意长度)作为ID
- 后续符合
YYYY-MM-DD格式的字符串作为日期 - 再后续符合
HH:MM:SS格式的字符串作为时间
完全不受字段长度变化的影响。
- 增加健壮性:添加空行跳过和匹配失败的日志记录,方便后续排查异常数据。
内容的提问来源于stack exchange,提问作者Jc John
相关产品推荐
相关产品推荐

