PHP fflush() 函数

说明: fflush() 函数用于将缓冲内容输出到文件,强制将缓冲区的数据写入文件系统。

语法

bool fflush ( resource $stream )

参数说明

参数 描述 必需
stream fopen() 打开的文件指针

返回值

  • 成功时返回 TRUE
  • 失败时返回 FALSE

工作原理

文件缓冲机制:
  1. 缓冲区:操作系统和标准库为了提高性能,会对文件写入进行缓冲
  2. 延迟写入:数据不会立即写入磁盘,而是先存储在内存缓冲区
  3. fflush()的作用:强制将缓冲区中的数据写入磁盘
  4. 自动刷新:缓冲区满、文件关闭或程序正常结束时,缓冲区会自动刷新

为什么需要fflush()? 在需要确保数据立即写入磁盘的场景(如日志记录、实时数据存储)中,fflush()可以防止数据丢失。

注意事项

  • fflush() 只能用于可写的文件流
  • 在某些操作系统或文件系统上,fflush() 可能不会立即将数据写入物理磁盘
  • 过度使用 fflush() 会影响性能,因为它会频繁进行磁盘I/O操作
  • 网络流(如HTTP、FTP)通常有自己的缓冲机制,fflush() 的行为可能不同
  • fflush() 不会刷新 PHP 的输出缓冲(ob_flush() 用于此目的)
  • 文件必须以写入模式打开(如 "w"、"a"、"r+"、"w+"、"a+" 等)

示例

示例 1:基本使用 - 确保数据写入

<?php
// 打开文件进行写入
$filename = "log.txt";
$handle = fopen($filename, "a");

if ($handle) {
    echo "文件打开成功,开始写入数据...\n";

    // 写入数据
    $log_entry = "[" . date('Y-m-d H:i:s') . "] 用户登录\n";
    fwrite($handle, $log_entry);

    echo "数据写入缓冲区完成\n";

    // 检查文件大小(可能还没有更新)
    $size_before = filesize($filename);
    echo "刷新前文件大小: " . $size_before . " 字节\n";

    // 强制刷新缓冲区到磁盘
    if (fflush($handle)) {
        echo "✅ 缓冲区已刷新到磁盘\n";

        // 清除文件状态缓存
        clearstatcache();

        // 检查文件大小(应该已更新)
        $size_after = filesize($filename);
        echo "刷新后文件大小: " . $size_after . " 字节\n";

        if ($size_after > $size_before) {
            echo "✅ 确认数据已写入磁盘\n";
        }
    } else {
        echo "❌ 缓冲区刷新失败\n";
    }

    // 关闭文件
    fclose($handle);
} else {
    echo "无法打开文件: " . $filename . "\n";
}

// 清理测试文件
unlink($filename);
?>

示例 2:实时日志记录系统

<?php
/**
 * 实时日志记录器类
 * 使用fflush()确保日志立即写入磁盘
 */
class RealtimeLogger {
    private $handle;
    private $filename;
    private $autoFlush;

    public function __construct($filename, $autoFlush = true) {
        $this->filename = $filename;
        $this->autoFlush = $autoFlush;

        // 以追加模式打开文件
        $this->handle = fopen($filename, "a");
        if (!$this->handle) {
            throw new Exception("无法打开日志文件: " . $filename);
        }

        // 写入日志文件头
        fwrite($this->handle, "=== 日志开始于 " . date('Y-m-d H:i:s') . " ===\n");
        if ($this->autoFlush) {
            fflush($this->handle);
        }
    }

    /**
     * 写入日志并可选地刷新缓冲区
     */
    public function log($message, $level = "INFO") {
        $timestamp = date('Y-m-d H:i:s');
        $log_entry = sprintf("[%s] [%s] %s\n", $timestamp, $level, $message);

        $bytes_written = fwrite($this->handle, $log_entry);

        if ($bytes_written === false) {
            return false;
        }

        // 如果启用自动刷新,立即写入磁盘
        if ($this->autoFlush) {
            return fflush($this->handle);
        }

        return true;
    }

    /**
     * 手动刷新缓冲区
     */
    public function flush() {
        if ($this->handle) {
            return fflush($this->handle);
        }
        return false;
    }

