Consider the following snippet CSV data from "NASDAQ.csv"
"Symbol,""Name"",""LastSale"",""MarketCap"",""ADR TSO"",""IPOyear"",""Sector"",""industry"",""Summary Quote"",";;
"FLWS,""1-800 FLOWERS.COM, Inc."",""2.9"",""81745200"",""n/a"",""1999"",""Consumer Services"",""Other Specialty Stores"",""http://www.nasdaq.com/symbol/flws"",";;
"FCTY,""1st Century Bancshares, Inc"",""4"",""36172000"",""n/a"",""n/a"",""Finance"",""Major Banks"",""http://www.nasdaq.com/symbol/fcty"",";;
"FCCY,""1st Constitution Bancorp (NJ)"",""8.8999"",""44908895.4"",""n/a"",""n/a"",""Finance"",""Savings Institutions"",""http://www.nasdaq.com/symbol/fccy"",";;
I'm trying to import Symbol, Sector, and Industry into a MySQL table with corresponding fields:
$path = "NASDAQ.csv";
$row = 1;
if (($handle = fopen($path, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$row++;
$entries[] = $data ;
}
fclose($handle);
}
foreach ($entries as $line) {
db_query("
INSERT INTO us_stocks (symbol, name, sector, industry)
VALUES ('%s', '%s', '%s', '%s', '%s')",
$line[0], $line[1], $line[6], $line[7]
);
}
The result, however, is not what I expected. In the database, only the Symbol field gets filled, and not even correctly:
symbol name sector industry
----------------------------------
Symbol,"Na
FLWS,"1-80
FCTY,"1st
FCCY,"1st
What am I doing wrong?
[edit]
If I print_r($entries), the output looks like
Array (
[0] => Array(
[0] => Symbol,"Name","LastSale","MarketCap","ADR TSO","IPOyear","Sector","industry","Summary Quote",;;
)
[1] => Array(
[0] => FLWS,"1-800 FLOWERS.COM, Inc.","2.9","81745200","n/a","1999","Consumer Services","Other Specialty Stores","http://www.nasdaq.com/symbol/flws",;;
)
[2] => Array(
[0] => FCTY,"1st Century Bancshares, Inc","4","36172000","n/a","n/a","Finance","Major Banks","http://www.nasdaq.com/symbol/fcty",;;
)
)
[edit2]
I have deleted the first line of the CSV, as suggested. I now have a very quick and dirty way of almost accomplishing what I want. Basically, the thing messes up whenever there's a company name with ", Inc" in it. So I just "glue" it to the name above: $data[1] = $data[1] . $data[2]:
$path = "NASDAQ.csv";
$row = 1;
if (($handle = fopen($path, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ";;")) !== FALSE) {
if ($row < 100) {
$row++;
$data = explode(',', $data[0]);
if (substr($data[2], 0, 1) == ' ') {
$data[1] = $data[1] . $data[2];
unset($data[2]);
}
$entries[] = $data ;
}
}
fclose($handle);
}
A print_r($entries) now gives:
[0] => Array
(
[0] => FLWS
[1] => "1-800 FLOWERS.COM Inc."
[3] => "2.9"
[4] => "81745200"
[5] => "n/a"
[6] => "1999"
[7] => "Consumer Services"
[8] => "Other Specialty Stores"
[9] => "http://www.nasdaq.com/symbol/flws"
[10] =>
)
Final problem: I don't know how to renumber the keys. So 3 into 2, 4 into 3, etc. so that the output looks like:
[0] => Array
(
[0] => FLWS
[1] => "1-800 FLOWERS.COM Inc."
[2] => "2.9"
[3] => "81745200"
[4] => "n/a"
[5] => "1999"
[6] => "Consumer Services"
[7] => "Other Specialty Stores"
[8] => "http://www.nasdaq.com/symbol/flws"
[9] =>
)
Any help would be greatly appreciated!
I'd say the data isn't "truely" CSV.
"FLWS,""1-800 FLOWERS.COM, Inc."",""2.9"",
should be :
"FLWS","1-800 FLOWERS.COM, INC.","2.9" - The quotes should wrap the individual fields with commas seperating each field. Usually numeric fields are not wrapped.
Depending on how you load the data, comma's in the data may confuse it. (i.e. the FLOWERS.COM, INC"
By the way - if it's really CSV - look at: http://dev.mysql.com/doc/refman/5.1/en/load-data.html
As Crontab said, probably it's a problem with quotes. Try:
foreach ($entries as $line) {
// Escape (see mysql_real_escape_string too) and remove double quotes
foreach ($line as $k => $v) $line[$k] = mysql_escape_string(trim($v, '"'));
// Rebuild array
$line = array_values($line);
db_query("
INSERT INTO us_stocks (symbol, name, sector, industry)
VALUES ('%s', '%s', '%s', '%s', '%s')",
$line[0], $line[1], $line[6], $line[7]
);
}
PS: I don't know if you already escape strings in db_query().
Related
I know there are a lot of topics about this, but just couldn't find any that would actually help me solve the problem.
Ok so i am having a problem with counting rows and values in multidimensional array (imported via .csv)
I am trying to achieve something like...
Array ( [0] => Array ( [0] => 1 [1] => 6278,31 [2] => 4)
[1] => Array ( [0] => 2 [1] => 2,0 [2] => 2)
[2] => Array ( [0] => 3 [1] => 3,01 [2] => 3)
)
where [0] would be buyer id, 1 is total number of buys and [2] total cost.
My current code:
if(($s_open = fopen("sales.csv", "r")) !== FALSE)
{
$s_count = count(file("sales.csv"));
while(($sales = fgetcsv($s_open, 100, ";")) !== FALSE)
{
...
}
fclose($s_open);
}
Thanks in advance.
You could group your data by creating an array with the buyer_id as index.
Each time you find a new buyer, you could create a small array ('id','count','amount').
Then, sum the values of the current row into that array.
const KEY_ID = 0; // shortcut for array indexes
const KEY_AMOUNT = 1;
const KEY_COUNT = 2;
$buyers = []; // final array
if (($s_open = fopen("sales.csv", "r")) !== FALSE)
{
$s_count = count(file("sales.csv"));
while(($sales = fgetcsv($s_open, 100, ";")) !== FALSE)
{
// Extract data from row:
[$id, $buyer_id, , $amount] = $sales;
// If the buyer doesn't exists in the array,
// create a new array with required format:
if (!isset($buyers[$buyer_id])) {
$buyers[$buyer_id] = [
KEY_ID => $buyer_id,
KEY_COUNT => 0,
KEY_AMOUNT => 0,
];
}
// Update values:
$buyers[$buyer_id][KEY_COUNT]++;
$buyers[$buyer_id][KEY_AMOUNT] += $amount;
}
fclose($s_open);
}
// Re-index values:
$buyers = array_values($buyers);
Using this mock data in.csv:
id, buyer_id, amount
1, 1, 100.55
2, 1, 500.1
3, 2, 50.55
4, 3, 1.0
I wrote the following PHP to parse it into a nicely formatted array (if you don't want to have named keys, you can just remove the header logic):
<?php
// Each line into an array
$csv = file(__DIR__ . DIRECTORY_SEPARATOR . 'in.csv');
// First line is the header
$header = str_getcsv(array_shift($csv));
// When the CSV header is `id, buyer_id, amount`, remove the whitespace
$header = array_map(function ($item) {
return trim($item);
}, $header);
// Get the CSV data as an array of arrays
$out = array_map(function ($line) use ($header) {
$data = str_getcsv($line);
return array_combine($header, $data);
}, $csv);
print_r($out);
Which prints the following to your screen:
Array
(
[0] => Array
(
[id] => 1
[buyer_id] => 1
[amount] => 100.55
)
[1] => Array
(
[id] => 2
[buyer_id] => 1
[amount] => 500.1
)
[2] => Array
(
[id] => 3
[buyer_id] => 2
[amount] => 50.55
)
[3] => Array
(
[id] => 4
[buyer_id] => 3
[amount] => 1.0
)
)
Try this
$data = [];
if(($s_open = fopen("sales.csv", "r")) !== FALSE) {
$s_count = count(file("sales.csv"));
while( ([$id, $buyer_id, $amount] = fgetcsv($s_open, 100, ";")) !== FALSE ){
if( $id !== 'id' ){
$data[$buyer_id] = [
$buyer_id,
($data[$buyer_id][1] ?? 0) + 1,
($data[$buyer_id][2] ?? 0) + $amount
];
}
}
fclose($s_open);
$data = array_values($data);
}
// print_r($data);
I have a giant list in excel, they are just two columns
name type
The file is currently being read:
$lines = array_map('str_getcsv', file('file.csv', FILE_IGNORE_NEW_LINES));
print_r($lines); returns:
name1;type
name2;type2
...
Array ( [0] => Array ( [0] => name1;type1) [1] => Array ( [0] => name2;type2)...
I would like to access separate name and type in an foreach
How can I do this?
Thanks
str_getcsv default delimiter is ',' so you need call it somehow with explicitly specifying ';' as delimeter
for example like this
$myGetCsv = function ($str) {
return str_getcsv($str, ';');
};
$lines = array_map($myGetCsv, file('file.csv', FILE_IGNORE_NEW_LINES));
Use this code for CSV file reading. it ease to use and understand how its work.
if (($handle = fopen('./suppression_invalid_emails.csv', "r")) !== false) {
//getting column name
$column_headers = fgetcsv($handle);
foreach ($column_headers as $header) {
//column as array;
$result[$header] = array();
}
// get data for column;
while (($data = fgetcsv($handle)) !== false) {
$i = 0;
foreach ($result as &$column) {
$column[] = $data[$i++];
}
}
fclose($handle);
echo '<pre>'; print_r($result); echo '</pre>';
}
i use two basic function for this 1st one is fopen for reading file and other is fgetcsv for getting data for column.
and result is:
Array
(
[reason] => Array
(
[0] => Mail domain mentioned in email address is unknown
[1] => Known bad domain
[2] => Known bad domain
)
[email] => Array
(
[0] => muneque#collegeclub.om
[1] => saharfa2000#hatmail.com
[2] => tawheeda81#yahoo.co
)
[created] => Array
(
[0] => 1502644294
[1] => 1502480171
[2] => 1502344320
)
)
How can i do a foreach with a CSV file.
Suppose i have fopen a csv file which looks like so ---
Array
(
[0] => Category ID
[1] => Category
[2] => Country
[3] => Original price
[4] => Reduce price
)
Array
(
[0] => 11
[1] => Phone cases
[2] => Denmark
[3] => 90,99
[4] => 120
)
Array
(
[0] => 13
[1] => Shoes
[2] => Denmark
[3] => 180,99
[4] => 200
)
So how can i loop through all the data's in store them in a array.
I have tried like so, but it does not work.
$all_data = array();
foreach ($result as $key => $obj) {
$doc = array();
$doc['id'] = $obj[$key];
$doc['category'] = $obj[$key];
$doc['country'] = $obj[$key];
$doc['original_price'] = $obj[$key];
$doc['reduce_price'] = $obj[$key];
// array push all documents into $all_data
$all_data [] = $doc;
}
Anyone knows how i can loop through those data!
Just using the PHP documentation :
if (($handle = fopen("yourfile.csv", "r")) !== FALSE) {
$all_data = array();
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if($i==0){ continue; $i=1; }
// Remove the first iteration as it's not "real" datas
$all_data[] = array(
'id' => $data[0],
'category' => $data[1],
'country' => $data[2],
'original_price' => $data[3],
'reduce_price' => $data[4],
);
}
fclose($handle);
}
It must achieve what you want. It's always better using the built-in functions. If you can't use this one, let me know.
EDIT :
As #Blag said :
you can use to file_get_contents() and str_getcsv()
But this is a different approach that'll load the full file in a string (file_get_contents) and parse the string in the second time (str_getcsv).
This should give you an idea of how to proceed :
$objsOut=array();
foreach ($result as $key => $obj) {
$objOut = array(
'id'=>$obj[0]
);
$objsOut[]=$objOut;
}
I have the following csv file:
"Id","Title","Body","Tags"
"101","this title","
\"">.</>"";
","c# asp.net excel table"
which I want to convert into an array as follows:
Array
(
[0] => Array
(
[0] => Id
[1] => Title
[2] => Body
[3] => Tags
)
[1] => Array
(
[0] => 101
[1] => this title
[2] => \"">.</>"";
[3] => c# asp.net excel table
)
)
My code is:
while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
$num = count($data);
for ($c=0; $c < $num; $c++) {
$data[$c] = strip_tags($data[$c]);
}
$result[$row] = $data;
$row++;
}
fclose($handle);
return $result;
My problem is I am getting the following array:
Array
(
[0] => Array
(
[0] => Id
[1] => Title
[2] => Body
[3] => Tags
)
[1] => Array
(
[0] => 101
[1] => this title
[2] =>
\">.</>"";
)
[2] => Array
(
[0] => ,c# asp.net excel table"
)
)
In general, how do I avoid detecting too many recors when there is potentially code inside the fields (it's a StackOverflow data dump so some text fields have all kinds of programming code).
This string is not correctly escaped:
"
\"">.</>"";
"
All quote chars must have backslashes before them (or other escape char that you've passed into appropriate param.
And you should't pass 0 and comma to fgetcsv, they are already default: http://php.net/fgetcsv
Try opening the file using CSVed to make sure that it was properly formatted as CSV.
If the CSV is broken, then you can do some quick fix to the parsed result. For example:
while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
$num = count($data);
for ($c=0; $c < $num; $c++) {
$data[$c] = strip_tags($data[$c]);
}
if (count($data) == 3) {
$data[1][2] .= $data[2].[0];
unset($data[2]);
}
$result[$row] = $data;
$row++;
}
fclose($handle);
return $result;
I am importing data from csv file so I used that code
<?php
$path = "Export.csv";
$row = 1;
if (($handle = fopen($path, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$row++;
$data_entries[] = $data ;
}
fclose($handle);
}
echo"<pre>";
print_r($data_entries);
echo"</pre>";
?>
and my array output like that my first array showing column names after that all array showing value so i want to insert value base on first array column names
Array
(
[0] => Array
(
[0] => Type
[1] => PinCode
[2] => APN
[3] => County
)
[1] => Array
(
[0] => Auction
[1] => 503082537
[2] => 502-052-002
[3] => United States of America
)
[2] => Array
(
[0] => Auction
[1] => 21596378
[2] => 628-202-038
[3] => Australia
)
)
Try the below code :
//extract the column names
$fields = array_shift($data_entries);
$values = array();
// Append the values
foreach($data_entries as $value){
$values[]="('{$value[0]}', '{$value[1]}', '{$value[2]}', '{$value[3]}' )";
}
// Build the SQL
$sql = "INSERT INTO `TABLE_NAME` (" . implode(',' , $fields) . ") values " . implode(',', $values);
You might try a different approach, since your data is coming from a CSV file.
LOAD DATA LOCAL INFILE 'Export.csv' INTO TABLE YourTable;
There are many options, read the manual: http://dev.mysql.com/doc/refman/5.0/en/load-data.html