I have a file and I need the save the content of the file in my MySQL database. Here is the code that I am using to parse the file:
$lines = file($tmp_filename);
$data = array();
if (($handle = fopen($tmp_filename, 'r')) !== FALSE)
{
while (($row = fgetcsv($handle, 1000, ";", "\"", "\n")) !== FALSE)
{
$key = array_shift($row);
$data[$key] = $row;
}
fclose($handle);
}
and here are the contents of the file that I am parsing:
HDR;Payroll Interface;5496;2012-07-20
NM1;082;IN2;12345678;2001-01-15;Mr;Marcial;Gustav;Gustav,Marcial;PRI;Marcial
PR1;082;IN2;12345678;7 The School;Alvarez;Bahaghari; ;Gandum
PR2;082;IN2;12345678;400006;IND;M;M;2007-10-16;1976-03-31
PR3;082;IN2;12345678; ; ;A;
**truncated**
Click Here for full data
There are scenarios where the array has the same index and the same value but I still need to save these data but array overwriting occurs. What must be added to put the same array to a different array index?
Take a look at this and tell me what i am missing
The data in the array is being overwritten because you are reassigning the value of $key each time it is encountered.
What you want to do is create a secondary array as the $key value and push nodes into that array this way you end up with your expected result.
[
'NM1' => ['...', '...'],
'PR1' => ['...', '...']
]
The code would be,
while (($row = fgetcsv($handle, 1000, ";", "\"", "\n")) !== FALSE) {
$key = array_shift($row);
// Notice the extra []
$data[$key][] = $row;
}
Each key will now contain an array with a node for each row encountered.
try changing:
...
$data[$key] = $row;
to
...
$data[][$key] = $row;
Related
I am currently doing the below in PHP; to convert a CSV file to usable JSON. This is working.... however,
$tmpName = $_FILES['csv']['tmp_name'];
move_uploaded_file($tmp_name, "/files/locations/");
$fh = fopen($tmpName, "r");
$csvData = array();
$keys = fgetcsv($fh, 0, ",");
while (($row = fgetcsv($fh, 0, ",")) !== FALSE) {
$csvData[] = array_combine($keys, $row);
}
// echo json_encode($csvData);
file_put_contents("/files/locations/locations.json",json_encode($csvData))
It is outputting the JSON like this:
{"Zipcode":"90210","City":"Something","Primary State":"Utah","County Code":"49530","County":"Loudoun"}
I would like the Zipcode field and it's value to be the header. So, like below, so I can use the Zipcode value as the ID of the data set. Is this possible?
{
"Zipcode":"90210": {
"City":"Something",
"Primary State":"Utah",
"County Code":"49530",
"County":"Loudoun"
}
Instead of pushing the row onto the array, assign to an array key.
$csvData[$row[0]][] = array_combine($keys, $row);
This assumes the zip code is in the first field in the row (as it appears to be from your example of the original JSON).
Using [] makes each zip code entry an array of locations. So the result will look like:
{ "90210": [
{
"Zipcode": "90210",
"City":"Something",
"Primary State":"Utah",
"County Code":"49530",
"County":"Loudoun"
}]
}
If you don't want the zip code to be redundantly included in the array elements, you can remove it from the key and values.
$keys = array_slice($keys = fgetcsv($fh, 0, ","), 1);
and
$zip = array_shift($row);
$csvData[$zip][] = array_combine($keys, $row);
I have this big file containing SWIFT numbers and bank names. I'm using the following php function for reading and comparing data:
function csv_query($blz) {
$cdata = -1;
$fp = fopen(DIR_WS_INCLUDES . 'data/swift.csv', 'r');
while ($data = fgetcsv($fp, 1024, ",")) {
if ($data[0] == $blz){
$cdata = array ('blz' => $data[0],
'bankname' => $data[7]);
// 'prz' => $data[2]
}
}
return $cdata;
}
The csv files looks like that:
"20730054",1,"UniCredit Bank - HypoVereinsbank (ex VereinWest)","21423","Winsen (Luhe)","UniCredit Bk ex VereinWest",,"HYVEDEMM324","68","013765","M",1,"20030000"
"20750000",1,"Sparkasse Harburg-Buxtehude","21045","Hamburg","Spk Harburg-Buxtehude","52002","NOLADE21HAM","00","011993","U",0,"00000000"
"20750000",2,"Sparkasse Harburg-Buxtehude","21605","Buxtehude","Spk Harburg-Buxtehude","52002",,"00","011242","U",0,"00000000"
As you can see from the code, I need the first and the eight string. If the first string has no duplicates everything is ok, but if it has, most likely the eighth field of the duplicate will be empty and I get no result back. So I want to ask how to display that eighth field of the first result if the line has a duplicate.
I guess this will solve your problem :
function csv_query($blz) {
$cdata = -1;
$fp = fopen(DIR_WS_INCLUDES . 'data/swift.csv', 'r');
$counter = 0; // add this line
while ($data = fgetcsv($fp, 1024, ",")) {
if ($data[0] == $blz && !$counter) { //change this line
$cdata = array(
'blz' => $data[0],
'bankname' => $data[7]
);
$counter++; //add this line
}
}
return $cdata;
}
I am using this code to process an uploaded csv file. How do I convert it to Json and loop through to display on a user's screen?
if (($handle = fopen('upload/'.$current.$_FILES["file"]["name"]. '', "r")) !== FALSE) {
while (($row_array = fgetcsv($handle, 1024, ","))) {
foreach ($row_array as $key => $val) {
$row_array[$key] = trim(str_replace('"', '', $val));
}
$complete[] = $row_array;
}
fclose($handle);
}
You should encode your array to json using
json_encode($complete);
Then you will need to iterate that array using javascript on client side.
I know there are a lot of resources out there for putting a CSV into an associative array, but I can't find anything that helps a noob like me do exactly what I want to do.
I currently have an associative array defined inside my PHP file:
$users = array(
'v4f25' => 'Stan Parker',
'ntl35' => 'John Smith',
);
I would like to move that array into a CSV file (users.txt) so:
v4f25, Stan Parker
ntl35, John Smith
The next step is to import users.txt so I can use it precisely like I was using the array $users.
Any help here? The last code I tried returned this: (which is not what I want)
array(2) {
["v4f25"]=>
string(5) "ntl35"
["Stan Parker"]=>
string(10) "John Smith"
}
What about the following?
$data = array();
if ($fp = fopen('csvfile.csv', 'r')) {
while (!feof($fp)) {
$row = fgetcsv($fp);
$data[$row[0]] = $row[1];
}
fclose($fp);
}
$users = array(
'v4f25' => 'Stan Parker',
'ntl35' => 'John Smith',
);
$fp = fopen('users.txt', 'w');
if ($fp) {
foreach ($users as $key => $value) {
fputcsv($fp, array($key, $value));
}
fclose($fp);
} else {
exit('Could not open CSV file')
}
See: fputcsv()
UPDATE - in the comments you're interested in how to read the file and get your users back out. Here's the return trip:
$users = array();
if (($handle = fopen("my-csv-file.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$users[$data[0]] = $data[1];
}
fclose($handle);
} else {
exit('Could not open CSV file');
}
if (count($users) == 0) {
exit('CSV file empty: no users found');
}
Here's a solution using fputcsv() which flattens the key/value pairs to an array before writing to disk.
$filehandle = fopen("csvfile.csv", "w");
if ($filehandle) {
foreach ($users as $key => $value) {
fputcsv($filehandle, array($key, $value);
}
fclose($filehandle);
}
else // couldn't open file
Try this (assuming your strings contain no commas):
$users = array(
'v4f25' => 'Stan Parker',
'ntl35' => 'John Smith',
);
foreach ($users as $k => $v) {
print "$k, $v\n";
}
Obviously you could then create the CSV file like so:
php above_script.php > outfile.csv
Now, to get from CSV back into an array you could use something like:
$file = 'outfile.csv';
$arr = array();
if (file_exists($file)) {
foreach (explode("\n", file_get_contents($file)) as $l) {
list($k, $v) = explode(',', $l);
$arr[trim($k)] = trim($l);
}
}
print_r($arr, true);
NOTES:
If your strings do (or might) contain commas, then you'll probably want to use a PHP builtin function to decode them - in which case the answers by harald and artlung are useful.
RFC 4180 describes how commas (and other values) are encoded in CSV, in case you want to roll your own CSV encoding/decoding functions for whatever reason.
I've seen numerous examples on how to take a CSV file and then create an associative array with the headers as the keys.
For example:
Brand,Model,Part,Test
Honda,Civic,123,244
Honda,Civic,135,434
Toyota,Supra,511,664
Where it would create an Array such as Array[$num][$key] where $key would be Brand, Model, Part, Test.
So If I wanted to access the test value "434" I would have to loop every index in the array and then ignore any Brands that were not honda, and any models that were not Civic
What I need to do is access the value most directly, instead of running through a for loop going through each $num index. I want to be able to access the value test "434" with:
Array['Honda']['Civic']['135']
or control a for statement with looping through every model Honda has... something like
foreach $model in Array['Honda']
At the very least I need to be able to go through every model given a known Brand and access all the relative info for each.
Edit:
Just to confirm I was setting this up an example. My actually data has headers like:
brand model part price shipping description footnote
Of which I need to access all the information tied to the part (price, shipping,desc, footnote)
Too many long solutions. I've always found this to be the simplest:
<?php
/* Map Rows and Loop Through Them */
$rows = array_map('str_getcsv', file('file.csv'));
$header = array_shift($rows);
$csv = array();
foreach($rows as $row) {
$csv[] = array_combine($header, $row);
}
?>
run over the csv file line by line, and insert to array like:
$array = $fields = array(); $i = 0;
$handle = #fopen("file.csv", "r");
if ($handle) {
while (($row = fgetcsv($handle, 4096)) !== false) {
if (empty($fields)) {
$fields = $row;
continue;
}
foreach ($row as $k=>$value) {
$array[$i][$fields[$k]] = $value;
}
$i++;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
To create an associative list array use something like:
$keys = fgetcsv($f);
while (!feof($f)) {
$array[] = array_combine($keys, fgetcsv($f));
}
And to traverse and filter by specific attributes write a function like:
function find($find) {
foreach ($array as $row) {
if (array_intersect_assoc($row, $find) == $find) {
$result[] = $row;
}
}
}
Where you would invoke it with $find = array(Brand=>Honda, Model=>Civic, Part=>135) to filter out the searched models. The other positional array structure seems not very workable, unless you only want to access the "Test" attribute.
Try this simple algorithm:
$assocData = array();
if( ($handle = fopen( $importedCSVFile, "r")) !== FALSE) {
$rowCounter = 0;
while (($rowData = fgetcsv($handle, 0, ",")) !== FALSE) {
if( 0 === $rowCounter) {
$headerRecord = $rowData;
} else {
foreach( $rowData as $key => $value) {
$assocData[ $rowCounter - 1][ $headerRecord[ $key] ] = $value;
}
}
$rowCounter++;
}
fclose($handle);
}
var_dump( $assocData);
Using fgetcsv() seems the most direct and sensible tool for the job.
csv.csv contents:
Brand,Model,Part,Test
Honda,Civic,123,244
Honda,Civic,135,434
Toyota,Supra,511,664
Code:
$assoc_array = [];
if (($handle = fopen("csv.csv", "r")) !== false) { // open for reading
if (($data = fgetcsv($handle, 1000, ",")) !== false) { // extract header data
$keys = $data; // save as keys
}
while (($data = fgetcsv($handle, 1000, ",")) !== false) { // loop remaining rows of data
$assoc_array[] = array_combine($keys, $data); // push associative subarrays
}
fclose($handle); // close when done
}
echo "<pre>";
var_export($assoc_array); // print to screen
echo "</pre>";
Output:
array (
0 =>
array (
'Brand' => 'Honda',
'Model' => 'Civic',
'Part' => '123',
'Test' => '244',
),
1 =>
array (
'Brand' => 'Honda',
'Model' => 'Civic',
'Part' => '135',
'Test' => '434',
),
2 =>
array (
'Brand' => 'Toyota',
'Model' => 'Supra',
'Part' => '511',
'Test' => '664',
),
)
Resource: http://php.net/manual/en/function.fgetcsv.php
Here is a solutions that will work by specifying a local file or URL. You can also switch the association on and off. Hopefully this helps.
class CSVData{
public $file;
public $data;
public $fp;
public $caption=true;
public function CSVData($file=''){
if ($file!='') getData($file);
}
function getData($file){
if (strpos($file, 'tp://')!==false){
copy ($file, '/tmp/csvdata.csv');
if ($this->fp=fopen('/tmp/csvdata.csv', 'r')!==FALSE){
$this->readCSV();
unlink('tmp/csvdata.csv');
}
} else {
$this->fp=fopen($file, 'r');
$this->readCSV();
}
fclose($this->fp);
}
private function readCSV(){
if ($this->caption==true){
if (($captions=fgetcsv($this->fp, 1000, ","))==false) return false;
}
$row=0;
while (($data = fgetcsv($this->fp, 1000, ",")) !== FALSE) {
for ($c=0; $c < count($data); $c++) {
$this->data[$row][$c]=$data[$c];
if ($this->caption==true){
$this->data[$row][$captions[$c]]=$data[$c];
}
}
$row++;
}
}
}
Try this usage:
$o=new CSVData();
$o->getData('/home/site/datafile.csv');
$data=$o->data;
print_r($data);
Here is my solution, similar to others stated but uses a while loop with fgetcsv, and uses a counter and array_combine to set the first row as the keys.
$rownum = 0;
while (($row = fgetcsv($openedFile, 1000, ',')) !== FALSE) {
if ($rownum > 0) {
$row = array_combine($importarray[0], $row);
}
array_push($importarray, $row);
$rownum++;
}
array_shift($importarray);