我不知道任何专门处理固定宽度记录的 PHP 库。但是,如果您可以自己分解文件的每一行,那么有一些很好的库可以过滤和验证一行数据字段。
查看 Zend Framework 中的Zend_Filter和Zend_Validate组件。我认为这两个组件都是相当独立的,只需要 Zend_Loader 即可工作。如果您愿意,您可以将这三个组件从 Zend Framework 中提取出来并删除其余部分。
Zend_Filter_Input就像过滤器和验证器的集合。您为数据记录的每个字段定义一组过滤器和验证器,您可以使用它们来处理数据集的每个记录。已经定义了许多有用的过滤器和验证器,并且编写自己的接口非常简单。我建议使用 StringTrim 过滤器来删除填充字符。
要将每一行分解为字段,我将扩展 Zend_Filter_Input 类并添加一个名为 setDataFromFixedWidth() 的方法,如下所示:
class My_Filter_Input extends Zend_Filter_Input
{
public function setDataFromFixedWidth($record, array $recordRules)
{
if (array_key_exists('regex', $recordRules) {
$recordRules = array($recordRules);
}
foreach ($recordRules as $rule) {
$matches = array();
if (preg_match($rule['regex'], $record, $matches)) {
$data = array_combine($rule['fields'], $matches);
return $this->setData($data);
}
}
return $this->setData(array());
}
}
并使用简单的正则表达式和匹配的字段名称定义各种记录类型。ICESA 可能看起来像这样:
$recordRules = array(
array(
'regex' => '/^(A)(.{4})(.{9})(.{4})/', // This is only the first four fields, obviously
'fields' => array('recordId', 'year', 'federalEin', 'taxingEntity',),
),
array(
'regex' => '/^(B)(.{4})(.{9})(.{8})/',
'fields' => array('recordId', 'year', 'federalEin', 'computer',),
),
array(
'regex' => '/^(E)(.{4})(.{9})(.{9})/',
'fields' => array('recordId', 'paymentYear', 'federalEin', 'blank1',),
),
array(
'regex' => '/^(S)(.{9})(.{20})(.{12})/',
'fields' => array('recordId', 'ssn', 'lastName', 'firstName',),
),
array(
'regex' => '/^(T)(.{7})(.{4})(.{14})/',
'fields' => array('recordId', 'totalEmployees', 'taxingEntity', 'stateQtrTotal'),
),
array(
'regex' => '/^(F)(.{10})(.{10})(.{4})/',
'fields' => array('recordId', 'totalEmployees', 'totalEmployers', 'taxingEntity',),
),
);
然后您可以逐行读取数据文件并将其输入到输入过滤器中:
$input = My_Filter_Input($inputFilterRules, $inputValidatorRules);
foreach (file($filename) as $line) {
$input->setDataFromFixedWidth($line, $recordRules);
if ($input->isValid()) {
// do something useful
}
else {
// scream and shout
}
}
要格式化数据以写回文件,您可能需要编写自己的 StringPad 过滤器来包装内部 str_pad 函数。然后对于数据集中的每条记录:
$output = My_Filter_Input($outputFilterRules);
foreach ($dataset as $record) {
$output->setData($record);
$line = implode('', $output->getEscaped()) . "\n";
fwrite($outputFile, $line);
}
希望这可以帮助!