PHP语法高级篇(二):文件处理

文件处理是任何 Web 应用程序的重要组成部分,PHP 拥有用于创建、读取、上传和编辑文件的多个函数。本篇文章将记录文件处理的学习过程。

本篇文章内容包括:

  • 文件打开/读取
  • 文件创建/写入
  • 文件上传

一、文件打开/读取

在本节中,我们将学习如何在服务器上打开、读取和关闭文件。

1、打开文件 - fopen()

fopen() 函数用于打开文件或者 URL。

php 复制代码
fopen(
    string $filename,
    string $mode,
    bool $use_include_path = false,
    ?resource $context = null
): resource|false

fopen() 将 filename指定的名字资源绑定到一个流上。

参数

filename

必需。如果 filename 是 "scheme://..." 的格式,则被当成一个 URL,PHP 将搜索协议处理器(也被称为封装协议)来处理此模式。如果该协议尚未注册封装协议,PHP 将发出一条消息来帮助检查脚本中潜在的问题并将 filename 当成一个普通的文件名继续执行下去。

mode

必需。mode 参数指定了所要求到该流的访问类型。如下表所示:

|----|---------------------------------------------------------|
| 模式 | 描述 |
| r | 只读方式打开文件。文件指针指向文件开头。 |
| w | 只写方式打开文件。 如果文件不存在则创建新文件。 如果文件存在,则清空文件内容。 文件指针指向文件开头。 |
| a | 只写方式打开文件。 如果文件不存在,则创建新文件。 如果文件存在,则不会清空文件内容。 文件指针指向文件末尾。 |
| x | 以只写方式创建新文件。 如果文件已存在,则返回 FALSE 并产生错误。 |
| r+ | 读写方式打开文件。文件指针指向文件开头。 |
| w+ | 读写方式打开文件。 如果文件不存在则创建新文件。 如果文件存在,则清空文件内容。 文件指针指向文件开头。 |
| a+ | 读写方式打开文件。 如果文件不存在则创建新文件。 如果文件存在,则不会清空文件内容。 文件指针指向文件末尾。 |
| x+ | 以读写方式创建新文件。 如果文件已存在,则返回 FALSE 并产生错误。 |

use_include_path

可选。如果需要在 include_path中搜寻文件的话,可以将可选的第三个参数 use_include_path 设为 '1' 或 true。

context

可选。上下文流(context stream) resource。

返回值

成功时返回文件指针资源, 或者在失败时返回 false。

2、读取文件 - fread()

使用 fopen() 函数打开文件后,接下来我们就可以开始读取文件内容了。

fread() 函数从打开的文件中读取内容。

php 复制代码
fread(resource $stream, int $length): string|false

fread() 从文件指针 stream 读取最多 length 个字节。该函数在遇上以下几种情况时停止读取文件:

  • 读取了 length个字节
  • 到达了文件末尾(EOF)

参数

stream

必需。文件系统指针。

length

必需。最多读取 length 个字节。

返回值

返回所读取的字符串, 或者在失败时返回 false。

3、关闭文件 - fclose()

使用 fopen() 函数打开的文件在完成操作后,需要将打开的文件进行关闭。

fclose() 函数用于关闭打开的文件。

php 复制代码
fclose(resource $stream): bool

stream指向的文件关闭。

参数

stream

必需。文件系统指针。

返回值

成功时返回 true, 或者在失败时返回 false。

接下来我们通过一个示例来看一下如何使用 fopen()、fread()、fclose() 函数来完成对文件的读取操作。

首先,准备一个文本文件,向其中写入一些内容,这个文件将作为稍后文件读取时使用的测试文件。将文件命名为 test.txt(其它的什么名字都可以),内容如下(随便写点什么内容就行):

php 复制代码
AJAX = Asynchronous JavaScript and XML
CSS = Cascading Style Sheets
HTML = Hyper Text Markup Language
PHP = PHP Hypertext Preprocessor
SQL = Structured Query Language
SVG = Scalable Vector Graphics
XML = EXtensible Markup Language

接下来我们来写读取文件内容的代码:

php 复制代码
$file_name = "test.txt";
$file = fopen($file_name, "r"); // 以只读的方式打开 test.txt 文件
// filesize(文件路径):取得指定文件的大小。 
$content = fread($file, filesize($file_name)); // 读取全部文件内容
fclose($file); // 关闭打开的文件

echo $content;

4、读取单行 - fgets()

fgets() 函数用于从文件中读取一行。相比于 fread() 函数,fgets() 函数更适合处理文本文件。

php 复制代码
fgets(resource $stream, ?int $length = null): string|false

从文件指针中读取一行。

参数

stream

必需。文件系统指针。

length

可选。从指向的文件中读取一行并返回长度最多为 length - 1 字节的字符串。碰到换行符、EOF 或者已经读取了 length - 1 字节后停止(看先碰到那一种情况)。如果没有指定 length,则默认为 1K,或者说 1024 字节。

返回值

从指向的文件中读取了 length - 1 字节后返回字符串。如果文件指针中没有更多的数据了则返回 false。

示例

php 复制代码
$file = fopen("test.txt", "r"); // 以只读的方式打开 test.txt 文件
$content = fgets($file); // 读取一行内容
fclose($file); // 关闭打开的文件

echo $content;

注意:在调用 fgets() 函数后,文件指针已移至下一行。

5、读取单个字符 - fgetc()

我们除了可以用 fgets() 函数读取一行内容外,还可以使用 fgetc() 函数从文件中读取单个字符。

php 复制代码
fgetc(resource $stream): string|false

从文件中读取单个字符。

参数

stream

必需。文件系统指针。

返回值

返回一个包含有一个字符的字符串,该字符从 stream 指向的文件中得到。碰到 EOF 则返回 false。

示例

php 复制代码
$file = fopen("test.txt", "r"); // 以只读的方式打开 test.txt 文件
$content = fgetc($file); // 读取一个字符内容
fclose($file); // 关闭打开的文件

echo $content;

注意:在调用 fgetc() 函数后,文件指针移至下一个字符。

6、检查文件末尾 - feof()

feof() 函数用于检查是否已达到"文件末尾"(EOF),在遍历读取文件内容时十分有用。

php 复制代码
feof(resource $stream): bool

测试文件指针是否到了文件结束的位。

参数

stream

必需。文件系统指针。

返回值

如果文件指针到了 EOF 或者出错时则返回 true,否则返回一个错误(包括 socket 超时),其它情况则返回 false。

示例 逐行读取 test.txt 文件内容,直至文件末尾

php 复制代码
$file = fopen("test.txt", "r");
while (!feof($file)) {
    $content = fgets($file);
    echo "$content <br>";
}
fclose($file);

二、文件创建/写入

在本节中,我们将学习如何在服务器上创建和写入文件。

1、创建文件 - fopen()

fopen() 函数也用于创建文件。如果在不存在的文件上使用 fopen(),并且该文件是打开以进行写入(w)或追加(a)的,那么它将创建该文件。

下面的示例创建了一个名为 "testfile.txt" 的新文件,该文件将在 PHP 代码所在的同一目录中创建:

php 复制代码
$file = fopen("testfile.txt", "w");

如果在运行此代码时遇到错误,请检查是否已授予 PHP 文件向硬盘写入信息的权限。

2、写入文件 - fwrite()

fwrite() 函数用于向文件写入。

php 复制代码
fwrite(resource $stream, string $data, ?int $length = null): int|false

fwrite() 把 data 的内容写入文件指针 stream 处。

参数

stream

必需。文件系统指针。

data

必需。要写入的字符串。

length

可选。当写入了 length 个字节或者写完了 string 以后,写入就会停止,看先碰到哪种情况。

返回值

fwrite() 返回写入的字符数, 或者在失败时返回 false。

示例

php 复制代码
$file = fopen("testfile.txt", "w");
fwrite($file, "Hello World!\n");
fwrite($file, "你好,世界!\n");
fclose($file);

三、文件上传

在本节中,我们将学习如何处理文件上传。

1、配置 "php.ini" 文件