    /**
     * 关闭日志文件
     */
    public function close() {
        if ($this->handle) {
            // 写入结束标记
            fwrite($this->handle, "=== 日志结束于 " . date('Y-m-d H:i:s') . " ===\n\n");
            fflush($this->handle);
            fclose($this->handle);
            $this->handle = null;
        }
    }

    public function __destruct() {
        $this->close();
    }

    /**
     * 获取日志文件统计信息
     */
    public function getStats() {
        if (!file_exists($this->filename)) {
            return false;
        }

        clearstatcache();
        return [
            'filename' => $this->filename,
            'size' => filesize($this->filename),
            'modified' => date('Y-m-d H:i:s', filemtime($this->filename)),
            'is_writable' => is_writable($this->filename)
        ];
    }
}

// 使用示例
echo "实时日志记录器演示:\n";
echo "========================\n";

try {
    // 创建日志记录器(启用自动刷新)
    $logger = new RealtimeLogger("app.log", true);

    // 记录一些事件
    $events = [
        ["用户登录成功", "INFO"],
        ["数据库连接已建立", "DEBUG"],
        ["处理用户请求 #1001", "INFO"],
        ["警告:内存使用率较高", "WARNING"],
        ["错误:数据库查询失败", "ERROR"]
    ];

    foreach ($events as $event) {
        list($message, $level) = $event;
        $logger->log($message, $level);
        echo "已记录: [$level] $message\n";

        // 模拟实时性 - 每0.5秒记录一条
        usleep(500000);
    }

    // 手动刷新(如果自动刷新已启用,这一步是多余的)
    $logger->flush();

    // 获取统计信息
    $stats = $logger->getStats();
    if ($stats) {
        echo "\n日志文件统计:\n";
        echo "文件名: " . $stats['filename'] . "\n";
        echo "大小: " . $stats['size'] . " 字节\n";
        echo "最后修改: " . $stats['modified'] . "\n";
        echo "可写: " . ($stats['is_writable'] ? '是' : '否') . "\n";
    }

    // 自动关闭(通过析构函数)
    unset($logger);

    // 显示日志内容
    echo "\n日志文件内容:\n";
    echo file_get_contents("app.log");

} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
}

// 清理
if (file_exists("app.log")) {
    unlink("app.log");
}
?>

示例 3:性能测试 - 有缓冲 vs 无缓冲

<?php
/**
 * 文件写入性能测试
 * 比较有缓冲和无缓冲(使用fflush)的性能差异
 */
function file_write_performance_test($filename, $iterations = 1000, $data_size = 1024) {
    $results = [];

    // 测试数据
    $test_data = str_repeat('A', $data_size);

    echo "文件写入性能测试\n";
    echo "================\n";
    echo "测试文件: $filename\n";
    echo "迭代次数: $iterations\n";
    echo "每次写入: $data_size 字节\n";
    echo "总数据量: " . ($iterations * $data_size) . " 字节\n\n";

    // 测试1:使用缓冲(默认行为)
    echo "测试1: 使用缓冲(默认)\n";
    $handle1 = fopen($filename . "_buffered.txt", "w");
    $start1 = microtime(true);

    for ($i = 0; $i < $iterations; $i++) {
        fwrite($handle1, $test_data);
    }

    fclose($handle1);
    $end1 = microtime(true);
    $time1 = $end1 - $start1;

    echo "时间: " . round($time1, 4) . " 秒\n";
    echo "速度: " . round(($iterations * $data_size) / $time1 / 1024, 2) . " KB/秒\n\n";

    // 测试2:每次写入后刷新(无缓冲)
    echo "测试2: 每次写入后刷新(无缓冲)\n";
    $handle2 = fopen($filename . "_unbuffered.txt", "w");
    $start2 = microtime(true);

    for ($i = 0; $i < $iterations; $i++) {
        fwrite($handle2, $test_data);
        fflush($handle2); // 每次写入后刷新
    }

    fclose($handle2);
    $end2 = microtime(true);
    $time2 = $end2 - $start2;

    echo "时间: " . round($time2, 4) . " 秒\n";
    echo "速度: " . round(($iterations * $data_size) / $time2 / 1024, 2) . " KB/秒\n\n";

    // 测试3:每N次写入后刷新
    echo "测试3: 每10次写入后刷新\n";
    $handle3 = fopen($filename . "_batch.txt", "w");
    $start3 = microtime(true);
    $flush_interval = 10;

    for ($i = 0; $i < $iterations; $i++) {
        fwrite($handle3, $test_data);

        if ($i % $flush_interval == 0) {
            fflush($handle3);
        }
    }

    fclose($handle3);
    $end3 = microtime(true);
    $time3 = $end3 - $start3;

    echo "时间: " . round($time3, 4) . " 秒\n";
    echo "速度: " . round(($iterations * $data_size) / $time3 / 1024, 2) . " KB/秒\n\n";

    // 清理测试文件
    unlink($filename . "_buffered.txt");
    unlink($filename . "_unbuffered.txt");
    unlink($filename . "_batch.txt");

    return [
        'buffered' => $time1,
        'unbuffered' => $time2,
        'batch' => $time3,
        'recommendation' => $time1 < $time2 ? '使用缓冲' : '使用无缓冲'
    ];
}

