Country.csv
this is countries.csv file, and i want to extract all the timezones from it, which is its 14th colomn, and the data in there is not properly json formatted. I'm trying to parse the json but it failed. Actually, I want to create an array of timezones like this
[0] => {zoneName:'Asia -> Kabul',gmtOffset:16200,gmtOffsetName:'UTC+04:30',abbreviation:'AFT',tzName:'Afghanistan Time'}
[1] => {zoneName:'Europe -> Mariehamn',gmtOffset:7200,gmtOffsetName:'UTC+02:00',abbreviation:'EET',tzName:'Eastern European Time'}
[2] => {zoneName:'Europe -> Tirane',gmtOffset:3600,gmtOffsetName:'UTC+01:00',abbreviation:'CET',tzName:'Central European Time'}
[3] => {zoneName:'Africa -> Algiers',gmtOffset:3600,gmtOffsetName:'UTC+01:00',abbreviation:'CET',tzName:'Central European Time'}
[4] => {zoneName:'Pacific -> Pago_Pago',gmtOffset:-39600,gmtOffsetName:'UTC-11:00',abbreviation:'SST',tzName:'Samoa Standard Time'}
[5] => {zoneName:'Europe -> Andorra',gmtOffset:3600,gmtOffsetName:'UTC+01:00',abbreviation:'CET',tzName:'Central European Time'}
[6] => {zoneName:'Africa -> Luanda',gmtOffset:3600,gmtOffsetName:'UTC+01:00',abbreviation:'WAT',tzName:'West Africa Time'}
what i'm doing, is this in App\Http\Controllers\TestController::class is this
public function timezone(): void {
$data = [];
if (($open = fopen(__DIR__ . '/countries.csv', 'r + b')) !== FALSE) {
while (($singleRecord = fgetcsv($open, NULL, ',')) !== FALSE) {
$data[] = $singleRecord;
}
fclose($open);
}
$data = $this->removeCharacters($data, ['[', ']']);
$data = $this->removeCharacters($data, (array)'\/', " -> ");
// $data = $this->removeCharacters($data, (array)'{}', '');
// dd(explode('},', $data[33][14]));
// dd(explode('},', $this->longJson));
// dd(explode(',', str_replace(['{', '}'], '', $data[167][14])));
$singleArray = [];
$count = count($data);
$itemsArray = [];
for ($i = 1; $i < $count; $i++) {
$singleArray[] = explode('},', $data[$i][14]);
foreach ($singleArray as $item) {
foreach ($item as $singleItem) {
$itemsArray[] = $singleItem;
}
}
}
$itemsArray = array_unique($itemsArray);
$this->printFormattedData($itemsArray);
}
private function removeCharacters($hayStack, array $charsArray, $character = ''): array {
$tempArray = [];
foreach ($hayStack as $item) {
$tempArray[] = str_replace($charsArray, $character, $item);
}
return $tempArray;
}
private function printFormattedData($data): void {
echo '<pre>';
print_r($data);
echo '</pre>';
}
Using regexp its not perfect solution, but you can transform timezone data to correct json format using function like this:
public function fixJson(string $str): string {
return preg_replace(
'/(?<=(\{|\,))(\w+)(?=\:)/',
'"$2"',
str_replace("'", '"', $zoneRaw) // may not work properly, if values may contain apostroph symbols, but seems not actual for your case
);
}
So, use this function:
$this->fixJson($data[$i][14]); // returns json string
json_decode($this->fixJson($data[$i][14])); // returns json decoded array
See usage example here https://sandbox.onlinephpfunctions.com/c/88f21
Following code would do, what you aim.
Please do not forget to mark this answer as ACCEPTED and thumbs up if it solves your problem, so that the work of the developers who help is appreciated and other developers can see in question list, that your question has already an accepted answer.
$lines = file("countries.csv");
array_shift($lines); // remove the first line with column names
$searchReplace = ['\/' => '->'];
$search = array_keys($searchReplace);
$replace = array_values($searchReplace);
$jsonFormattedTimeZones = [];
foreach($lines as $line)
{
$line = trim(str_getcsv($line)[14], " []");
$line = str_replace($search, $replace, $line);
$jsonFormattedTimeZones[] = $line;
}
print_r($jsonFormattedTimeZones);
I have this text file that I want to read and check if the value is correct or not and then display in html file:
Audi, 2006
BMW, 2019 //date incorrect
Toyota, 2016
Frd, 2017 //name incorrect
All I did till now is:
$handle = file('src/can.txt');
$data = array();
//loop to get the value from handle
foreach ($handle as $key ) {
array_push($data, $key);
}
I wanted to continue using another loop where I create 2 array and then using explode method to separate the name of the car from the year of production.
My question is: is there any build in php method or any better way to perform the same operation?
I would suggest to use method for repeating action. Here is an example and suggest you to handle the case-senitivity of brands/makes.
I would also keep the array index for easy reference.
<?php
class File {
private $_minYear = 2000,
$_maxYear = 2018,
$_brand = array('BMW','Audi','Toyota','Ford');
private function validateYear($year) {
$year = (int)$year;
return ($this->_minYear < $year && $year < $this->_maxYear);
}
public function scan($file) {
$lines = file($file);
foreach ($lines as $key => $value) {
$data = explode(',',$value);
if (in_array($data[0], $this->_brand) && $this->validateYear($data[1])) {
$records[$key] = $value;
} else {
$errors[$key] = $value;
}
}
return array('records' => $records, 'errors' => $errors);
}
}
$file = new File;
$data = $file->scan('testcar.txt');
echo '<pre>';
print_r($data['records']);
print_r($data['errors']);
OUTPUT:
Array
(
[0] => Audi, 2006
[2] => Toyota, 2016
)
Array
(
[1] => BMW, 2019
[3] => Frd, 2017
)
Without using Class/Method
<?php
$brands = array('BMW','Audi','Toyota','Ford');
function validateYear($year) {
$year = (int)$year;
return (2000 < $year && $year < 2018);
}
function fileScan($file) {
$lines = file($file);
foreach ($lines as $key => $value) {
$data = explode(',',$value);
if (in_array($data[0], $brands) && validateYear($data[1])) {
$records[$key] = $value;
} else {
$errors[$key] = $value;
}
}
return array('records' => $records, 'errors' => $errors);
}
$data = fileScan('testcar.txt');
echo '<pre>';
print_r($data['records']);
print_r($data['errors']);
ok..I'm trying to re-map the keynames of a key-value array in php using a fieldmap array ie.
i want the $outRow array to hold $inRow['name1'] = 10 to $outRow['name_1'] = 10 for a large set of pre-mapped values..
$fieldmap=array("name1"=>"name_1","name2"=>"name_2");
private function mapRow($inRow) {
$outRow = array();
foreach($inRow as $key => $value) {
$outRow[$this->fieldmap[$key]][] = $value;
}
return $outRow;
} // end mapRow
public function getListings($inSql) {
// get data from new table
$result = mysql_query($inSql);
if (!result) {
throw new exception("retsTranslate SQL Error: $inSql");
}
while ($row = mysql_fetch_assoc($result)) {
$outResult[] = $this->mapRow($row);
}
return $outResult;
} // end getListings
this is not working..I'm getting the array but its using $outResult[0][keyname]...I hope this is clear enough :)
$fieldmap=array("name1"=>"name_1","name2"=>"name_2");
private function mapRow($inRow) {
$outRow = array();
foreach($inRow as $key => $value) {
$outRow[$this->fieldmap[$key]][] = $value;
}
return $outRow;
} // end mapRow
while ($row = mysql_fetch_assoc($result)) {
//$outResult[] = $this->mapRow($row);
$outResult[= $this->mapRow($row);
}
I commented your line of code and added new one..it definitely got what you mentioned in question.
If you can structure your arrays to where the keys align with the values (see example below) you can use PHP array_combine(). Just know that you will need to make absolutely sure the array is ordered correctly.
<?php
$fieldmap = array( 'name_1', 'name_2', 'name_3' );
private function mapRow($inRow)
{
$outRow = array_combine( $this->fieldmap, $inRow );
return $outRow;
}
For example, if your array was:
array( 'name1' => 10, 'name2' => 20, 'name3' => 30 );
The new result would be:
array( 'name_1' => 10, 'name_2' => 20, 'name_3' => 30 );
Let me know if this helps.
Try this:
function mapRow($inRow) {
$outRow = array();
foreach($inRow as $key => $value) {
$outRow[preg_replace('/\d/', '_$0', $key,1)] = $value;
}
return $outRow;
}
I am new to laravel and having a tough time figuring out a way to export one table to csv.
I have tried the following code in the controller class, but it gives me an error:
public function get_export()
{
$table = Cpmreport::all();
$file = fopen('file.csv', 'w');
foreach ($table as $row) {
fputcsv($file, $row);
}
fclose($file);
return Redirect::to('consolidated');
}
Model Class for Cpmreport:
class Cpmreport extends Eloquent
{
public static $table='cpm_report';
}
The error :
Message:
fputcsv() expects parameter 2 to be array, object given
Location:
C:\xampp\htdocs\cpm_report\application\controllers\cpmreports.php on line 195
Any help would be appreciated.
Easy way
Route::get('/csv', function() {
$table = Cpmreport::all();
$output='';
foreach ($table as $row) {
$output.= implode(",",$row->toArray());
}
$headers = array(
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="ExportFileName.csv"',
);
return Response::make(rtrim($output, "\n"), 200, $headers);
});
fputcsv($file, $table); should be fputcsv($file, $row), shouldn't it?
And convert the object to an array using Eloquent's to_array()method: http://laravel.com/docs/database/eloquent#to-array
public function get_export()
{
$table = Cpmreport::all();
$file = fopen('file.csv', 'w');
foreach ($table as $row) {
fputcsv($file, $row->to_array());
}
fclose($file);
return Redirect::to('consolidated');
}
Select query of MySQL data.
$data = \DB::connection('mysql')->select($select);
Call following function:
query_to_csv($data, 'data.csv');
function data_to_csv($data, $filename)
{
$fp = fopen($filename, 'w');
foreach ($data as $row) {
fputcsv($fp, $row);
}
fclose($fp);
}
0.1 Million records takes 1 second to create.
this is better and simple.
$file_name = "abc";
$postStudent = Input::all();
$ck = DB::table('loan_tags')->select('LAN')->where('liabilitiesId', $postStudent['id'])->get();
$i = 0;
foreach ($ck as $row) {
$apps[$i]['LAN'] = $row->LAN;
$apps[$i]['Account_number'] = $postStudent['account_number'];
$apps[$i]['Bank_Name'] = $postStudent['bank_name'];
$i++;
}
ob_end_clean();
ob_start();
Excel::create($file_name, function($excel) use($apps){
$excel->sheet('Sheetname', function($sheet) use($apps){
$sheet->row(1, array(
'LAN', 'Account number' , 'Bank Name'
));
$k = 2;
foreach ($apps as $deta) {
$sheet->row($k, array($deta['LAN'], $deta['Account_number'], $deta['Bank_Name']
));
$k++;
}
});
})->download('xlsx');
I have a csv file which looks like this
$lines[0] = "text, with commas", "another text", 123, "text",5;
$lines[1] = "some without commas", "another text", 123, "text";
$lines[2] = "some text with commas or no",, 123, "text";
And I would like to have a table:
$t[0] = array("text, with commas", "another text", "123", "text","5");
$t[1] = array("some without commas", "another text", "123", "text");
$t[2] = array("some text, with comma,s or no", NULL , "123", "text");
If I use split($lines[0],",") I'll get "text" ,"with commas" ...
Is there any elegant way to do it?
You can use fgetcsv to parse a CSV file without having to worry about parsing it yourself.
Example from PHP Manual:
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
In addition to Matt's suggestion, you can also use SplFileObject to read in the file:
$file = new SplFileObject("data.csv");
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl(',', '"', '\\'); // this is the default anyway though
foreach ($file as $row) {
list ($fruit, $quantity) = $row;
// Do something with values
}
source: http://de.php.net/manual/en/splfileobject.setcsvcontrol.php
you can read the data using the following function.
function readCSV() {
$csv = array_map('str_getcsv', file('data.csv'));
array_shift($csv); //remove headers
}
http://www.pearlbells.co.uk/how-to-sort-a1a2-z9z10aa1aa2-az9az10-using-php/
here is also a simple method to get read csv file.
$sfp = fopen('/path/to/source.csv','r');
$dfp = fopen('/path/to/destination.csv','w');
while ($row = fgetcsv($sfp,10000,",","")) {
$goodstuff = "";
$goodstuff = str_replace("¦",",",$row[2]);
$goodstuff .= "\n";
fwrite($dfp,$goodstuff);
}
fclose($sfp);
fclose($dfp);
Maybe my code solves your problem:
// Parse all content from csv file and generate array from line.
function csv_content_parser($content) {
foreach (explode("\n", $content) as $line) {
// Generator saves state and can be resumed when the next value is required.
yield str_getcsv($line);
}
}
// Get content from csv file.
$content = file_get_contents('your_file.csv');
// Create one array from csv file's lines.
$data = array();
foreach (csv_content_parser($content) as $fields) {
array_push($data, $fields);
}
In result you have an array with all values from csv.
It would be something like:
Array
(
[0] => Array
(
[0] => text, with commas
[1] => another text
[2] => 123
[3] => text
[4] => 5
)
[1] => Array
(
[0] => some without commas
[1] => another text
[2] => 123
[3] => text
)
[2] => Array
(
[0] => some text, with comma,s or no
[1] => NULL
[2] => 123
[3] => text
)
)
Suppose you have a create a function for same things, Then it should look like
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, 1000, $delimiter)) !== FALSE)
{
if(!$header){
$header = $row;
}else{
$data[] = array_combine($header, $row);
}
}
fclose($handle);
}
if(file_exists($filename)) #unlink($filename);
return $data;
}
$data = csvtoarray('file.csv', ',');
print_r($data);
You could use something like https://github.com/htmlburger/carbon-csv that allows column mapping:
$csv = new \Carbon_CSV\CsvFile('path-to-file/filename.csv');
$csv->set_column_names([
0 => 'first_name',
1 => 'last_name',
2 => 'company_name',
3 => 'address',
]);
foreach ($csv as $row) {
print_r($row);
}
The result of the below code would be something like:
Array
(
[0] => Array
(
[first_name] => John
[last_name] => Doe
[company_name] => Simple Company Name
[address] => Street Name, 1234, City Name, Country Name
)
[1] => Array
(
[first_name] => Jane
[last_name] => Doe
[company_name] => Nice Company Name
[address] => Street Name, 5678, City Name, Country Name
)
)
Another library that does the same thing(and much more) is http://csv.thephpleague.com/9.0/reader/
When you want to keep the index (first line) for multidimensional result array, you can use:
$delim = ';';
$csvFile = file($csv_file);
$firstline = str_getcsv($csvFile[0], $delim);
$data = array();
foreach ($csvFile as $line) {
$line = str_getcsv($line, $delim);
$data[] = array_combine($firstline, $line);
}
I've built an application to extract data from a CSV file , this php application was used to show a daily quote for users.
The full project on github: 365-quotes-php-csv.
Also this is the class Code for the application i've built
<?php
/*
Main Class
please note :
1- the CSV file must be comma separated (,) and each line must End with (;).
2- Feel free to edit the all.CSV file and add all of your 366 New Quotes.
3- don't change any thing specially the CSV file Location.
---------------------------------------------------------------------------
RISS.WORK all copy rights reserved 2018
please Don't Remove
Github/RissWork
Email : info#riss.work
*/
class Quote{
//properties
private $_quote,$_allQuotes;
private static $_instance = null;
//Constructor
private function __construct(){
//Day Count
$dayCount = date(z);
if($this->readCsvAndGetQuote($dayCount)){
return $this->getQuote();
}else{
echo 'Error Cannot open the .CSV File';
}
}
//Methods
//get Instance
public function getInstance(){
if(!isset(self::$_instance)){
self::$_instance = new Quote();
}
return self::$_instance;
}//end of get Instance
//get daily Quote
public function getQuote(){
return $this->_quote;
}//end of get Quote
//Read CSV
private function readCsvAndGetQuote($dayCount = 1 ){
if(($handel = fopen("csv/all.csv" , "r")) !== false){
$this->_allQuotes = fgetcsv($handel,1000000,';');
$this->_quote = explode(',',$this->_allQuotes[$dayCount]);
return true;
}
return false;
}//end of read CSV
}//end of Class
Return a php mapping array with the column of interests :
public function extractCSVDatas($file_uri) {
$AliasToSystemPathMappingArray = [];
if (($handle = fopen($file_uri, "r")) !== FALSE) {
$csv = array_map('str_getcsv', file($file_uri));
//remove header and choose columns among the list:
foreach((array_slice($csv,1)) as $line) {
list($id, $alias, $systemPath) = explode(';',$line[0]);
$AliasToSystemPathMappingArray[] = [$alias, $systemPath];
}
fclose($handle);
}
return $AliasToSystemPathMappingArray;
}
/**
* #return mixed[]
*/
public function csvToArray(string $delimiter, string $filename = ''): array
{
$data = [];
if (file_exists($filename) && is_readable($filename)) {
$header = null;
if (($handle = fopen($filename, 'r')) !== false) {
while (($row = fgetcsv($handle, 1000, $delimiter)) !== false) {
if (!$header) {
$header = $row;
} else {
$data[] = array_combine($header, $row);
}
}
fclose($handle);
}
}
return $data;
}
And why must it be simple when it can be complicated?
Joke aside, here is a quick and easy solution using the PHP function str_getcsv()
Here is an example:
function parse_csv( $filename_or_text, $delimiter=',', $enclosure='"', $linebreak="\n" )
{
$return = array();
if(false !== ($csv = (filter_var($filename_or_text, FILTER_VALIDATE_URL) ? file_get_contents($filename_or_text) : $filename_or_text)))
{
$csv = trim($csv);
$csv = mb_convert_encoding($csv, 'UTF-16LE');
foreach(str_getcsv($csv, $linebreak, $enclosure) as $row){
$col = str_getcsv($row, $delimiter, $enclosure);
$col = array_map('trim', $col);
$return[] = $col;
}
}
else
{
throw new \Exception('Can not open the file.');
$return = false;
}
return $return;
}
Imagine a situation where you need a function that works with both URL and comma delimited text. This is exactly the function that works like that. Just simply insert a CSV URL or comma separated text and it work nicely.
Just created a function that extracts data from .csv file or csv formatted text and then parses it for more convenient usage (presuming the first line is the columns). Works with however many rows/columns you'd like/have, just simply point the function to the file location/string and it will return the results!
function csvParse($input, $callback = false){
$results = [];
$raw_array = (is_file($input)) ? array_map('str_getcsv', file($input)) : array_map('str_getcsv', explode("\n", $input));
$array = array_splice($raw_array, 1, count($raw_array));
foreach($raw_array[0] as $c) $columns[] = $c;
foreach($array as $key0 => $val0)
foreach($val0 as $key1 => $val1)
$results[$key0][$columns[$key1]] = $val1;
if(is_callable($callback)) call_user_func_array($callback, array($results));
else return $results;
}
# Either One Would Work
$input = "dir/file.csv";
$input = "name,age,occupation,city\nCrimin4L,24,Programmer,New York\nMrAwesome,20,Gamer,Los Angeles";
# Usage #1
$array = csvParse($input);
var_export($array);
# Usage #2
csvParse($input, function($array){
var_export($array);
});
Input:
name,age,occupation,city
Crimin4L,24,Programmer,New York
MrAwesome,20,Gamer,Los Angeles
Array Output:
array (
0 =>
array (
'name' => 'Crimin4L',
'age' => '24',
'occupation' => 'programmer',
'city' => 'New York',
),
1 =>
array (
'name' => 'MrAwesome',
'age' => '20',
'occupation' => 'gamer',
'city' => 'Los Angeles',
),
)
Live Demo: https://ideone.com/Sa1aMO