I'm trying to parse a CSV string to an array in PHP. The CSV string has the following attributes:
Delimiter: ,
Enclosure: "
New line: \r\n
Example content:
"12345","Computers","Acer","4","Varta","5.93","1","0.04","27-05-2013"
"12346","Computers","Acer","5","Decra","5.94","1","0.04","27-05-2013"
When I try to parse it like this:
$url = "http://www.url-to-feed.com";
$csv = file_get_contents($url);
$data = str_getcsv($csv);
var_dump($data);
The last and first element are concatenated in one string:
[0]=> string(5) "12345"
...
[7]=> string(4) "0.04"
[8]=> string(19) "27-05-2013
"12346""
How can I fix this? Any help would be appreciated.
Do this:
$csvData = file_get_contents($fileName);
$lines = explode(PHP_EOL, $csvData);
$array = array();
foreach ($lines as $line) {
$array[] = str_getcsv($line);
}
print_r($array);
It will give you an output like this:
Array
(
[0] => Array
(
[0] => 12345
[1] => Computers
[2] => Acer
[3] => 4
[4] => Varta
[5] => 5.93
[6] => 1
[7] => 0.04
[8] => 27-05-2013
)
[1] => Array
(
[0] => 12346
[1] => Computers
[2] => Acer
[3] => 5
[4] => Decra
[5] => 5.94
[6] => 1
[7] => 0.04
[8] => 27-05-2013
)
)
I hope this can be of some help.
You should use fgetcsv. Since you cannot import a file as a stream because the csv is a variable, then you should spoof the string as a file by using php://temp or php://memory first:
$fp = fopen("php://temp", 'r+');
fputs($fp, $csvText);
rewind($fp);
Then you will have no problem using fgetcsv:
$csv = [];
while ( ($data = fgetcsv($fp) ) !== FALSE ) {
$csv[] = $data;
}
fclose($fp)
$data will be an array of a single csv line (which may include line breaks or commas, etc), as it should be.
Caveat: The memory limit of php://temp can be controlled by appending /maxmemory:NN, where NN is the maximum amount of data to keep in memory before using a temporary file, in bytes. (the default is 2 MB) http://www.php.net/manual/en/wrappers.php.php
Handy oneliner:
$csv = array_map('str_getcsv', file('data.csv'));
I have used following function to parse csv string to associative array
public function csvToArray($file) {
$rows = array();
$headers = array();
if (file_exists($file) && is_readable($file)) {
$handle = fopen($file, 'r');
while (!feof($handle)) {
$row = fgetcsv($handle, 10240, ',', '"');
if (empty($headers))
$headers = $row;
else if (is_array($row)) {
array_splice($row, count($headers));
$rows[] = array_combine($headers, $row);
}
}
fclose($handle);
} else {
throw new Exception($file . ' doesn`t exist or is not readable.');
}
return $rows;
}
if your csv file name is mycsv.csv then you call this function as:
$dataArray = csvToArray(mycsv.csv);
you can get this script also in http://www.scriptville.in/parse-csv-data-to-array/
A modification of previous answers using array_map.
Blow up the CSV data with multiple lines.
$csv = array_map('str_getcsv', explode("\n", $csvData));
Slightly shorter version, without unnecessary second variable:
$csv = <<<'ENDLIST'
"12345","Computers","Acer","4","Varta","5.93","1","0.04","27-05-2013"
"12346","Computers","Acer","5","Decra","5.94","1","0.04","27-05-2013"
ENDLIST;
$arr = explode("\n", $csv);
foreach ($arr as &$line) {
$line = str_getcsv($line);
}
If you need a name for the csv columns, you can use this method
$example= array_map(function($v) {$column = str_getcsv($v, ";");return array("foo" => $column[0],"bar" => $column[1]);},file('file.csv'));
If you have carriage return/line feeds within columns, str_getcsv will not work.
Try https://github.com/synappnz/php-csv
Use:
include "csv.php";
$csv = new csv(file_get_contents("filename.csv"));
$rows = $csv->rows();
foreach ($rows as $row)
{
// do something with $row
}
You can convert CSV string to Array with this function.
function csv2array(
$csv_string,
$delimiter = ",",
$skip_empty_lines = true,
$trim_fields = true,
$FirstLineTitle = false
) {
$arr = array_map(
function ( $line ) use ( &$result, &$FirstLine, $delimiter, $trim_fields, $FirstLineTitle ) {
if ($FirstLineTitle && !$FirstLine) {
$FirstLine = explode( $delimiter, $result[0] );
}
$lineResult = array_map(
function ( $field ) {
return str_replace( '!!Q!!', '"', utf8_decode( urldecode( $field ) ) );
},
$trim_fields ? array_map( 'trim', explode( $delimiter, $line ) ) : explode( $delimiter, $line )
);
return $FirstLineTitle ? array_combine( $FirstLine, $lineResult ) : $lineResult;
},
($result = preg_split(
$skip_empty_lines ? ( $trim_fields ? '/( *\R)+/s' : '/\R+/s' ) : '/\R/s',
preg_replace_callback(
'/"(.*?)"/s',
function ( $field ) {
return urlencode( utf8_encode( $field[1] ) );
},
$enc = preg_replace( '/(?<!")""/', '!!Q!!', $csv_string )
)
))
);
return $FirstLineTitle ? array_splice($arr, 1) : $arr;
}
Try this, it's working for me:
$delimiter = ",";
$enclosure = '"';
$escape = "\\" ;
$rows = array_filter(explode(PHP_EOL, $content));
$header = NULL;
$data = [];
foreach($rows as $row)
{
$row = str_getcsv ($row, $delimiter, $enclosure , $escape);
if(!$header) {
$header = $row;
} else {
$data[] = array_combine($header, $row);
}
}
Related
I need to read the content of a file called orders.log with PHP and use the variables. The log file is stored like this:
Array
(
[time] => 2099-99-99 00:00:00
[gateway] => Paypal
[gatewayOK] => Yes
[gatewayTransactionId] => XXXXXXX
[POST] => Array
(
[mc_gross] => 9.99
[protection_eligibility] => Eligible
[address_status] => confirmed
[payer_id] => XXXXX
[address_street] => XXXXX
[payment_date] => 00:00:00 Nov 11, 2018 PDT
[payment_status] => Completed
[charset] => windows-1252
)
)
I have tried reading it like this:
<?php
$orders=file_get_contents("orders.log");
echo $orders['time'];
echo $myarray[0]['gateway'];
echo $myarray[1]['mc_gross'];
?>
But the result does not work like intended. It throws "A" and "r" . Any help would be appreciated.
This assumes that each entry is 20 lines long, it reads in the log file and the splits it into 20 segments using array_chunk().
It then processes each segment, first splitting the lines by the => using explode() and adding the values to an associative array with the left hand side as the key. You can then use the key to access each value.
$input = file("log.txt", FILE_IGNORE_NEW_LINES);
$orders = array_chunk($input, 20);
foreach ( $orders as $order ) {
$split = [];
foreach ( $order as $line ) {
$info = explode("=>", $line);
if ( count($info) == 2){
$split[trim($info[0]," \t[]")] = trim ($info[1]);
}
}
echo "gateway-".$split['gateway'].PHP_EOL;
echo "mc_gross-".$split['mc_gross'].PHP_EOL;
}
If you wanted a list of all orders...
$input = file("log.txt", FILE_IGNORE_NEW_LINES);
$orders = array_chunk($input, 20);
$orderList = [];
foreach ( $orders as $order ) {
$split = [];
foreach ( $order as $line ) {
$info = explode("=>", $line);
if ( count($info) == 2){
$split[trim($info[0]," \t[]")] = trim ($info[1]);
}
}
$orderList[] = $split;
}
echo "gateway-".$orderList[0]['gateway'].PHP_EOL;
echo "mc_gross-".$orderList[0]['mc_gross'].PHP_EOL;
A third way which doesn't rely on the data being all the same format, this reads on a line by line basis and tries to work out the end of an element itself (just a line containing ))...
$fp = fopen("log.txt", "r");
$orderList = [];
$order = [];
while ( $line = fgets($fp)) {
// Remove extra data after content
$line = rtrim($line);
// If end of order (a line just starting with a ')')
if ( $line == ')' ) {
// Convert order into associative array
$split = [];
foreach ( $order as $line ) {
$info = explode("=>", $line);
if ( count($info) == 2){
$split[trim($info[0]," \t[]")] = trim ($info[1]);
}
}
// Add data to order list
$orderList[] = $split;
$order = [];
}
else {
// Add line to existing data
$order[] = $line;
}
}
print_r($orderList);
fclose($fp);
I have this sort of structure on a txt file.
[FILE_INFO]
[FIRST]
LOAD1= CPU
LOAD2 = RAM
[END_FIRST]
[GLOBAL_INDEX]
ELEC1=1235.12
GAZ2,1=1563.123
GAZ2,2= 28.56
[END_GLOBAL_INDEX]
[END_FILE_INFO]
What i need is to convert this txt structure to a php array , is this possible or txt structure is know ?
Array
(
[FILE_INFO] => Array
(
[FIRST] => Array
(
[LOAD1] => CPU
[LOAD2] => RAM
)
[GLOBAL_INDEX] => Array
(
[ELEC1] => 1235.12
[GAZ2] => Array
(
[1] => 1563.123
[2] => 28.56
)
)
)
)
Here is my approach:
$txt_file = file_get_contents("test.rt");
$rows = explode("\n", $txt_file);
$new_array = array(); $dimension = array();
foreach($rows as $row =>$data)
{
if($data[0] == "[" && substr($data, 0, 4) != "[END"){ // start
$output = str_replace( array('[',']') , '' , $data );
array_push($dimension, trim($output));
continue;
}else if(substr($data, 0, 4) == "[END"){ // end
$output = str_replace( array('[',']') , '' , $data );
array_pop($dimension);
continue;
}
$dim="";
foreach($dimension as $k=>$v){
$dim.= "['$v']";
}
$new_array.$dim[] = $data; // this is not working !!!!!
}
The problem is to position my cursor in the dimension of the array and insert the data
Try this:
<?php
$myfile = fopen("test.txt", "r");
// Iterate one line until end-of-file
while(!feof($myfile)) {
$text[] = fgets($myfile); // Add the data in an array
}
fclose($myfile);
print_r($text); // print the array
?>
I am new to PHP and working to get some results but failing to achieve my target. I have text file which contains data like this,
APAC|AU|enable|SYD1925|8|20150929|WORKING
APAC|AU|disable|ADL7235|3|20120123|RESIGNED
APAC|NZ|disable|NZ1356|6|20110123|RESIGNED
APAC|NZ|enable|NZ1356|3|20130123|WORKING
I am trying to search "AU" && "enable" for this text, line by line and I am a bit successful in it. Here is my Code example;
public function scan1()
{
$file = FCPATH.'uploads/example.txt';
// the following line prevents the browser from parsing this as HTML.
header('Content-Type: text/plain');
$search1 = "AU";
$search2 = "enable";
$lines = file($file);
foreach($lines as $line)
{
if(stristr($line,$search1) && stristr($line,$search2))
echo $line;
}
}
Now, I am trying to explode/split output data and assign variable / array to save in database but I am failing to do so, can someone please help or give me some direction to achieve this. Thank you
Please show us your_table scheme.
If '$db' is a handle of the db connection :
foreach($lines as $line)
{
if(stristr($line,$search1) && stristr($line,$search2))
{
$arr = explode("|", $line);
$query = "INSERT INTO your_table VALUES ('".$arr[0]."', '".$arr[1]."', '".$arr[2]."', '".$arr[3]."', '".$arr[4]."', '".$arr[5]."')";
$db->query($query);
}
}
First, obtain the file contents with file_get_contents:
$str = file_get_contents(FCPATH.'uploads/example.txt');
Then, use the regex (preg_match_all) to find all portion of text you're looking for:
preg_match_all("/APAC\\|(\w{2}\\|\w+)/", $str, $matches);
Then adapt the array so the 'AU' and 'enabled' are separated (array_map, explode):
$matches = array_map(function ($v) { return explode('|', $v); }, $matches[1]);
So, print_r($matches); returns:
Array
(
[0] => Array
(
[0] => AU
[1] => enable
)
[1] => Array
(
[0] => AU
[1] => disable
)
[2] => Array
(
[0] => NZ
[1] => disable
)
[3] => Array
(
[0] => NZ
[1] => enable
)
)
Finally, the foreach loop:
foreach($matches as $k => $kv)
{
$search1 = $kv[0]; // AU
$search2 = $kv[1]; // enabled
}
This works as expected:
public function scan1()
{
$file = FCPATH.'uploads/example.txt';
// the following line prevents the browser from parsing this as HTML.
header('Content-Type: text/plain');
$search1 = "AU";
$search2 = "enable";
$lines = file($file);
foreach($lines as $line)
{
if(strpos($line,$search1) !== false && strpos($line,$search2) !== false)
echo $line;
}
}
using strpos function for detection.
So I have this code:
<?php
$csv = array();
$lines = file('file.csv', FILE_IGNORE_NEW_LINES);
foreach ($lines as $key => $value)
{
$csv[$key] = str_getcsv($value);
}
echo '<pre>';
print_r($csv);
echo '</pre>';
?>
which gives me the following
[0] => Array
(
[0] => value1
[1] => value2
[2] => value3
[3] => value4
How can I name my keys? so I don't see 0-1-2-3 but Name1-Name2-Name3 etc.
Like This:
[0] => Array
(
[Name0] => value1
[Name1] => value2
[Name2] => value3
[Name3] => value4
function csvToArray($filename, $delimiter = ',') {
if (!file_exists($filename) || !is_readable($filename)) {
return FALSE;
}
$header = NULL;
$data = array();
if (($handle = fopen($filename, 'r')) !== FALSE) {
while (($row = fgetcsv($handle, 0, $delimiter)) !== FALSE) {
if (count($row) > 0 && !is_null($row[0])) {
if (!$header) {
$header = $row;
} else {
$data[] = array_combine($header, $row);
}
}
}
fclose($handle);
}
return $data;
}
Try this function
$filename is the full path to the file
also add in csv as first line keys you want to have and function will use this first line for keys
csv example:
"id","country","city"
"1","us","abanda"
"2","us","abbeville"
Now I understand!
All you need to do in this case is concatenate a string literal onto the front of the key that you generate, like this :-
<?php
$csv = array();
$lines = file('file.csv', FILE_IGNORE_NEW_LINES);
foreach ($lines as $key => $value)
{
$csv['Name'.$key] = str_getcsv($value);
}
echo '<pre>';
print_r($csv);
echo '</pre>';
?>
$keys = ['Name1', 'Name2', 'Name3', 'etc'];
$csv[$key] = array_combine($keys, str_getcsv($value));
This worked
Thanks Mark Baker
I'm having a problem with this. I have a string that looks like this:
coilovers[strut_and_individual_components][complete_strut][][achse]
And i want to convert it to to array that looks like this:
[coilovers] => Array
(
[strut_and_individual_components] => Array
(
[complete_strut]=> Array
(
[1] => Array
(
[achse] => some_value
)
[2] => Array
(
[achse] => some_value
)
)
)
)
is it possible?
Here is a quick implementation of a parser that will attempt to parse this string:
$input = 'coilovers[strut_and_individual_components][complete_strut][][achse]';
$output = array();
$pointer = &$output;
while( ($index = strpos( $input, '[')) !== false) {
if( $index != 0) {
$key = substr( $input, 0, $index);
$pointer[$key] = array();
$pointer = &$pointer[$key];
$input = substr( $input, $index);
continue;
}
$end_index = strpos( $input, ']');
$array_key = substr( $input, $index + 1, $end_index - 1);
$pointer[$array_key] = array();
$pointer = &$pointer[$array_key];
$input = substr( $input, $end_index + 1);
}
print_r( $output);
Essentially, we are iterating the string to find matching [ and ] tags. When we do, we take the value within the brackets as $array_key and add that into the $output array. I use another variable $pointer by reference that is pointing to the original $output array, but as the iteration goes, $pointer points to the last element added to $output.
It produces:
Array
(
[coilovers] => Array
(
[strut_and_individual_components] => Array
(
[complete_strut] => Array
(
[] => Array
(
[achse] => Array
(
)
)
)
)
)
)
Note that I've left the implementation of [] (an empty array key) and setting the values in the last index (some_value) as an exercise to the user.
Well I've found an another answer for it and it looks like this:
private function format_form_data(array $form_values) {
$reformat_array = array();
$matches = array();
$result = null;
foreach($form_values as $value) {
preg_match_all("/\[(.*?)\]/", $value["name"], $matches);
$parsed_product_array = $this->parse_array($matches[1], $value["value"]);
$result = array_push($reformat_array, $parsed_product_array);
}
return $result;
}
private function parse_array(array $values, $value) {
$reformat = array();
$value_carrier_key = end($values);
foreach (array_reverse($values) as $arr) {
$set_value_carrier = array($arr => $reformat);
if($arr == $value_carrier_key) {
$set_value_carrier = array($arr => $value);
}
$reformat = empty($arr) ? array($reformat) : $set_value_carrier;
}
return $reformat;
}
where array $form_values is:
Array
(
[name] => '[coilovers][strut_and_individual_components][complete_strut][][achse]',
[value] => 'some_value'
)
No. If you evaluate the string you will get invalid PHP.
If you want to store a PHP Array as string and get it loaded back as PHP Array, have a look at serialize and unserialize functions.
Of course you can build an array from your string, but you'll have to write a parser.
The solution I propose:
function format_form_data(array $data) {
$matches = array();
$result = [];
foreach($data as $key => $value) {
preg_match_all("/\[(.*?)\]/", $key, $matches);
$matches = array_reverse($matches[1]);
$matches[] = substr( $key, 0, strpos($key, '['));;
foreach ($matches as $match) {
$value = [$match=>$value];
}
$result = array_replace_recursive($result, $value);
}
return $result;
}