// 运行性能测试
$results = file_write_performance_test("test_perf", 100, 512);

echo "性能对比总结:\n";
echo "==============\n";
echo "缓冲写入速度最快: " . ($results['recommendation'] == '使用缓冲' ? '是' : '否') . "\n";
echo "缓冲 vs 无缓冲时间比: " . round($results['buffered'] / $results['unbuffered'], 2) . "\n";
echo "建议: " . $results['recommendation'] . "\n";
echo "\n注意: 实际性能取决于磁盘速度、操作系统和文件系统\n";
?>

示例 4:事务性文件写入

<?php
/**
 * 事务性文件写入类
 * 确保数据要么完全写入,要么完全不写入
 */
class TransactionalFileWriter {
    private $tempHandle;
    private $tempFilename;
    private $targetFilename;
    private $committed = false;

    public function __construct($targetFilename) {
        $this->targetFilename = $targetFilename;

        // 创建临时文件
        $this->tempFilename = tempnam(sys_get_temp_dir(), 'txn_');
        $this->tempHandle = fopen($this->tempFilename, "w");

        if (!$this->tempHandle) {
            throw new Exception("无法创建临时文件");
        }
    }

    /**
     * 写入数据到临时文件
     */
    public function write($data) {
        if ($this->committed) {
            throw new Exception("事务已提交,不能继续写入");
        }

        $bytes = fwrite($this->tempHandle, $data);

        // 立即刷新以确保数据写入临时文件
        if ($bytes !== false) {
            fflush($this->tempHandle);
        }

        return $bytes;
    }

    /**
     * 提交事务 - 将临时文件移动到目标文件
     */
    public function commit() {
        if ($this->committed) {
            throw new Exception("事务已提交");
        }

        // 关闭临时文件
        fclose($this->tempHandle);

        // 使用原子操作重命名文件
        if (rename($this->tempFilename, $this->targetFilename)) {
            $this->committed = true;

            // 确保文件系统同步
            $handle = fopen($this->targetFilename, "r");
            if ($handle) {
                fflush($handle);
                fclose($handle);
            }

            return true;
        }

        return false;
    }

    /**
     * 回滚事务 - 删除临时文件
     */
    public function rollback() {
        if ($this->tempHandle) {
            fclose($this->tempHandle);
        }

        if (file_exists($this->tempFilename)) {
            unlink($this->tempFilename);
        }

        $this->tempHandle = null;
        $this->tempFilename = null;
        $this->committed = false;
    }

    public function __destruct() {
        if (!$this->committed) {
            $this->rollback();
        }
    }

    /**
     * 获取事务状态
     */
    public function getStatus() {
        $tempSize = file_exists($this->tempFilename) ? filesize($this->tempFilename) : 0;

        return [
            'target_file' => $this->targetFilename,
            'temp_file' => $this->tempFilename,
            'committed' => $this->committed,
            'temp_size' => $tempSize,
            'target_exists' => file_exists($this->targetFilename)
        ];
    }
}

// 使用示例
echo "事务性文件写入演示:\n";
echo "===================\n";

