To register for an Internet.com membership to receive newsletters and white papers, use the Register button ABOVE.
To participate in the message forums BELOW, click here
PHPBuilder.com  
 

 

Go Back   PHPBuilder.com > PHP Help > General Help

General Help Forum for General Help questions pertaining to PHP

Reply
 
Thread Tools Rating: Thread Rating: 2 votes, 5.00 average. Display Modes
Old 11-18-2009, 12:20 PM   #1
phpSimon
Member
 
Join Date: Nov 2009
Posts: 31
resolved [RESOLVED] Parse CSV file - get last items

Hi all

I want to parse a CSV file and get the last few items (which are monthly totals), into variables.

The CSV length will change but the last 14 items are always the same - the word "Totals", 12 values, then the word "End of Report".

"Totals",2000.00,0.00,480.00,480.00,480.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"End of Report"

From the above example I'd like to get:

$month1 = 2000.00
$month2 = 0.00
$month3 = 480.00
etc

I don't know how to parse the file then start from the end and work backwards!

Would it be best to re-order the CSV then take items 2 - 13? (and if so... how do I do that!)

I also can't look for the word "Totals" and start from there because it exists more than once in the CSV.

Can anyone suggest a way of doing this?

Many thanks


Simon
phpSimon is offline   Reply With Quote
Old 11-18-2009, 12:57 PM   #2
phpSimon
Member
 
Join Date: Nov 2009
Posts: 31
I think I'm getting closer...

If I do:

PHP Code:
$row = 1;
$handle = fopen("test.csv", "r");
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";
    }
}
$row=$row-1;
$startpos = $num-13;
echo
"Last row number = $row <br />";
echo
"Start position = $startpos <br />";
fclose($handle);
?>
This script prints data contained in 3 rows of 77 items each.

If anyone knows how to parse the file starting at row 3, item 64, taking only 12 items - I'd get the 12 items of data I need. Because the code above tells me what the last row is, it doesn't matter if there's 3 or 50 - I'll always start at the last row at the 64th item.

Any comments on the code above welcome too, I amended something I found on php.net.

Simon
phpSimon is offline   Reply With Quote
Old 11-18-2009, 01:11 PM   #3
phpSimon
Member
 
Join Date: Nov 2009
Posts: 31
Even better - I can now get the data I need. Does anyone know a neater way of doing this, or have a way of optimising this code please?

PHP Code:
$row = 1;
$handle = fopen("reviewbox/be.csv", "r");
while ((
$data = fgetcsv($handle, 1000, ",")) !== FALSE) {
    
$num = count($data);
    
$startpos = $num-13;
    
$row++;
}
fclose($handle);

$handle = fopen("reviewbox/be.csv", "r");
$data = fgetcsv($handle, 1000, ",");

$row=$row-1;

$item=$startpos;
$itemend=$startpos+12;

while (
$item < $itemend) {
echo
"Item number " . $item . " = " . $data[$item] . "<br />";
$item++;
}

fclose($handle);
phpSimon is offline   Reply With Quote
Old 11-18-2009, 01:44 PM   #4
NogDog
High Energy Magic Dept.
 
NogDog's Avatar
 
Join Date: Aug 2006
Location: Ankh-Morpork
Posts: 11,999
It's not entirely clear to me what an "item" is in this case, nor exactly which rows/items you want, but you could load everything into an array, and then grab things from it as desired, using the various array functions to reverse it, sort it, grab chunks of it, etc.
PHP Code:
$data = array();
if((
$fh = fopen('/path/to/file')) != false)
{
   while(
$row = fgetcsv($fh, 1000) !== false)
   {
      if(
count($row) == 1 and $row[0] === null)
      {
         continue;  
// skip empty rows
      
}
      
$data[] = $row;
   }
}
// get 12 rows starting with 3rd row (offset 2):
$myData = array_slice($data, 2, 12);
// reverse the order of the selected rows:
$myData = array_reverse($myData);
foreach(
$myData as $row)
{
   echo
"The fifth element in this row is: " . $row[4] . "<br />";
}
The above is untested and merely intended to give you some ideas.
__________________
"That's what the gods are! An answer that will do! Because there's food to be caught and babies to be born and life to be lived and so there is not time for big, complicated, and worrying answers! Please give us a simple answer, so that we don't have to think, because if we think, we might find answers that don't fit the way we want the world to be." -- from Nation, by Terry Pratchett
freelancer.internet.com
Email me
NogDog is offline   Reply With Quote
Old 11-19-2009, 03:48 AM   #5
phpSimon
Member
 
Join Date: Nov 2009
Posts: 31
Thank you, I will have a look at that way of doing it; a lot neater!

