Dragen Posted April 9, 2007 Share Posted April 9, 2007 Hi, I'm trying to write a script to calculate my hours for work. I have a text file with my hours written down as a timestamp.. 11:40 01/04/2007 13:30 01/04/2007 19:30 01/04/2007 19:40 01/04/2007 21:10 01/04/2007 00:15 01/04/2007 Basically the first line is my start time the one below is when I finish. Each work block is broken up by an empty line. I've never tried a file based system before as I've always used databases, but I'm wanting to use a flat file system for this. How can I take the information from the file? I want it to read as something like: $start = first line $end = second line Then I'd have a for each statement I guess.. so foreach (block of work) { echo "start: " . $start; echo "end: " . $end; } I'm not sure how to work with flat files so how would I go about reading from it and then defining what parts of the file is what? Thanks Quote Link to comment Share on other sites More sharing options...
Wildbug Posted April 9, 2007 Share Posted April 9, 2007 file_get_contents() followed by preg_match_all() followed by your foreach loop. Quote Link to comment Share on other sites More sharing options...
clown[NOR] Posted April 9, 2007 Share Posted April 9, 2007 well.. what i would have done first is seperating time and date with something else than a blank space.. maybe using || then i would use file() $file = file(filename); then i would do something like this this reads every line in the $file array $work = array(); $i = 0; foreach($file as $result) { $i++; $work[] = $result; } now you need to separate time from date. $count = 0; foreach($count <= $i) { $workInfo = explode("||", $work) $workTime = $workInfo[0]; $workDate = $workInfo[1]; $count++; } but i think it will be a conflict with the blank line.. and i'm not sure on how to bypass it ... but most likely with an if statement inside the last foreach that sais something about "if there's no || in $workInfo, skip it" or something like that.. think this should work Quote Link to comment Share on other sites More sharing options...
Dragen Posted April 9, 2007 Author Share Posted April 9, 2007 okay, what I've got is this <?php $file = file('hours.txt'); $work = array(); $i = 0; foreach($file as $result) { $i++; $work[] = $result; } $count = 0; foreach($count <= $i) { $workInfo = explode("||", $work); $workTime = $workInfo[0]; $workDate = $workInfo[1]; $count++; } ?> Although I'm recieving this error: Parse error: parse error, unexpected ')' in /home/fhlinux181/g/gimppro.co.uk/user/htdocs/test/hours.php on line 21 can't find the problem though.. also, using '$file = file('hours.txt');', do I still need to include something like this: $fp = fopen('hours.txt','r'); if (!$fp) { echo 'ERROR: Unable to open file.'; exit; } Quote Link to comment Share on other sites More sharing options...
clown[NOR] Posted April 9, 2007 Share Posted April 9, 2007 about the fopen... that's a no... file() automaticly reads the whole file into an array over to the error.. what's on on line 21? Quote Link to comment Share on other sites More sharing options...
Wildbug Posted April 9, 2007 Share Posted April 9, 2007 $contents = file_get_contents('hours.txt'); $contents = explode("\n\n",trim($contents)); foreach ($contents as $value) echo 'Start: ',substr($value,0,15),echo "\nEnd: ",substr($value,17),"\n"; Quote Link to comment Share on other sites More sharing options...
clown[NOR] Posted April 9, 2007 Share Posted April 9, 2007 hmm... yeah that's a good question... where the hell is that missing ) ?? hehe .. Quote Link to comment Share on other sites More sharing options...
Dragen Posted April 9, 2007 Author Share Posted April 9, 2007 line 21 is foreach($count <= $i) { and wildbug I tried your suggesstion and it outputted the data like this Start: 11:40 01/04/200 End: 13:30 01/04/2007 19:30 01/04/2007 19:40 01/04/2007 20:00 01/04/2007 20:03 01/04/2007 21:10 01/04/2007 00:15 01/04/2007 It seems to have a problem once it reaches the blank line.. Is there a better way of putting the data into the flat file, so that I can display it easily? As I've said I've never used flat files before, so I just wrote my txt file how I thought easy to read... Quote Link to comment Share on other sites More sharing options...
clown[NOR] Posted April 9, 2007 Share Posted April 9, 2007 hmm... weird... i'm using the exact same code for my calendar script... to grab entries for selected date... this is my exact code (copy/paste): <?php $file = file("$scheFILE"); $i = 0; $sche = array(); foreach ($file as $result) { $i++; $sche[] = $result; } $cnt = 0; while ($cnt < $i) { $schInfo = explode("||", $sche[$cnt]); $schTime = $schInfo[0]; $schTitle = $schInfo[1]; $schMessage = $schInfo[2]; echo $schTime." :: ".$schTitle."<br>"; echo $schMessage."<hr size=1 color=#000000>"; $cnt++; } ?> Quote Link to comment Share on other sites More sharing options...
Dragen Posted April 9, 2007 Author Share Posted April 9, 2007 but what does $scheFILE look like? I think it has problems with my file because of the blank lines dividing the work blocks. Quote Link to comment Share on other sites More sharing options...
Wildbug Posted April 9, 2007 Share Posted April 9, 2007 Ah, damn. I didn't test it. It's possible that it's a DOS file and has \r\n instead of \n or that there's more whitespace on that blank line. Perhaps you could use preg_split('/\s{2,}/',$contents) instead of explode (or {4,} if \r\n, maybe). If you've been careful about entering your data, i.e., consistent, then it should be no trouble to parse it automatically, whatever method you end up using. Quote Link to comment Share on other sites More sharing options...
clown[NOR] Posted April 9, 2007 Share Posted April 9, 2007 $scheFILE = sche/file.txt Quote Link to comment Share on other sites More sharing options...
Dragen Posted April 9, 2007 Author Share Posted April 9, 2007 My file is just a .txt file. There is no whitespace on the blank lines except the actual existence of the blank line itself.. no spaces etc. I've now got the code as: <?php $contents = file_get_contents('hours.txt'); $contents = preg_split('/\s{2,}/',$contents); foreach ($contents as $value) { echo "<p align=\"left\">Start: " . substr($value,0,16); echo "<br />End: " . substr($value,17) . "</p>"; } ?> which works to an extent. For some reason it outputs everythings as start, and I get nothing for end. Start: 11:40 01/04/2007 End: Start: 13:30 01/04/2007 End: Start: 19:30 01/04/2007 // this should be under the end above End: Start: 19:40 01/04/2007 End: Start: 20:00 01/04/2007 End: Start: 20:03 01/04/2007 End: Start: 21:10 01/04/2007 End: Start: 00:15 01/04/2007 End: Quote Link to comment Share on other sites More sharing options...
kenrbnsn Posted April 9, 2007 Share Posted April 9, 2007 Here is some basic code that should help you on your way: <?php $ts = file('timesheet.txt'); for ($i=0;$i<count($ts);$i += 3) { $tmp = array(); $tmp[] = 'Start: ' . trim($ts[$i]); $tmp[] = 'End: ' . trim($ts[$i+1]); echo implode('<br>', $tmp) . '<br><br>'; } ?> Ken Quote Link to comment Share on other sites More sharing options...
clown[NOR] Posted April 9, 2007 Share Posted April 9, 2007 this should work <?php $contents = file_get_contents('hours.txt'); $contents = preg_split('/\s{2,}/',$contents); $value = array(); foreach ($contents as $value) { echo "<p align=\"left\">Start: " . substr($value[0],0,16); echo "<br />End: " . substr($value[1],17) . "</p>"; } ?> Quote Link to comment Share on other sites More sharing options...
Wildbug Posted April 9, 2007 Share Posted April 9, 2007 Try changing the pattern from /\s{2,}/ to /\s{4,}/. Quote Link to comment Share on other sites More sharing options...
Dragen Posted April 9, 2007 Author Share Posted April 9, 2007 Try changing the pattern from /\s{2,}/ to /\s{4,}/. ah thanks, that worked! Quote Link to comment Share on other sites More sharing options...
Wildbug Posted April 9, 2007 Share Posted April 9, 2007 I'm glad that worked; I was almost out of ideas :-) Your file is probably a DOS (Windows) format which uses two characters to indicate a carriage return (\r\n) whereas UNIX uses just the one (\n - newline), so the whitespace pattern indicator (\s) will match at each of these -- \r and \n. To break at the blank lines I was assuming a double space -- \n\n, but it was really \r\n\r\n. Thus, \s{4,} is needed instead of \s{2,}. Quote Link to comment Share on other sites More sharing options...
kenrbnsn Posted April 9, 2007 Share Posted April 9, 2007 That's one of reasons to use the trim() function. It will remove the newline character from the end of a line whether the new line character consists of "\n", "\r\n", or "\r". If you use the trim() function, your code is portable across different OS's. Ken Quote Link to comment Share on other sites More sharing options...
Dragen Posted April 9, 2007 Author Share Posted April 9, 2007 thanks for all the help everyone! Just a thought though, if I wanted to seperate the times and dates as two seperate arrays or perhaps just different parts of the same array, how would I do that? Quote Link to comment Share on other sites More sharing options...
kenrbnsn Posted April 9, 2007 Share Posted April 9, 2007 Look at the explode() function. Ken Quote Link to comment Share on other sites More sharing options...
Wildbug Posted April 9, 2007 Share Posted April 9, 2007 You could use substr() since you have a nice, even, zero-padded format. I like regular expressions, though, so I might jump right to that. In fact, you could replace the previous code we've discussed with a preg_match_all() like so: $contents = file_get_contents('hours.txt'); preg_match_all('|(\d\d:\d\d) (\d\d/\d\d/\d{4})\s+(\d\d:\d\d) (\d\d/\d\d/\d{4})|',$contents,$matches,PREG_SET_ORDER); foreach ($matches as $value) { printf("Start time: %s\nStart date: %s\n End time: %s\n End date: %s\n\n", $value[1],$value[2],$value[3],$value[4]); } Quote Link to comment Share on other sites More sharing options...
Dragen Posted April 9, 2007 Author Share Posted April 9, 2007 thanks. That works.. could you please explain to me what this actually means? preg_match_all('|(\d\d:\d\d) (\d\d/\d\d/\d{4})\s+(\d\d:\d\d) (\d\d/\d\d/\d{4})|',$contents,$matches,PREG_SET_ORDER); I can't quite figure it out and if I'm told what it means then I can learn from it easier. thanks Quote Link to comment Share on other sites More sharing options...
Dragen Posted April 9, 2007 Author Share Posted April 9, 2007 actually, I think I've got it now... preg_match_all('|(\d\d:\d\d) (\d\d/\d\d/\d{4})\s+(\d\d:\d\d) (\d\d/\d\d/\d{4})|',$contents,$matches,PREG_SET_ORDER); The \d means number. {4} is the blank line. not sure what the \s+ does though Quote Link to comment Share on other sites More sharing options...
Wildbug Posted April 9, 2007 Share Posted April 9, 2007 \d is a numerical digit, same as the character class [0-9] {4} is a quantifier. \d{4} means "four digits" (the year). It's equivalent to \d\d\d\d, but takes less space. \s+ means "one or more whitespace characters." \s is a whitespace character -- tab, space, return, both \r and \n. The plus sign is also a quantifier, meaning "one or more." This matches the line break between the start and end timestamps. The parentheses, in this case, capture the subpatterns for inclusion in the $matches array. More on quantifiers (not all relevant to the preceeding pattern): * means "zero or more," same as {0,}. ? means "zero or one," same as {0,1} (Edit: forgot this one.) + means "one or more," same as {1,}. {5,10} means "from five to ten occurences." {,50} means "a maximum of 50 occurences (including zero)." {50,} means "at least 50 occurences." Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.