try {
    // 创建事务性写入器
    $writer = new TransactionalFileWriter("important_data.txt");

    echo "1. 事务状态:\n";
    print_r($writer->getStatus());

    // 写入一些数据
    $data = [
        "第一行重要数据\n",
        "第二行重要数据\n",
        "第三行重要数据\n"
    ];

    echo "\n2. 写入数据到临时文件...\n";
    foreach ($data as $line) {
        $bytes = $writer->write($line);
        echo "  写入 " . $bytes . " 字节: " . trim($line) . "\n";
    }

    echo "\n3. 提交前的事务状态:\n";
    $status_before = $writer->getStatus();
    echo "   临时文件大小: " . $status_before['temp_size'] . " 字节\n";
    echo "   目标文件存在: " . ($status_before['target_exists'] ? '是' : '否') . "\n";

    echo "\n4. 提交事务...\n";
    if ($writer->commit()) {
        echo "   ✅ 事务提交成功\n";
    } else {
        echo "   ❌ 事务提交失败\n";
    }

    echo "\n5. 提交后的事务状态:\n";
    $status_after = $writer->getStatus();
    print_r($status_after);

    // 显示最终文件内容
    echo "\n6. 最终文件内容:\n";
    if (file_exists("important_data.txt")) {
        echo file_get_contents("important_data.txt");
    }

} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
}

// 清理测试文件
if (file_exists("important_data.txt")) {
    unlink("important_data.txt");
}

echo "\n\n演示回滚场景:\n";
echo "===================\n";

try {
    $writer2 = new TransactionalFileWriter("rolled_back.txt");
    $writer2->write("这条数据应该被回滚\n");

    echo "写入数据后,但不提交...\n";

    // 显式回滚
    $writer2->rollback();

    echo "事务已回滚\n";

    $status = $writer2->getStatus();
    echo "回滚后状态:\n";
    echo "目标文件存在: " . ($status['target_exists'] ? '是' : '否') . "\n";
    echo "临时文件存在: " . (file_exists($status['temp_file'] ?? '') ? '是' : '否') . "\n";

} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
}
?>

示例 5:网络流中的fflush()使用

<?php
/**
 * 网络流处理类
 * 演示在网络流中使用fflush()
 */
class NetworkStreamHandler {
    private $handle;
    private $url;
    private $timeout = 10;

    public function __construct($url, $timeout = 10) {
        $this->url = $url;
        $this->timeout = $timeout;
    }

    /**
     * 连接到远程服务器并发送数据
     */
    public function connectAndSend($data) {
        // 创建流上下文
        $context = stream_context_create([
            'http' => [
                'method' => 'POST',
                'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
                            "Connection: close\r\n",
                'content' => http_build_query(['data' => $data]),
                'timeout' => $this->timeout
            ]
        ]);

        // 打开网络流
        $this->handle = fopen($this->url, 'r', false, $context);

        if (!$this->handle) {
            throw new Exception("无法连接到: " . $this->url);
        }

        return $this->handle;
    }

    /**
     * 发送数据并立即刷新
     */
    public function sendWithFlush($data) {
        // 注意:对于HTTP流,fflush()的行为可能不同
        // 通常需要在发送数据后使用
        $result = $this->connectAndSend($data);

        if ($result) {
            // 尝试刷新(在某些流实现中可能有效)
            $flushed = fflush($this->handle);

            // 读取响应
            $response = stream_get_contents($this->handle);

            fclose($this->handle);
            $this->handle = null;

            return [
                'flushed' => $flushed,
                'response' => $response
            ];
        }

        return false;
    }

    /**
     * 演示TCP套接字连接(需要socket扩展)
     */
    public function tcpSend($host, $port, $data) {
        // 创建TCP套接字连接
        $this->handle = fsockopen($host, $port, $errno, $errstr, $this->timeout);

        if (!$this->handle) {
            throw new Exception("无法连接到 $host:$port - $errstr ($errno)");
        }

        // 设置非阻塞模式(可选)
        stream_set_blocking($this->handle, false);

        // 发送数据
        fwrite($this->handle, $data . "\n");

        // 立即刷新,确保数据发送
        $flushed = fflush($this->handle);

        // 等待响应
        $response = '';
        $start = time();

        while ((time() - $start) < $this->timeout) {
            $chunk = fread($this->handle, 1024);
            if ($chunk !== false && strlen($chunk) > 0) {
                $response .= $chunk;
            } else {
                break;
            }
        }

        fclose($this->handle);
        $this->handle = null;

        return [
            'flushed' => $flushed,
            'response' => $response,
            'data_sent' => $data
        ];
    }
}

