Я не знаю ни одной библиотеки PHP, которая специально обрабатывает записи фиксированной ширины.Но есть несколько хороших библиотек для фильтрации и проверки строки полей данных, если вы можете самостоятельно разбить каждую строку файла.
Взгляните на Zend_Filter и Zend_Validate компоненты от Zend Framework.Я думаю, что оба компонента довольно автономны и требуют только 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);
}
Надеюсь, это поможет!