Последнее обновление:
Как превратить содержимое файла csv в массив в языке РНР?
Напомним, что такое файл, имеющий расширение csv. Это файл, состоящий из строк. В каждой из которых имеются данные, разделенные тем или иным разделителем. Например, запятой «,», точкой с запятой «;» или иным (одиночным) символом. В таких файлах удобно хранить справочную информацию. Или совокупность данных, имеющих отношение к настройкам сайта. Кроме того, на файлах csv можно сделать аналог «баз данных». Правда, такие «базы данных» будут работать несколько медленнее, чем обычно используемые (типа MySQL, к примеру). Кроме того, реализация управления такими «базами данных» ляжет целиком и полностью на разработчика, т.к. никакого готового механизма работы с файлами csv с точки зрения иерархии данных не существует. Однако, здесь есть, пожалуй, один плюс: зато такая «СУБД» будет полностью контролироваться разработчиком сайта. И качество (в том числе, склонность к уязвимостям) ее работы будет полностью определяться им, этим разработчиком.
Читать информацию из такого файла можно, например, построчно. И каждую строчку – превращать в массив, например, при помощи функций explode()
или str_getcsv()
.
Однако, при этом придется делать построчное чтение файла (в цикле). Что является оправданным, если файл или слишком большой, или, наоборот, довольно небольшой. А вот при «средних» размерах файла, равных, скажем, 0,5…5 МБ (это чисто из практического опыта) целесообразнее использовать более скоростной метод чтения файла и превращения его в массив целиком. Как показала практика автора этой статьи, так РНР работает быстрее.
Итак, пусть у нас есть файл, содержащие строки с данными. Например, вот с таким содержимым:
red;trueCRLF
ecre;1234;qqqqqqqqqqqqCRLF
Последние символы – это, как известно, символы перевода каретки и перехода на следующую строку в текстовых файлах, созданных в операционной системе Windows.
Как превратить содержимое файла в массив?
И мы хотим превратить это содержимое в массив. Вот функция, написанная на языке PHP. Назовем ее str_getcsv_Arr()
:
function str_getcsv_Arr($file, $delim){
$csv = array_map(function ($elem) use ($delim){
return str_getcsv($elem, $delim);
}, file($file));
return $csv;
}
Как это работает
Вначале содержимое файла, в котором имеются указанные данные, передается в переменную $file
. Функция file()
читает этот файл и сразу превращает его в массив, в каждом из элементов которого будет содержаться соответствующая строка из файла. Однако, нам-то надо, чтобы еще и данные из каждой строки были, в свою очередь, записаны в отдельные элементы массива…
Вместо цикла используется известная универсальная команда array_map()
. Она перебирает элементы полученного массива (которые представляют собой строки). А в качестве callback-функции для array_map
используется безымянная функция.
Впрочем, можно использовать и функцию с именем, но это, во-первых, увеличит объем кода; а, во-вторых, безымянная функция НЕ будет храниться в стеке и уничтожится из оперативной памяти сразу после ее выполнения. Можно сказать, что безымянная функция немного эффективнее, чем именованная.
Эта функция принимает в качестве входного параметра $elem
, т.е. одну из строк, содержащихся в файле. И уже к ней, к этой строке, применяется функция str_getcsv()
, преобразуя эту строку в массив. Точнее, в подмассив.
Все бы просто, но по умолчанию в качестве разделителей в csv-файлах используется запятая. А мы-то хотим – чтобы точка с запятой. Поэтому используется второй параметр - $delim
, в которай как раз и передается символ ;
.
Безымянная функция представляет собой замыкание. И в него нужно передать параметр $delim
. Можно было бы указать его в качестве второй переменной для этой функции, НО это не дает сделать array_map
: она принимает на вход только массивы. А создавать массив из символов ;
как-то не очень. Поэтому здесь используется слово use
. Оно как раз требуется в подобных случаях, когда в функцию следует передать данные, но невозможно или нецелесообразно передавать их в качестве «обычного» параметра (т.е. в круглых скобках).
Результат работы
И вот что получим в результате работы нашей функции. Получится массив. Назовем его Arr
:
Array
(
[0] => Array
(
[0] => red
[1] => true
)
[1] => Array
(
[0] => ecre
[1] => 1234
[2] => qqqqqqqqqqqq
)
)
Как видим, каждый элемент данных, содержащихся в файле и отделенный разделителем (в данном случае ;
или символом конца строки) от другого элемента данных, записался в отдельный элемент массива.
Итоговый массив, конечно, является двумерным. Т.е. для того, чтобы, скажем, получить элемент данных true, следует обратиться к следующему элементы массива: Arr[0][1]
.
Следует отметить, что двумерные массивы требует повышенного расхода оперативной памяти. Поэтому в случае, если файл csv
будет большим – следует контролировать объем потребляемой памяти в
процессе выполнения РНР. Иначе может возникнуть ситуация, когда памяти
вдруг не хватит (точнее, потребляемый ее объем сравняется с предельно
допустимым объемом памяти, установленным для интерпретатора PHP). Это
приведет к аварийному завершению работы скрипта.