// 使用示例(演示模式)
echo "网络流fflush()演示\n";
echo "==================\n\n";

echo "1. HTTP流演示(模拟):\n";
echo "   注意:HTTP流通常有自己的缓冲机制\n";
echo "   fflush()在某些HTTP流实现中可能不会立即发送数据\n\n";

echo "2. TCP套接字演示(模拟):\n";

try {
    $handler = new NetworkStreamHandler("http://example.com", 5);

    // 模拟TCP发送
    echo "   模拟发送数据到服务器...\n";

    // 注意:实际运行需要真实的服务器地址
    // 这里只是演示代码结构
    /*
    $result = $handler->tcpSend("127.0.0.1", 8080, "Hello Server");
    if ($result) {
        echo "   刷新状态: " . ($result['flushed'] ? '成功' : '失败') . "\n";
        echo "   响应: " . substr($result['response'], 0, 100) . "...\n";
    }
    */

    echo "   由于需要真实服务器连接,此处跳过实际执行\n";

} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
}

echo "\n重要提示:\n";
echo "对于网络流,fflush()的行为取决于:\n";
echo "1. 流类型(HTTP、FTP、TCP等)\n";
echo "2. PHP配置和流包装器\n";
echo "3. 操作系统和网络设置\n";
echo "4. 服务器端的缓冲策略\n";
?>

示例 6:多进程/多线程环境下的文件同步

<?php
/**
 * 多进程安全的文件写入器
 * 使用文件锁和fflush()确保多进程环境下的数据一致性
 */
class MultiprocessFileWriter {
    private $filename;
    private $lockHandle;
    private $writeHandle;

    public function __construct($filename) {
        $this->filename = $filename;
    }

    /**
     * 安全写入数据(使用文件锁)
     */
    public function safeWrite($data, $timeout = 5) {
        $startTime = microtime(true);
        $locked = false;

        // 尝试获取锁
        while ((microtime(true) - $startTime) < $timeout) {
            $this->lockHandle = fopen($this->filename . '.lock', 'w');

            if (flock($this->lockHandle, LOCK_EX | LOCK_NB)) {
                $locked = true;
                break;
            }

            fclose($this->lockHandle);
            usleep(100000); // 等待100ms后重试
        }

        if (!$locked) {
            throw new Exception("获取文件锁超时");
        }

        try {
            // 打开文件进行写入
            $this->writeHandle = fopen($this->filename, 'a');
            if (!$this->writeHandle) {
                throw new Exception("无法打开文件: " . $this->filename);
            }

            // 写入数据
            $bytes = fwrite($this->writeHandle, $data);

            if ($bytes !== false) {
                // 立即刷新到磁盘
                fflush($this->writeHandle);

                // 强制文件系统同步(如果支持)
                if (function_exists('fsync')) {
                    fsync($this->writeHandle);
                }
            }

            fclose($this->writeHandle);

            return $bytes;

        } finally {
            // 释放锁
            flock($this->lockHandle, LOCK_UN);
            fclose($this->lockHandle);

            // 删除锁文件
            if (file_exists($this->filename . '.lock')) {
                unlink($this->filename . '.lock');
            }
        }
    }

    /**
     * 批量写入多条数据
     */
    public function batchWrite($dataArray) {
        $result = [];

        foreach ($dataArray as $index => $data) {
            try {
                $bytes = $this->safeWrite($data . "\n");
                $result[$index] = [
                    'success' => true,
                    'bytes' => $bytes
                ];
            } catch (Exception $e) {
                $result[$index] = [
                    'success' => false,
                    'error' => $e->getMessage()
                ];
            }
        }

        return $result;
    }

