PHP Undefined Offset with fgetcsv - php

Okay, I've spent several hours on this problem and I'm not sure what's going on. I think I just need a fresh perspective on this problem especially since I've been up for over 24 hours and the deadline for this is in five hours.
I am getting an Undefined offset notice for every single offset (0 to 907) when I try to use the data I pulled from a CSV. (It probably means I am not successfully pulling the data, but I am exhausted and would appreciate some help)
Does anyone know what I'm doing wrong?
$lines = array();
$lines2 = "";
$one = array();
$two = array();
$three = array();
$four = array();
$five = array();
$six = array();
$header = "";
$footer = "";
$countLines = 0;
/*
* Open the file and store its data into an array
*/
$fp = fopen('db.csv','r') or die("can't open file");
while($lines = fgetcsv($fp)) {
for ($k = 0, $m = count($lines) - 1; $k < $m; $k++) {
$one[$k] = $lines[0];
$two[$k] = $lines[1];
$three[$k] = $lines[2];
$four[$k] = $lines[3];
$five[$k] = $lines[4];
$six[$k] = $lines[5];
}
$countLines++;
}
fclose($fp) or die("can't close file");
/*
* Set up file header
*/
$header = "Header"
;
/*
* Set up file footer
*/
$footer = "Footer";
/*
* Prepare data for export
*/
for ($i = 0, $j = $countLines - 1; $i < $j; $i++) {
$lines2 .= $one[$i] ." ".
$two[$i] ." ".
str_pad($three[$i], 3) ." ".
str_pad($four[$i], 30) ." ".
str_pad($five[$i], 30) ." ".
str_pad($six[$i], 30) ."\r\n";
}
/*
* Store data in file
*/
$fp = fopen('db2.csv', 'w') or die("can't open file");
fwrite($fp, $header);
fwrite($fp, $lines2);
fwrite($fp, $footer);
fclose($fp) or die("can't close file");
The CSV file is a standard comma-delimited file so I don't see any reason to post that data here.

