Archive

You are currently browsing the Miles Per Hour blog archives for June, 2008.

Jun

13

fseek()

By mike@mike-miles.com

There is this nifty function in PHP called fseek().  It allows you to set a pointer to any where in a file (a text file for example).  It comes in handy when your dealing with very large files (like log files, or config files), and today I discoverd it can be very useful if you want to search throu a file backwards.

Which was exactly what I was trying to do.  I needed to traverse a file, starting at the end.  The only solutions I could find infolved reading the whole file into an array, reversing the array and thensearching that way, which completly nullified the point of going the end of the file (I had to read the whole file into memory to get the end).

The solution I came up with, involves using fseek() and fread() (which allows you to read a file byte by byte).  With this function you give it a file, and a string to search for, and it’ll go through the file backwards byte by byte, and return the pointer (byte location in the file) of where the search string occures. (if it doesnt find the string, it’ll return FALSE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?PHP
function searchFromEnd($filename,$search){
	//first make sure that the file is there, and we can read it
	if(file_exists($filename) && is_readable($filename)){ 
		//open the file for reading
		$fp = fopen($filename,'r');
		//get the length of the search string(minus the first character)
		$size=strlen($search)-1; 
		//get first element in string
		$first=$search[0]; 
		//size of the file
		$file_size=filesize($filename); 
		//set seek pointer to end of the file - size of the string
		$seek=$file_size-$size; 
		//set found to FALSE
		$found=false;
		//while not past the begining of the file
		while($seek>=0){
			//set file pointer to seek value
			fseek($fp,$seek); 
			//read in the first byte from pointer
            $test=fread($fp,1); 
            //if byte is same as the first string character, and  back far enough in file for search length
			if($test==$first && (($seek+$size) <= $file_size) ){ 
				//append enough characters to $test to make it same size as $search
				$test.=fread($fp,$size); 
				//if test value is what we're looking for
				if(strcmp($test,$search)==0){ 
					//return position;
					$found=$seek;
					//set pointer to -1 (exit loop);
					$seek=-1; 
				}else{
					//move back a byte
					$seek--; 
				}
			}else{
				//move back a byte
				$seek--; 
			}
		}
		//close the file
		fclose($fp); 
	}
	//return FALSE or position of search string
	return $found; 
}
?>

A much better method then reading the whole file.

You can download this file from here