    /**
     * 模拟多进程写入测试
     */
    public static function simulateMultiprocessTest($filename, $processCount = 3, $writesPerProcess = 5) {
        echo "多进程文件写入测试\n";
        echo "进程数: $processCount, 每个进程写入次数: $writesPerProcess\n\n";

        $results = [];

        // 创建多个"进程"(实际上是顺序执行模拟)
        for ($i = 1; $i <= $processCount; $i++) {
            echo "进程 $i 开始写入...\n";

            $writer = new MultiprocessFileWriter($filename);
            $data = [];

            for ($j = 1; $j <= $writesPerProcess; $j++) {
                $message = "进程 $i, 写入 #$j, 时间: " . microtime(true);
                $data[] = $message;
            }

            $result = $writer->batchWrite($data);
            $results[$i] = $result;

            echo "进程 $i 完成写入\n";
        }

        // 验证结果
        $allLines = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        $lineCount = count($allLines);
        $expectedCount = $processCount * $writesPerProcess;

        echo "\n验证结果:\n";
        echo "预期行数: $expectedCount\n";
        echo "实际行数: $lineCount\n";

        if ($lineCount === $expectedCount) {
            echo "✅ 所有写入成功,数据一致\n";
        } else {
            echo "❌ 数据不一致,可能发生了数据丢失或竞争条件\n";

            // 检查重复或丢失的行
            $uniqueLines = array_unique($allLines);
            $duplicateCount = $lineCount - count($uniqueLines);
            echo "重复行数: $duplicateCount\n";
        }

        // 清理测试文件
        if (file_exists($filename)) {
            unlink($filename);
        }

        return $results;
    }
}

// 运行多进程测试
echo "多进程文件同步演示:\n";
echo "==================\n\n";

MultiprocessFileWriter::simulateMultiprocessTest("multiprocess_test.log", 3, 5);

echo "\n实际应用场景:\n";
echo "1. 多进程日志记录\n";
echo "2. 数据采集系统\n";
echo "3. 并行处理任务的结果汇总\n";
echo "4. 实时监控系统\n";
?>

fflush() vs 相关函数

函数 作用 适用场景 区别
fflush() 刷新文件缓冲区到磁盘 文件写入、确保数据持久化 只刷新文件流缓冲区
ob_flush() 刷新输出缓冲区 Web输出、实时显示数据 刷新PHP输出缓冲区,不是文件缓冲区
fsync() 强制将文件数据写入磁盘 需要最高级别的数据安全 比fflush()更强力,确保数据写入物理磁盘
fclose() 关闭文件 文件操作结束 关闭文件时会自动刷新缓冲区
clearstatcache() 清除文件状态缓存 获取最新文件信息 不刷新缓冲区,只清除缓存信息

相关函数

最佳实践
  1. 权衡性能与安全性:频繁使用fflush()会影响性能,只在必要时使用
  2. 关键数据立即刷新:对于日志、事务数据等关键信息,使用fflush()确保数据不丢失
  3. 结合文件锁使用:在多进程/多线程环境中,结合flock()使用fflush()
  4. 考虑使用批处理:不要每次写入都刷新,可以每N次写入刷新一次
  5. 错误处理:检查fflush()的返回值,处理刷新失败的情况
  6. 网络流谨慎使用:网络流的fflush()行为可能不同,需要测试验证
  7. 配合fsync()使用:对于最高级别的数据安全,可以结合使用fflush()和fsync()
  8. 清理状态缓存:刷新后使用clearstatcache()获取最新的文件信息
常见使用模式
模式1:关键数据写入
// 写入关键数据并立即刷新
$handle = fopen($filename, "a");
fwrite($handle, $critical_data);
fflush($handle);  // 确保数据写入磁盘
fclose($handle);
模式2:定期刷新(批处理)
// 每N次写入刷新一次
$handle = fopen($filename, "a");
$counter = 0;
$flush_interval = 100;

foreach ($data_items as $item) {
    fwrite($handle, $item);
    $counter++;

    if ($counter % $flush_interval == 0) {
        fflush($handle);  // 定期刷新
    }
}

fclose($handle);
模式3:事务性写入
// 使用临时文件和原子操作
$temp_file = tempnam(sys_get_temp_dir(), 'tmp_');
$handle = fopen($temp_file, "w");

// 写入所有数据
foreach ($data as $chunk) {
    fwrite($handle, $chunk);
}

fflush($handle);  // 确保所有数据写入临时文件
fclose($handle);

// 原子性地重命名到目标文件
rename($temp_file, $target_file);