I have been working with a script to change my CSV file to Tab Delimited. It seems to work great, but it is read-only. How do I go about actually writing the changes to the file? Here is the script:
<?php
$myfile = "/path/to/my.csv";
$csv_fp = fopen ($myfile, "r");
$rows = 0;
while ($data = fGetCsv ($csv_fp, 10000, ","))
{
$num = count($data);
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
$rows++;
}fclose ($csv_fp);
?>
This is how you can change a comma delimited CSV to a tab delimited. However, I don't see the benefits of doing this. I think comma delimited CSVs are much less prone to errors.
<?php
$myfile = "/path/to/my.csv";
$csv_fread = fopen($myfile, 'r');
$rows = array();
while ($columns = fgetcsv($csv_fread, 10000, ",")) {
$rows[] = $columns;
}
fclose($csv_fread);
$csv_fwrite = fopen($myfile, 'w');
foreach($rows as $row){
fputcsv($csv_fwrite, $row, "\t");
}
fclose($csv_fwrite);
?>
You will need to change the mode in your call to fopen from r to one that opens the file in write mode. Which one you choose depends on what you want to do (append, overwrite). I am guessing that you want to overwrite, in which case you can choose w or w+.
Check out the manual for fopen and fwrite.
Related
Using PHP, how can I get the total number of rows that are in a CSV file? I'm using this method but cannot get it to work properly.
if (($fp = fopen("test.csv", "r")) !== FALSE) {
while (($record = fgetcsv($fp)) !== FALSE) {
$row++;
}
echo $row;
}
Create a new file reference using SplFileObject:
$file = new SplFileObject('test.csv', 'r');
Try to seek to the highest Int PHP can handle:
$file->seek(PHP_INT_MAX);
Then actually it will seek to the highest line it could in the file, there is your last line and the last line + 1 is equals to your total lines:
echo $file->key() + 1;
Tricky, but this will avoid you from loading the file contents into memory, which is a very cool thing to do when dealing with really large files.
Here's another option using file() to read the entire file into an array, automatically parsing new lines etc:
$fp = file('test.csv');
echo count($fp);
Also, since PHP5, you can pass in the FILE_SKIP_EMPTY_LINES... to skip empty lines, if you want to:
$fp = file('test.csv', FILE_SKIP_EMPTY_LINES);
Manual: http://php.net/manual/en/function.file.php
Try
$c =0;
$fp = fopen("test.csv","r");
if($fp){
while(!feof($fp)){
$content = fgets($fp);
if($content) $c++;
}
}
fclose($fp);
echo $c;
I know that this is pretty old, but actually I ran into the same question.
As a solution I would assume to use linux specific logic:
$rows = shell_exec('$(/bin/which cat) file.csv | $(/bin/which tr) "\r" "\n" | $(which wc) -l');
NOTE: this only works for linux only and this only should be used if you are 100% certain that your file has no multiline-cells
CSV rows are separated by line breaks. Therefore, split the rows by line breaks, and you will get an array of rows, which is countable.
if (($fp = fopen("test.csv", "r")) !== FALSE) {
$rows = explode("\n", $fp);
$length = count($rows);
echo $length;
}
Note; none of higher-upvoted solutions that count lines in the file are reliable, as they are only counting the lines, not the csv entries (which can contain newline characters)
I'm using a similar solution to op, and it works perfectly, but with op's code the while part can break on empty lines, which is potentially his problem.
So it looks like this (edited op's code)
$rowCount=0;
if (($fp = fopen("test.csv", "r")) !== FALSE) {
while(!feof($fp)) {
$data = fgetcsv($fp , 0 , ',' , '"', '"' );
if(empty($data)) continue; //empty row
$rowCount++;
}
fclose($fp);
}
echo $rowCount;
I find this the most reliable:
$file = new SplFileObject('file.csv', 'r');
$file->setFlags(
SplFileObject::READ_CSV |
SplFileObject::READ_AHEAD |
SplFileObject::SKIP_EMPTY |
SplFileObject::DROP_NEW_LINE
);
$file->seek(PHP_INT_MAX);
$lineCount = $file->key() + 1;
I know this is an old post, but I've been googling this issue, and found that the only problem with the original code was that you need to define $row outside the while loop, like this:
if (($fp = fopen("test.csv", "r")) !== FALSE) {
$row = 1;
while (($record = fgetcsv($fp)) !== FALSE) {
$row++;
}
Just in case it helps someone :)
echo $row;
}
In case you are getting the file from a form
$file = $_FILES['csv']['tmp_name'];
$fp = new SplFileObject($file, 'r');
$fp->seek(PHP_INT_MAX);
echo $fp->key() + 1;
$fp->rewind();
Works like charm!!!!!!!!!!!!!!!!!!
$filename=$_FILES['sel_file']['tmp_name'];
$file=fopen($filename,"r");
$RowCount=0;
while ((fgetcsv($file)) !== FALSE)
{
$RowCount++;
}
echo $RowCount;
fclose($file);
I am converting csv file to an array using code bellow. But, problem is that end of the row is CR LF, and it is not detected, so array has wrong offset. CR LF is ignored and "cells" around it are merged.
How could i rewrite code to detect this row ending and split array correctly ? Or, is there better approach to convert csv to array?
There are some simmilar questions here but i have not found solution to this issue yet.
Thanks.
$fileName ='test.csv';
$csvData = file_get_contents($fileName);
$csvNumColumns = 11;
$csvDelim = ";";
$data = array_chunk(str_getcsv($csvData, $csvDelim), $csvNumColumns);
print_r($data);
Have you tried using fgetcsv()? full info on php.net.
Example usage from php.net
<?php
$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);
}
?>
I would avoid str_getcsv() and work with fgetcsv() to avoid dealing with some of the end of line futz.
http://php.net/manual/en/function.fgetcsv.php
if (($handle = fopen("fileName", "r")) !== FALSE) {
while (($data = fgetcsv($handle)) !== FALSE) {
var_dump($data); //array representation of one line of csv...
}
}
fclose($handle);
If you're on a Mac...
Note: If PHP is not properly recognizing the line endings when reading files either on or created by a Macintosh computer, enabling the auto_detect_line_endings run-time configuration option may help resolve the problem.
I've looked for questions on this topic, but failed to get what I'm looking for. This is for C++, I need similar for PHP. This is for including php files, I just want to read a CSV file.
I have this:
if(file_exists("data.csv")){
echo "CSV file found";
$csv_data = file_get_contents("data.csv");
$lines = explode("\n", trim($csv_data));
$array = array();
foreach ($lines as $line){
$array[] = str_getcsv($line);
}else {echo "File not found";}
But I want to NOT specify the file name - i.e. generically load/read/open the file.
Is there any simple why of doing that? Doesn't make sense, but I was told to not have anything hard coded in my PHP script.
Thanks in advance.
use fgetcsv
if(file_exists("data.csv")){
echo "CSV file found";
$handle = fopen("data.csv", "r");
if(!$handle) die("Could not open file!");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}else {echo "File not found";}
If you may not have anything hard coded in your script, you need to put those hardcoded things into some sort of external config file. You will have to hardcode the name of that config file into your bootstrap or whatever comes first in your application. Once the config is loaded, make the configuration data available in the places where it is needed. Not hardcoding configuration data into your code will allow you to create more reusable components and code, e.g. CSV Reader that can read any CSV file instead of a CSV Reader that can only read that one particular CSV file hardcoded into it.
Example:
// config.php
<?php
return array(
'csvFile' => '/path/to/file.csv',
…
);
// bootstrap.php
<?php
$config = include '/path/to/config.php';
…
// someFile.php
<?php
include '/path/to/bootstrap.php';
$file = new SplFileObject($config['csvFile']);
$file->setFlags(SplFileObject::READ_CSV);
foreach ($file as $row) {
// Do something with values
}
Put your code into a function...
function open_file($file_name)
{
if (!file_exists($file_name))
{
return false;
}
$csv_data = file_get_contents($file_name);
$lines = explode("\n", trim($csv_data));
$array = array();
foreach ($lines as $line)
{
$array[] = str_getcsv($line);
}
return $array;
}
I am trying to read a CSV file (delimited by commas) but unfortunately, it isn't responding as it ought to. I am not so sure what I am doing wrong here, but I'll paste out the contents of the code and the CSV file both :
$row = 0;
if($handle = fopen("SampleQuizData.csv","r") !== FALSE)
{
// WORKS UNTIL HERE, SO FILE IS BEING READ
while(!feof(handle))
{
$line = fgetcsv($handle, 1024, ",") ;
echo $line[2]; // DOES NOT WORK
}
}
Here is the CSV file: (the emails and names have been changed here to protect the identities of the users)
parijat,something,parijatYkalia#hotmail.com
matthew,durp, mdurpdurp#gmail.com
steve,vai,stevevai#gmail.com
rajni,kanth,rajnikanth#superman.com
it lacks a '$' to the handle variable
while(!feof($handle)){
and not :
while(!feof(handle)){
Give this a try:
<?php
$row = 0;
if (($handle = fopen("SampleQuizData.csv", "r")) !== FALSE)
{
while(!feof($handle))
{
$line = fgetcsv($handle, 1024, ",") ;
echo "$line[2]";
}
}
?>
It's worth a mention but when I was working on CSV exports a few weeks ago, I had weird line ending inconsistencies. So I put this at the top of my php file and it worked splendid.
<?php
ini_set("auto_detect_line_endings", true);
?>
How do I import CSV files using zend framework? Should I use zend_file_transfer or is there any special class that I have to look into? Also if I use zend_file_transfer is there any special validator for CSV?
you don't have to use any zend libraries to import csv files, you can just use native php functions, take a look at fgetcsv
$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);
}
You could also use SplFileObject for reading CSV files.
From the php manual:
<?php
$file = new SplFileObject("animals.csv");
$file->setFlags(SplFileObject::READ_CSV);
foreach ($file as $row) {
list($animal, $class, $legs) = $row;
printf("A %s is a %s with %d legs\n", $animal, $class, $legs);
}
?>
http://php.net/manual/en/splfileobject.fgetcsv.php
There is currently no way to do this with the Zend Framework. How can one be sure?
For example, Zend_Translate supports translation with CSV files, but if you check the the source code of the respective adapter (Zend_Translate_Adapter_Csv), you can verify it uses fgetcsv, and not a specific Zend class. Besides, this CSV adapter comes with the following warning:
Note: Beware that the Csv Adapter has
problems when your Csv files are
encoded differently than the locale
setting of your environment. This is
due to a Bug of PHP itself which will
not be fixed before PHP 6.0
(http://bugs.php.net/bug.php?id=38471).
So you should be aware that the Csv
Adapter due to PHP restrictions is not
locale aware.
which is related with the problems of the fgetcsv function.
Here's a function that reads a csv file and returns an array of items that contain the first two column data values.
This function could read a file of first_name,last_name for example.
function processFile ($filename) {
$rtn = array();
if (($handle = fopen($filename, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$item = array();
$item[] = $data[0];
$item[] = $data[1];
$rtn[] = $item;
}
}
return $rtn;
}