PHP5. Быстрая обработка csv файлов

Задача.
Есть основной файл и файлы шаблонов, причем все имеют расширение csv. Как можно быстро обработать файл на основе шаблонов?

В php5 есть специализированные функции str_getcsv(), fgetcsv() и fputcsv(), которые адаптированы для работы с такого рода файлами. Но можно обойтись и без этих функций. Во время такого рода манипуляций часто сталкивался с ошибками, которые необходимо учитывать - извлекаемые значения из массивов порой содержали неожиданные знаки табуляции, или строка состояла из символов в перемешку с NULL-символами... Поэтому обращение к шаблонам, разобранных на соответствующие массивы, сопровождались казусами, например - использование неопределенных массивов. Отсюда вывод - нужно использовать trim() как фильтр от таких "неожиданностей" и isset() - как подобие отлова исключительной ситуации с попыткой извлечения значения из массива по неопределенному индексу. В остальном все сработало неплохо :)

Пример (download).

<?php ## manipulation with csv-files (base of device tags)
/***********open source and target csv-files*****************************************
// 13010000.csv
$f = fopen("c:\\php\\scripts\\in\\devices.csv", "rb");
// pattern.csv
$pattern = fopen("c:\\php\\scripts\\templates\\pattern.csv", "rb");
// BTDevices_Adresses.csv
$btdevices = fopen("c:\\php\\scripts\\templates\\BTDevices_Adresses.csv", "rb");
// output.csv
$output = fopen("c:\\php\\scripts\\out\\output.csv", "wb");
//***********transfer data from file to string and clean all NULL************************
function transfer($file) {
 // read file to $hash from $buffer. Take max length of Double Integer
 while(($buffer = fgets($file, 64536)) !== FALSE) {
  $hash[] = $buffer;
 }
 // sort $hash and clean from '\0'
 for($k = 0; $k < count($hash); $k++) {
  // cleaned massive
  $strbox[$k] = " ";
  for($i = 0, $j = 0; $j < strlen($hash[$k]); $j++) {
   if($hash[$k][$j] == "\0") {
    continue;
   }
   else {
    $strbox[$k][$i] = $hash[$k][$j];
    $i++;
   }
  } 
 }

 // Clean buffer
 $buffer = NULL;

 return $strbox;
}
//**********transfer all files****************************************************
// device.csv
$box_f = transfer($f);
// pattern.csv
$box_patt = transfer($pattern);
// BTDevices_Adresses.csv
$box_btd = transfer($btdevices);
// create accessories arraies
//********$template_array  ********Array[:TEMPLATES][$i] = Signal Alias   ***********
// parse string into an array
for($i = 0; $i < count($box_patt); $i++) {
 $temp[] = explode(",", $box_patt[$i]);
}
// create Array[:TEMPLATES][$i] = Signal Alias
$template_array = Array();
for($col = 0; $col < count($temp[0]); $col++) {
 $template_name = NULL;
 $template_name = $temp[0][$col];
 for($str = 1; $str < count($temp); $str++) {
  $tem = NULL;
  $tem = $temp[$str][$col];
  $template_array[$template_name][] = $tem;
 }
}
//************************************************  $btd  ***********************   Array[:Tagname] = ShortDesc   *****************
// create Array[:Tagname] = ShortDesc
// ...немного схалтурил, так как нужно искать по индексам или иначе.
// Сие допустимо, так как структура файла - исходника нам известна
// parse string into an array. $i = 0 - header string have to miss
for($i = 1; $i < count($box_btd); $i++) {
 list(, $shortdesc,,,,,,, $tagname) = explode(",", $box_btd[$i]);
 $btd[$tagname] = $shortdesc;
 $shortdesc = NULL;
 $tagname = NULL;
}
//**********$engunits  ****************Array[:Tagname] = EngUnits   *****************
// create Array[:Tagname] = EngUnits
// ...немного схалтурил, так как нужно искать по индексам или иначе.
// Сие допустимо, так как структура файла - исходника нам известна
// parse string into an array. $i = 0 - header string have to miss
for($i = 1; $i < count($box_btd); $i++) {
 list(,,,, $engunit,,,, $tagname) = explode(",", $box_btd[$i]);
 $engunits[$tagname] = $engunit;
 $engunit = NULL;
 $tagname = NULL;
}
// create main array ($arr is base on input file)
//**********************$arr ****************************************************
// parse string into an array
for($i = 0; $i < count($box_f); $i++) {
 $arr[] = explode(",", $box_f[$i]);
}
print_r($arr);
//***********************processing $arr and rewrite needly values*********************
// for change values of $arr in loop we get array by ref
$count_row = 0;
foreach($arr as &$row) {
 foreach($row as $elem => $value) {

  // ':TEMPLATE'
  if((strpos($value, ':TEMPLATE')) !== false) {
  
   // reset array
   $signal_aliases = Array();
   // find template name of device
   list(,$templ) = explode("=", $value);
   $trimmed_templ = trim($templ);
   // defined signal aliases of find template
   // $template_array is array that content link :TEMPLATE -> Array(Template signal aliases)
   if(isset($template_array[$trimmed_templ])) {
    $signal_aliases = $template_array[$trimmed_templ];
   }  
  }
 
  // ':Tagname'
  if((strpos($value, ':Tagname')) !== false) {
  
   // initialization
   $index = 1;
   $stop = true;
   // reset array $tags
   $tags = Array();
   //
   while($stop) {
    $tag = trim($arr[$count_row + $index][$elem]);
    if($tag !== "") {
     $tags[] = $tag;
     $index++;
    }
    if($tag == "") {
     $stop = false;
    }
   }
  }
 
  // 'ShortDesc'
  if((strpos($value, 'ShortDesc')) !== false) {
   // initialization
   $position = $count_row + 1;
   $indexx = 0;
   while($indexx < count($tags)) {
    $tag_item = trim($tags[$indexx]);
    if(isset($btd[$tag_item])) {
     $short_desc = trim($btd[$tag_item]);
     $arr[$position + $indexx][$elem] = $short_desc;
    }
    $indexx++;
   }  
  }
 
  // 'Signal_alias.Desc'
  if((strpos($value, '.Desc')) !== false) {
 
   // find index field 'ShortDesc'
   list($item,) = explode(".", $value);
   $item = trim($item);
   //
   if(in_array($item, $signal_aliases)) {
  
    $pos = $count_row + 1;
    $indexxx = 0;
   
    while($indexxx < count($tags)) {
     $new_tag_item = trim($tags[$indexxx]);
     if(isset($btd[$new_tag_item])) {     
      $new_item = ". ".str_replace("_", " ", $item).".";
      $item_for_push = $btd[$new_tag_item].$new_item;
      $arr[$pos + $indexxx][$elem] = $item_for_push;
     }
     $indexxx++;
    }
   }  
  
  }
 }
 $count_row++;
}
//**************transfer from massive to string and write to output csv-file*****************
// for catch mini bug 'ая;'. It`s may be control symbols
$str = ltrim(implode(",", $arr[0]), "ая;");
fputs($output, $str);
// build output file
for($i = 1; $i < sizeof($arr); $i++) {
 $str = implode(",", $arr[$i]);
 fputs($output, $str);
}
//***********************close handles of source and target csv-files*********************
 
fclose($f);
fclose($pattern);
fclose($btdevices);
fclose($output);
?>