Simon
phpSimon is offline   Reply With Quote
Old 11-23-2009, 12:55 PM   #6
Richard.William
Junior Member
 
Join Date: Nov 2009
Posts: 2
Here is an alternate script using biterscripting.


Code:
set $wsep = ","
var str data, lastline, month1, month2
# Read the csv file.
cat "file.csv" > $data
# Get the last line.
lex "l" $data > $lastline
# Get and assign 2nd, 3rd, etc fields.
set $month1 = { wex -p "2" $lastline }
set $month2 = { wex -p "3" $lastline }
# etc.
Richard.William is offline   Reply With Quote
Old 11-24-2009, 05:05 AM   #7
phpSimon
Member
 
Join Date: Nov 2009
Posts: 31
That's clever - I don't know anything about biterscripting (goes to Google it...)
phpSimon is offline   Reply With Quote
Old 11-24-2009, 05:06 AM   #8
phpSimon
Member
 
Join Date: Nov 2009
Posts: 31
NogDog, I couldn't get that way of doing it to work. I'll post some samples of what I've tried when I can.
phpSimon is offline   Reply With Quote
Old 12-07-2009, 08:07 AM   #9
phpSimon
Member
 
Join Date: Nov 2009
Posts: 31
Working through NogDog's example and referring to the manual I have code that does what I want (which has changed slightly from the initial 'last few items' question that the post began with but I feel the content is still on topic and will still assist others with CSV parse questions).

I'm parsing a csv file that contains varying numbers of rows; I want to get specific elements (is that the correct term? Fields?) from each row into different arrays.

The code below works fine but I can't see how it knows to read the next row in the CSV file.

I am incrementing $row but as it's not actually used in the WHILE command, how does it know to start the next one?

I'm obviously happy it works but I'd really like to know how! Can anyone assist please?

PHP Code:
$row = 1;
if ((
$handle = fopen('awreviewbox/be.csv', 'r')) !== FALSE) {  // only proceed if the file is present

  
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {  // only proceed if there is data in the csv

   
$num = count($data);
   
// There are $num of fields in row $row
       
$row++;
      
            for (
$c=0; $c < $num; $c++) {

            
// fill arrays with data
            
$name[$row-1]=$data[21];
            
$id[$row-1]=$data[22];
            
$reference[$row-1]=$data[24];
           }
    }
    
fclose($handle);
    
$totalrows = $row-1;

//  There are $totalrows in the csv file
phpSimon is offline   Reply With Quote
Old 12-07-2009, 09:02 AM   #10
Installer
Member
 
Join Date: Aug 2004
Posts: 3,025
When reading from a file with a function such as fgetcsv() or fgets() PHP maintains a file pointer which points to the current position in that file. The pointer is automatically incremented each time a read is done, and can be directly manipulated with e.g. fseek() or rewind().
Installer is offline   Reply With Quote
Old 12-07-2009, 09:09 AM   #11
phpSimon
Member
 
Join Date: Nov 2009
Posts: 31
Thank you!

So does it presume end-of-row in both these cases;

1) reaches the specified number of delimeters (1000 in fgetcsv($handle, 1000, ",")
2) reachs the end of the row

?
phpSimon is offline   Reply With Quote
Old 12-07-2009, 09:16 AM   #12
Installer
Member
 
Join Date: Aug 2004
Posts: 3,025
As the manual entry for fgetcsv() says:
Quote:
Reading ends when length - 1 bytes have been read, on a newline (which is included in the return value), or on EOF (whichever comes first). If no length is specified, it will keep reading from the stream until it reaches the end of the line.
The file pointer, btw, is bound to the resource returned by fopen().
Installer is offline   Reply With Quote
Old 12-07-2009, 09:25 AM   #13
phpSimon
Member
 
Join Date: Nov 2009
Posts: 31
Thanks again. I couldn't find (and still can't find) that quote on the manual entry for fgetcsv() so I'm grateful for the information.
phpSimon is offline   Reply With Quote
Old 12-07-2009, 09:26 AM   #14
phpSimon
Member
 
Join Date: Nov 2009
Posts: 31
.. and also for the fopen() information!
phpSimon is offline   Reply With Quote
Old 12-07-2009, 09:40 AM   #15
Installer
Member
 
Join Date: Aug 2004
Posts: 3,025
My mistake; the quote is from the entry for fgets(), which is linked to from the entry for fgetcsv(). It applies to the length parameter for the former. That parameter for fgetcsv() works slightly differently.

Last edited by Installer; 12-07-2009 at 09:43 AM.
Installer is offline   Reply With Quote
Reply

Bookmarks


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Forum Jump


All times are GMT -4. The time now is 01:53 PM.






Acceptable Use Policy


The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.