The statement
while($lines = fgetcsv($fp)) {
fgetcsv will return a single line in the form of an array containing the elements on the line;
Therefore the following is wrong and needs to be removed as you are iterating over a single line in the CSV
for ($k = 0, $m = count($lines) - 1; $k < $m; $k++) {
So, after revision the reading loop should (I think) be like this:
$fp = fopen('db.csv','r') or die("can't open file");
$k=0;
while($lines = fgetcsv($fp)) {
$one[$k] = $lines[0];
$two[$k] = $lines[1];
$three[$k] = $lines[2];
$four[$k] = $lines[3];
$five[$k] = $lines[4];
$six[$k] = $lines[5];
$k++;
$countLines++;
}
After this use, e.g. print_r($one) for debug to view the arrays.
To output it I'm relying heavily on guesswork as to what you want to achieve, because you are outputting to db2.csv, but without commas (to seperate). however try something like the following
/*
* Store data in file
*/
$fp = fopen('db2.csv', 'w') or die("can't open file");
fwrite($fp, $header);
/*
* Data for export
*/
for ($i = 0, $j = $countLines - 1; $i < $j; $i++) {
fprintf($fp, "%s %s %-3s %-30s %-30s %-30s\r\n", /* possibly add commas here? */
$one[$i], $two[$i], $three[$i],$four[$i], $five[$i], $six[$i]);
}

I get the same one and look for a solution as you ...
In fact it's really simple and diabolic :fgetcsv() add an array with one NULL value at the end of the reading. Therefore, $lines[1] will produce an error, because the last added array has only one value.
Just count the number of columns in $lines like this :
/*
* Open the file and store its data into an array
*/
$fp = fopen('db.csv','r') or die("can't open file");
while($lines = fgetcsv($fp)) {
if ( count($lines) == 6 )
{
for ($k = 0, $m = count($lines) - 1; $k < $m; $k++) {
$one[$k] = $lines[0];
$two[$k] = $lines[1];
$three[$k] = $lines[2];
$four[$k] = $lines[3];
$five[$k] = $lines[4];
$six[$k] = $lines[5];
}
}
$countLines++;
}

Related

Read external file match specific string in first column and return respective string of second column in php

I have two text files, csvurl.txt and tickerMaster.txt
tickerMaster.txt
H0001
Remarks: No "H0003" in tickerMaster.txt and the number are not in sequence
csvurl.txt
H0001, URL1
H0003, URL3
I would like to read the entries in tickerMaster.txt one by one, say H0001, H0003...
and createURL by matching the data in csvurl.txt. So I am using following code...
<?php
function createURL($ticker){
$file = 'csvurl.txt';
header('Content-Type: text/plain');
$contents = file_get_contents($file);
$sep = ',';
$pattern = preg_quote($searchfor, '/');
$searchfor = $ticker;
$pattern = "/^($searchfor\w+)$sep.*$/m";
if (preg_match_all($pattern, $contents, $matches)){
echo implode($matches[0])."\n";
}
else{
echo "No matches found";
}
}
function getCSVFile($url, $outputFile){
$content = file_get_contents($url);
$content = str_replace("Date,Open,High,Low,Close,Volume,Adj Close", "", $content);
$content = trim($content);
file_put_contents($outputFile, $content);
}
function fileToDatabase($txtFile, $tableName){
$file = fopen($txtFile, "r");
while(!feof($file)){
$line = fgets($file);
$pieces = explode(",", $line);
$date = $pieces[0];
$open = $pieces[1];
$high = $pieces[2];
$low = $pieces[3];
$close = $pieces[4];
$volume = $pieces[5];
$amount_change = $close-$open;
$percent_change = ($amount_change/$open)*100;
$sql = "SELECT * FROM $tableName";
$result = mysql_query($sql);
if(!$result){
$sql2 = "CREATE TABLE $tableName (date DATE, PRIMARY KEY(date), open FLOAT, high FLOAT, low FLOAT, close FLOAT, volume INT, amount_change FLOAT, percent_change FLOAT)";
mysql_query($sql2);
}
$sql3 = "INSERT INTO $tableName (date, open, high, low, close, volume, amount_change, percent_change) VALUES ('$date','$open','$high','$low','$close','$volume', '$amount_change', '$percent_change')";
mysql_query($sql3);
}
fclose($file);
}
function main(){
$mainTickerFile = fopen("tickerMaster.txt", "r");
while(!feof($mainTickerFile)){
$companyTicker = fgets($mainTickerFile);
$companyTicker = trim($companyTicker);
$fileURL = createURL($companyTicker);
$companyTxtFile = "txtFiles/".$companyTicker.".txt";
getCSVFile($fileURL, $companyTxtFile);
fileToDatabase($companyTxtFile, $companyTicker);
}
}
main()
?>
However, what I got is the whole line on the information in csvurl.txt
for example:
No matches foundH0001,URL1H0003,URL3
My desired output is just:
URL1
Actually, I am looking for the function like vlookup in excel, but I cant search any solution for this kind of matching.
Thanks.
I suppouse data have not error, so don't do any test
$c1 = file('csvurl.txt');
$l = count($c1);
for ($i = 0; $i < $l; $i++) {
list($name,$url) = explode(',', $c1[$i]);
// making array $red['H001'] => 'URL1"
$red[trim($name)] = trim($url);
}
unset($c1);
$c = file('tickerMaster.txt');
$l = count($c);
for ($i = 0; $i < $l; $i++) {
$c[$i] = trim($c[$i]);
// If rule exists
if(isset($red[$c[$i]])) echo($red[$c[$i]]);
}

How to save database table in text file? And how to specify format in text file?

I am using a script for saving a database table in .txt file. The script is working perfectly.The table fields are like this :
8,c.s.e,computer ,9,0
9,m.c.a,b.a. in hindi ,10,0
but i want it to be like this-:
{ "table_name": [
["8","c.s.e","computer","9","0"],
["9","m.c.a","computer","10","0"],
]
}
and here is my script:
$fh = fopen('db.txt', 'w');
$con = mysql_connect("localhost","root","");
mysql_select_db("dot", $con);
$result = mysql_query("SELECT * FROM class_master");
while ($row = mysql_fetch_array($result)) {
$num = mysql_num_fields($result) ;
$last = $num - 1;
for($i = 0; $i < $num; $i++) {
fwrite($fh, $row[$i]);
if ($i != $last) {
fwrite($fh, ",");
}
}
fwrite($fh, "\n");
}
fclose($fh);
Implement this line in your code
fwrite($fh, json_encode($row[$i]));

PHP and csv report calculations

I have a csv file that I would like to generate a summary report from. The csv looks like this :
The csv has in each row an activity and the coresponding time when it starts.
The summary I'm trying to generate has to look like this :
Basically I need to show each activity and the times when it starts and it ends
I did as following in PHP, I'm almost done but the result I get is not really what I want :
$csvFileName = "The csv path";
$report = array();
$file = fopen($csvFileName, "r");
while (($data = fgetcsv($file, 8000, "\n")) !== FALSE) {
$num = count($data);
for ($c = 0; $c < $num; $c++) {
$t = explode(',', $data[$c]);
$time = $t[0];
$activity = $t[1];
$report[] = array($activity, $time);
}
}
fclose($file);
//I'm reading the whole file content and copying it into an array.
$summaryReport = array();
$j = 1;
for($i=0; $i<sizeof($report); $i++){
if($report[$i][0] !== $report[$j][0]){
array_push($summaryReport,array($report[$i][0],$report[$i][1],$report[$j][1]));
}
$j++;
}
echo json_encode($summaryReport);
The output json looks like this :
[["Start","10:42","10:59"],["Driving route","11:10","11:50"],["Lunch-Rest Break","11:50","11:57"],["Driving route","11:57","12:03"],["Break","12:11","12:41"],["Driving route","13:05","14:09"],["Waiting","14:14","14:28"]]
What I'm looking for as result is something like that:
[["Start","10:42","10:59"],["Driving route","10:59","11:50"],["Lunch-Rest Break","11:50","11:57"],["Driving route","11:57","12:03"],["Break","12:03","12:41"],["Driving route","12:41","14:09"],["Waiting","14:09","14:28"],["End","14:28"]]
my coding logic is not really working well, does anyone see how can I do a simple loop to do what I'm looking for?
Thank you in advance.
The result can be achieved much easier. Look at my code, I got rid of all your inner loops, fixed syntax errors and there is no need to store the whole csv file in memory:
PHP code
<?php
$csvFileName = "./test.csv";
$file = fopen($csvFileName, "r");
$summaryReport = array();
$i = 0;
$previous_name = null;
while ($data = fgetcsv($file, 8000)) {
if ($previous_name !== $data[1])
{
$summaryReport[$i] = array($data[1], $data[0]);
if ($i > 0)
{
$summaryReport[$i-1][2] = $data[0];
}
$previous_name = $data[1];
++$i;
}
}
fclose($file);
echo json_encode($summaryReport);
Test csv file
10:41,Start
10:59,Driving
11:29,Driving
11:11,End
Output
[["Start","10:41","10:59"],["Driving","10:59","11:11"],["End","11:11"]]

Writing to multiple (splitting) CSV files with PHP

I'm using a simple function to write write arrays to a CSV-file, which look like this:
function writeToCSV($array) {
$fp = fopen('programmes.csv', 'a');
fputcsv($fp, $array);
fclose($fp);
}
Simple as a pie. However, is there anyway to know what line-number the pointer is at? Because I want to be able to after 1000 lines to begin writing to a new file. Why? Because I need to be able to import them to a database later with some memory constraints, and to parse a CSV-file with 15000 lines is a no-no.
function writeToCSV($array) {
$i = 1;
$j = 1;
$fp = fopen('programmes' . $j . '.csv', 'a');
foreach($array as $fields) {
if ($i % 1000 == 0) {
fclose($fp);
$fp = fopen('programmes' . $j . '.csv', 'a');
$j = $j + 1;
}
fputcsv($fp, $fields);
$i = $i + 1;
}
fclose($fp);
}
Try this:
count(file('programmes.csv'));
This will give you the number of lines in a file.
I haven't tried if this works, but i would do something like this:
<?php
function writeToCSV($array) {
// count lines in the current file
$linecount = 0;
$fh = fopen('programmes.csv','rb') or die("ERROR OPENING DATA");
while (fgets($fh) !== false) $linecount++;
fclose($fh);
$aSize = sizeof($array);
if (($linecount + $aSize) > 1000) {
// split array
$limit = 1000 - $linecount;
$a = array_slice($array, 0, $limit);
$b = array_slice($array, $limit);
// write into first file
$fp = fopen('programmes.csv', 'a');
foreach($a as $field) fputcsv($fp, $field);
fclose($fp);
// write into second file
$fp = fopen('programmes2.csv', 'a');
foreach($b as $field) fputcsv($fp, $field);
fclose($fp);
} else {
$fp = fopen('programmes.csv', 'a');
$idx = 0;
while ($linecount < 1000) {
// fill the file to the 1000 lines
fputcsv($fp, $array[$idx]);
++$linecount;
++$idx;
}
fclose($fp);
if ($idx != $aSize) {
// create new file
$fp = fopen('programmes.csv', 'a');
while ($idx< $aSize) {
// fill the file to the 1000 lines
fputcsv($fp, $array[$idx]);
++$idx;
}
fclose($fp);
}
}
}
?>

remove All lines except first 20 using php

how to remove every line except the first 20 using php from a text file?
If loading the entire file in memory is feasible you can do:
// read the file in an array.
$file = file($filename);
// slice first 20 elements.
$file = array_slice($file,0,20);
// write back to file after joining.
file_put_contents($filename,implode("",$file));
A better solution would be to use the function ftruncate which takes the file handle and the new size of the file in bytes as follows:
// open the file in read-write mode.
$handle = fopen($filename, 'r+');
if(!$handle) {
// die here.
}
// new length of the file.
$length = 0;
// line count.
$count = 0;
// read line by line.
while (($buffer = fgets($handle)) !== false) {
// increment line count.
++$count;
// if count exceeds limit..break.
if($count > 20) {
break;
}
// add the current line length to final length.
$length += strlen($buffer);
}
// truncate the file to new file length.
ftruncate($handle, $length);
// close the file.
fclose($handle);
For a memory efficient solution you can use
$file = new SplFileObject('/path/to/file.txt', 'a+');
$file->seek(19); // zero-based, hence 19 is line 20
$file->ftruncate($file->ftell());
Apologies, mis-read the question...
$filename = "blah.txt";
$lines = file($filename);
$data = "";
for ($i = 0; $i < 20; $i++) {
$data .= $lines[$i] . PHP_EOL;
}
file_put_contents($filename, $data);
Something like:
$lines_array = file("yourFile.txt");
$new_output = "";
for ($i=0; $i<20; $i++){
$new_output .= $lines_array[$i];
}
file_put_contents("yourFile.txt", $new_output);
This should work as well without huge memory usage
$result = '';
$file = fopen('/path/to/file.txt', 'r');
for ($i = 0; $i < 20; $i++)
{
$result .= fgets($file);
}
fclose($file);
file_put_contents('/path/to/file.txt', $result);

Categories