int fseek ( resource $handle , int $offset [, int $whence = SEEK_SET ] )
| 参数 | 描述 |
|---|---|
handle |
文件指针资源,通常由fopen()函数创建 |
offset |
偏移量,表示要移动的字节数 |
whence |
偏移量参考位置,可选值:
|
| 常量 | 值 | 描述 | 示例 |
|---|---|---|---|
SEEK_SET |
0 | 从文件开头计算偏移量 | fseek($fp, 100, SEEK_SET) - 移动到第100字节 |
SEEK_CUR |
1 | 从当前位置计算偏移量 | fseek($fp, 50, SEEK_CUR) - 从当前位置向前移动50字节 |
SEEK_END |
2 | 从文件末尾计算偏移量 | fseek($fp, -20, SEEK_END) - 移动到文件末尾前20字节 |
<?php
// 创建测试文件
$content = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
file_put_contents('test.txt', $content);
$handle = fopen('test.txt', 'r');
if (!$handle) {
die('无法打开文件');
}
echo "文件内容: " . htmlspecialchars($content) . "<br><br>";
// 1. 使用SEEK_SET(默认) - 从文件开头
fseek($handle, 5, SEEK_SET);
echo "移动到第5字节: " . htmlspecialchars(fread($handle, 1)) . "<br>"; // 输出: 5
// 2. 使用SEEK_CUR - 从当前位置
fseek($handle, 3, SEEK_CUR);
echo "从当前位置向前移动3字节: " . htmlspecialchars(fread($handle, 1)) . "<br>"; // 输出: 9
// 3. 使用SEEK_END - 从文件末尾
fseek($handle, -5, SEEK_END);
echo "移动到文件末尾前5字节: " . htmlspecialchars(fread($handle, 1)) . "<br>"; // 输出: V
// 4. 负偏移量(只能在SEEK_END中使用,其他情况下会出错)
fseek($handle, -10, SEEK_SET); // 这会失败
echo "负偏移量测试: " . (fseek($handle, -10, SEEK_SET) === -1 ? '失败' : '成功') . "<br>";
fclose($handle);
unlink('test.txt');
?>
<?php
// 创建测试文件
$content = <<<EOT
这是一个测试文件,包含多行内容。
第二行:这里有一些数据。
第三行:这是另一行数据。
第四行:文件读取示例。
第五行:最后一行内容。
EOT;
file_put_contents('sample.txt', $content);
function readFileChunk($filename, $start, $length) {
$handle = fopen($filename, 'r');
if (!$handle) return false;
// 移动到指定位置
if (fseek($handle, $start, SEEK_SET) === -1) {
fclose($handle);
return false;
}
// 读取指定长度的内容
$chunk = fread($handle, $length);
fclose($handle);
return $chunk;
}
// 使用示例
echo "<h5>读取文件的特定部分:</h5>";
// 读取从第30字节开始的20个字节
$chunk1 = readFileChunk('sample.txt', 30, 20);
echo "从第30字节开始的20字节: " . htmlspecialchars($chunk1) . "<br><br>";
// 读取文件末尾的15个字节
$filesize = filesize('sample.txt');
$chunk2 = readFileChunk('sample.txt', $filesize - 15, 15);
echo "文件末尾的15字节: " . htmlspecialchars($chunk2) . "<br><br>";
// 读取整个文件(分块读取)
$handle = fopen('sample.txt', 'r');
echo "分块读取文件:<br>";
$chunkSize = 20;
$position = 0;
while (!feof($handle)) {
fseek($handle, $position);
$chunk = fread($handle, $chunkSize);
if ($chunk !== false && strlen($chunk) > 0) {
echo "位置 {$position}: " . htmlspecialchars($chunk) . "<br>";
$position += $chunkSize;
}
}
fclose($handle);
unlink('sample.txt');
?>
<?php
// 创建二进制文件
$binaryData = '';
for ($i = 0; $i < 256; $i++) {
$binaryData .= chr($i); // 0x00 到 0xFF
}
file_put_contents('binary.dat', $binaryData);
// 读取二进制文件的特定位置
function readBinaryAtPosition($filename, $position, $length = 1) {
$handle = fopen($filename, 'rb'); // 二进制模式
if (!$handle) return false;
if (fseek($handle, $position, SEEK_SET) === -1) {
fclose($handle);
return false;
}
$data = fread($handle, $length);
fclose($handle);
return $data;
}
// 使用示例
echo "<h5>二进制文件操作:</h5>";
// 读取特定位置的字节
echo "位置 65 的字节: ";
$byte = readBinaryAtPosition('binary.dat', 65);
echo "ASCII: " . ord($byte) . " (" . htmlspecialchars($byte) . ")<br>";
// 读取文件头(前4个字节)
echo "文件头 (前4字节): ";
$header = readBinaryAtPosition('binary.dat', 0, 4);
for ($i = 0; $i < strlen($header); $i++) {
echo sprintf('%02X ', ord($header[$i]));
}
echo "<br>";
// 读取文件尾(最后4个字节)
echo "文件尾 (最后4字节): ";
$filesize = filesize('binary.dat');
$footer = readBinaryAtPosition('binary.dat', $filesize - 4, 4);
for ($i = 0; $i < strlen($footer); $i++) {
echo sprintf('%02X ', ord($footer[$i]));
}
echo "<br>";
// 搜索特定字节值
function findByteInBinaryFile($filename, $searchByte) {
$handle = fopen($filename, 'rb');
if (!$handle) return false;
$position = 0;
while (!feof($handle)) {
$byte = fread($handle, 1);
if ($byte === false) break;
if (ord($byte) === $searchByte) {
fclose($handle);
return $position;
}
$position++;
}
fclose($handle);
return false;
}
$searchFor = 0x41; // 搜索 'A' 的ASCII值
$foundAt = findByteInBinaryFile('binary.dat', $searchFor);
if ($foundAt !== false) {
echo "找到字节 0x" . dechex($searchFor) . " 在位置: {$foundAt}<br>";
}
unlink('binary.dat');
?>
<?php
class RandomAccessFile {
private $handle;
private $filename;
private $mode;
private $position = 0;
public function __construct($filename, $mode = 'r') {
$this->filename = $filename;
$this->mode = $mode;
$this->handle = fopen($filename, $mode);
if (!$this->handle) {
throw new Exception("无法打开文件: {$filename}");
}
}
/**
* 移动到指定位置
*/
public function seek($offset, $whence = SEEK_SET) {
$result = fseek($this->handle, $offset, $whence);
if ($result === 0) {
$this->position = ftell($this->handle);
return true;
}
return false;
}
/**
* 读取指定长度的数据
*/
public function read($length) {
$data = fread($this->handle, $length);
if ($data !== false) {
$this->position += strlen($data);
}
return $data;
}
/**
* 写入数据
*/
public function write($data) {
$bytes = fwrite($this->handle, $data);
if ($bytes !== false) {
$this->position += $bytes;
}
return $bytes;
}
/**
* 获取当前位置
*/
public function getPosition() {
return ftell($this->handle);
}
/**
* 获取文件大小
*/
public function getSize() {
$current = $this->getPosition();
fseek($this->handle, 0, SEEK_END);
$size = ftell($this->handle);
$this->seek($current);
return $size;
}
/**
* 读取一行
*/
public function readLine() {
$line = fgets($this->handle);
if ($line !== false) {
$this->position += strlen($line);
}
return $line;
}
/**
* 关闭文件
*/
public function close() {
if ($this->handle) {
fclose($this->handle);
$this->handle = null;
}
}
/**
* 跳转到文件开头
*/
public function rewind() {
return $this->seek(0, SEEK_SET);
}
/**
* 跳转到文件末尾
*/
public function end() {
return $this->seek(0, SEEK_END);
}
public function __destruct() {
$this->close();
}
}
// 使用示例
try {
// 创建测试文件
$testData = "Line 1: Hello World\nLine 2: PHP fseek Example\nLine 3: Random Access\nLine 4: End of File";
file_put_contents('testfile.txt', $testData);
$file = new RandomAccessFile('testfile.txt', 'r+');
echo "<h5>随机文件访问示例:</h5>";
// 读取第一行
echo "第一行: " . htmlspecialchars($file->readLine()) . "<br>";
// 移动到第30字节
$file->seek(30);
echo "第30字节开始读取: " . htmlspecialchars($file->read(10)) . "<br>";
// 获取当前位置
echo "当前位置: " . $file->getPosition() . "<br>";
// 获取文件大小
echo "文件大小: " . $file->getSize() . " 字节<br>";
// 移动到文件末尾
$file->end();
echo "移动到文件末尾,位置: " . $file->getPosition() . "<br>";
// 从末尾向前移动并读取
$file->seek(-15, SEEK_END);
echo "文件末尾前15字节: " . htmlspecialchars($file->read(15)) . "<br>";
// 跳回文件开头
$file->rewind();
echo "重新回到文件开头,读取: " . htmlspecialchars($file->read(5)) . "<br>";
$file->close();
unlink('testfile.txt');
} catch (Exception $e) {
echo "错误: " . $e->getMessage();
}
?>
'rb'或'wb+'等二进制模式SEEK_END一起使用,与SEEK_SET使用会导致错误flock()进行文件锁定ftell()配合使用,获取当前位置| 特性 | fseek() | rewind() |
|---|---|---|
| 功能 | 移动到文件任意位置 | 移动到文件开头 |
| 参数 | 需要偏移量和参考位置 | 不需要参数 |
| 灵活性 | 高,可精确定位 | 低,只能回到开头 |
| 错误处理 | 返回0成功,-1失败 | 成功返回true,失败返回false |
| 使用场景 | 随机文件访问 | 重新读取文件 |
ftell() - 返回文件指针读/写的位置rewind() - 倒回文件指针的位置fopen() - 打开文件或URLfread() - 读取文件(二进制安全)fwrite() - 写入文件feof() - 测试文件指针是否到达文件末尾stat() - 获取文件信息解析图片、音频、视频等二进制文件的特定部分。
从大型日志文件的特定位置开始读取或搜索。
在索引文件中快速定位和读取数据记录。
实现文本编辑器的跳转到行、跳转到位置功能。