Анализ данных, состоящих из полей фиксированной ширины
Решение
Это делается при помощи функции substr():
$fp=fopen('fixed-width-records.txt','r') or die ("can't open file");
while ($s=fgets($fp,1024)) {
$fields[1]=substr($s,0,10); // первое поле:первые 10 символов строки
$fields[2]=substr($s,10,5); // второе поле:следующие 5 символов строки
$fields[3]=substr($s,15,12); // третье поле:следующие 12 символов строки
// функция обработки полей
process_fields($fields);
}
fclose($fp) or die("can't close file");
Или функции unpack():
$fp = fopen('fixed width records.txt','r') or die ("can't open file");
while ($s=fgets($fp,1024)) {
// ассоциативный массив с ключами "title", "author" и
// "publication_year"
$fields=unpack('A25title/A14author/A4publication_year',$s);
// функция обработки полей
process_fields($fields);
} fclose($fp) or die("can't close file");
Обсуждение
Данные, в которых каждому полю выделено фиксированное число символов в строке, могут выглядеть, как этот список книг, названий и дат опубликования:
$booklist=<< Elmer Gantry Sinclair Lewis1927
The Scarlatti InheritanceRobert Ludlum 1971
The Parsifal Mosaic Robert Ludlum 1982
Sophie's Choice William Styron1979
END;
В каждой строке название занимает 25 символов, имя автора – следующие 14 символов, а год публикации – следующие 4 символа. Зная ширину полей, очень просто с помощью функции substr() перенести поля в массив.
$books = explode("\n",$booklist);
for($i=0, $j=count($books); $i < $j; $i++) {
$book_array[$i]['title']=substr($books[$i],0,25);
$book_array[$i]['author']=substr($books[$i],25,14);
$book_array[$i]['publication_year']=substr($books[$i],39,4);
}
Разбиение переменной $booklist на массив строк позволяет применить один код разбора одной строки ко всем строкам, прочитанным из файла. Цикл можно сделать более гибким, определив отдельные массивы для имен полей и их ширины, которые могут быть переданы в анализирующую функцию, как показано в функции pc_fixed_width_substr() примера 1.3.
Пример 1.3. pc_fixed_width_substr()
function pc_fixed_width_substr($fields,$data) {
$r=array();
for ($i=0, $j=count($data); $i < $j; $i++) {
$line_pos=0;
foreach($fields as $field_name => $field_length) {
$r[$i][$field_name]=rtrim(substr($data[$i],$line_pos,$field_length));
$line_pos += $field_length;
}
}
Return $r;
}
$book_fields=array('title' => 25, 'author' => 14, 'publication_year' => 4);
$book_array=pc_fixed_width_substr($book_fields,$books);
Переменная $line_pos отслеживает начало каждого поля, и она увеличивается на ширину предыдущего поля по мере того, как код обрабатывает каждую строку. Для удаления пробельных символов в конце каждого поля предназначена функция rtrim(). Как альтернатива функции substr() для извлечения полей может применяться функция unpack(). Вместо того чтобы задавать имена полей и их ширину в виде ассоциативных массивов, создайте строку форматирования для функции. Код для извлечения полей фиксированной ширины аналогичен функции pc_fixed_width_unpack(), показанной в примере 1.4.
Пример 1.4. pc_fixed_width_unpack()
function pc_fixed_width_unpack($format_string,$data) {
$r=array();
for ($i=0, $j=count($data); $i < $j; $i++) {
$r[$i]=unpack($format_string,$data[$i]);
}
return $r;
}
$book_array=pc_fixed_width_unpack
('A25title/A14author/A4publication_year',$books);
Формат A означает «строку в обрамлении пробелов», поэтому нет необходимости удалять завершающие пробелы с помощью функции rtrim().Поля, перенесенные с помощью какой-либо функции в переменную $book_array, могут быть отображены в виде HTML-таблицы, например:
$book_array=
pc_fixed_width_unpack('A25title/A14author/A4publication_year',$books);
print "<table>\n";
// печатаем строку заголовка
print '<tr><td>';
print join('</td><td>',array_keys($book_array[0]));
print "</td></tr>\n";
// печатаем каждую строку данных
foreach ($book_array as $row) {
print '<tr><td>';
print join('</td><td>',array_values($row));
print "</td></tr>\n";
}
print '</table>\n';
Объединение данных с помощью тегов </td><td> формирует строку таблицы, не включая в нее начальный <td> и заключительный </td> теги. Печатая <tr><td> перед выводом объединенных данных и </td></tr> вслед за выводом объединенных данных, мы формируем полную строку таблицы.
И функция substr(), и функция unpack() имеют одинаковые возможности, если поля фиксированной ширины содержат строки, но функция unpack() является наилучшим решением при наличии полей других типов данных.
Комментарии:
Комментариев нет
|
|
|