首先,确保 PHP 配置为允许文件上传。在你的 "php.ini" 文件中,搜索 file_uploads 指令,并将其设置为 On:

php 复制代码
file_uploads = On

2、创建 HTML 表单

接下来,创建一个 HTML 表单,允许用户选择要上传的文件:

html 复制代码
<!DOCTYPE html>
<html>
    <meta charset="utf-8">
    <body>
        <form action="upload.php" method="post" enctype="multipart/form-data">
            选择上传的文件:
            <input type="file" name="userfile">
            <input type="submit" value="上传文件">
        </form>
    </body>
</html>

上述 HTML 表单需要遵循的一些规则:

  • 确保表单使用 method="post"
  • 表单还需要以下属性:enctype="multipart/form-data"。它指定提交表单时要使用的 content-type

如果不满足上述要求,文件上传将无法工作。

上述表单将数据发送到名为 "upload.php" 的文件,接下来我们就来创建该文件。

3、创建上传文件的 PHP 脚本

全局变量 $_FILES 包含有所有上传的文件信息。数组的内容来自以下范例表单。我们假设文件上传字段的名称如下例所示,为 userfile。名称可随意命名。

|--------------------------------------|---------------------------------------------------------------------------------|
| _FILES\['userfile'\]\['name'\] | 客户端机器文件的原名称。 | | _FILES['userfile']['type'] | 文件的 MIME 类型,如果浏览器提供此信息的话。一个例子是"image/gif"。不过此 MIME 类型在 PHP 端并不检查,因此不要想当然认为有这个值。 |
| _FILES\['userfile'\]\['size'\] | 已上传文件的大小,单位为字节。 | | _FILES['userfile']['tmp_name'] | 文件被上传后在服务端储存的临时文件名。 |
| _FILES\['userfile'\]\['error'\] | 和该文件上传相关的错误代码。 | | _FILES['userfile']['full_path'] | 浏览器提交的完整路径。该值并不总是包含真实的目录结构,因此不能被信任。从 PHP 8.1.0 起可用。 |

创建 "upload.php" 文件来接收上传的文件。

php 复制代码
$uploaddir = 'uploads/'; // 指定上传文件要放置的目录
// basename(): 返回路径中的文件名部分
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']); // 指定要上传的文件的路径

/*
    move_uploaded_file --- 将上传的文件移动到新位置
        move_uploaded_file(string $from, string $to): bool
        本函数检查并确保由 from 指定的文件是合法的上传文件(即通过 PHP 的 HTTP POST 上传机制所上传的)。如果文件合法,则将其移动为由 to 指定的文件。 
        参数 
            from: 上传的文件的文件名。 
            to: 移动文件到这个位置。 
        返回值
            成功时返回 true。 
            如果 from 不是合法的上传文件,不会出现任何操作,move_uploaded_file() 将返回 false。 
            如果 from 是合法的上传文件,但出于某些原因无法移动,不会出现任何操作,move_uploaded_file() 将返回 false。此外还会发出一条警告。 
 */
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    echo "文件上传成功.\n";
} else {
    echo "文件上传失败!\n";
}

注意:需要在 "upload.php" 文件所在的目录中创建一个名为 "uploads" 的新目录。上传的文件将保存在那里。

接受上传文件的 PHP 脚本为了决定接下来要对该文件进行哪些操作,应该实现任何逻辑上必要的检查。例如可以用 _FILES\['userfile'\]\['size'\] 变量来排除过大或过小的文件,也可以通过 _FILES['userfile']['type'] 变量来排除文件类型不相符合上传标准的文件。

如果表单中没有选择上传的文件,则 PHP 变量 _FILES\['userfile'\]\['size'\] 的值将为 0,_FILES['userfile']['tmp_name'] 将为空。

如果该文件没有被移动到其它地方也没有被改名,则该文件将在表单请求结束时被删除。

关于文件处理的学习过程就记录到此,更多关于文件处理的函数,可以查看文件系统函数

相关推荐
BingoGo2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo3 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack3 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack4 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo4 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack5 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082855 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe5 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5