PHP将指定文件夹下多csv文件[即多表]导入到sqlite单文件

支持多表,中文字段,csv文件utf-8编码 逗号分隔,第一行字段以后一行一条内容

php 复制代码
<?php

class CsvToSqlite {
    private $db;
    private $csvDir;
    private $sqliteFile;
    public function __construct($csvDir, $sqliteFile) {
        $this->csvDir = rtrim($csvDir, '/');
        $this->sqliteFile = $sqliteFile;
        try {
            $this->db = new PDO("sqlite:{$this->sqliteFile}");
            $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            die("数据库连接失败: " . $e->getMessage());
        }
    }
    public function convert() {
        $csvFiles = glob($this->csvDir . '/*.csv');        
        foreach ($csvFiles as $csvFile) {
            $this->processCsvFile($csvFile);
        }        
        echo "所有CSV文件处理完成!\n";
    }
    private function processCsvFile($csvFile) {
        $tableName = pathinfo($csvFile, PATHINFO_FILENAME);
        echo "正在处理文件: {$csvFile}\n";        
        try {
            $handle = fopen($csvFile, 'r');
            if ($handle === false) throw new Exception("无法打开文件: {$csvFile}");
            $headers = fgetcsv($handle);
            if ($headers === false) throw new Exception("CSV文件为空: {$csvFile}");
            $this->createTable($tableName, $headers);
            $placeholders = str_repeat('?,', count($headers) - 1) . '?';
            $sql = "INSERT INTO {$tableName} VALUES ($placeholders)";
            $stmt = $this->db->prepare($sql);
            $this->db->beginTransaction();
            while (($row = fgetcsv($handle)) !== false) {
                if (count($row) === count($headers)) {
                    try {
                        $stmt->execute($row);
                    } catch (PDOException $e) {
                        echo "插入数据失败: " . $e->getMessage() . "\n";
                        continue;
                    }
                }
            }
            $this->db->commit();            
            fclose($handle);
            echo "表 {$tableName} 创建并导入完成\n";            
        } catch (Exception $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            echo "处理文件 {$csvFile} 时出错: " . $e->getMessage() . "\n";
        }
    }
    private function createTable($tableName, $headers) {
        $tableName = $this->sanitizeIdentifier($tableName);
        $columns = array_map([$this, 'sanitizeIdentifier'], $headers);
        $columnDefs = array_map(function($col) {
            return "{$col} TEXT";
        }, $columns);        
        $sql = "CREATE TABLE IF NOT EXISTS {$tableName} (" . 
               implode(', ', $columnDefs) . ")";        
        try {
            $this->db->exec($sql);
            $this->db->exec("DELETE FROM {$tableName}");
        } catch (PDOException $e) {
            throw new Exception("创建表失败: $sql@" . $e->getMessage());
        }
    }
    private function sanitizeIdentifier($identifier) {
        $safe = preg_replace('/[^\w\x{4e00}-\x{9fa5}]+/u', '_', $identifier);
        if (is_numeric($safe[0])) { $safe = 'col_' . $safe;}
        return Trim($safe,"_");
    }
    public function getTableRowCount($tableName) {
        $tableName = $this->sanitizeIdentifier($tableName);
        $stmt = $this->db->query("SELECT COUNT(*) FROM {$tableName}");
        return $stmt->fetchColumn();
    }
    public function __destruct() {
        $this->db = null;
    }
}

// 使用示例
try {
    $csvDir = './csv_files';
    $sqliteFile = './database.sqlite';    
    $converter = new CsvToSqlite($csvDir, $sqliteFile);    
    $converter->convert();    
} catch (Exception $e) {
    echo "发生错误: " . $e->getMessage() . "\n";
}
?>
相关推荐
从零开始的ops生活1 天前
【Day 80】Linux-NAS 和 SAN 存储
linux·运维·php
shizhenshide1 天前
为什么有时候 reCAPTCHA 通过率偏低,常见原因有哪些
开发语言·php·验证码·captcha·recaptcha·ezcaptcha
小宁爱Python1 天前
Django Web 开发系列(二):视图进阶、快捷函数与请求响应处理
前端·django·sqlite
小杰帅气1 天前
内存管理C++
jvm
YuanlongWang1 天前
C#基础——GC(垃圾回收)的工作流程与优化策略
java·jvm·c#
白露与泡影1 天前
BAT 大厂 java高频面试题汇总:JVM+Spring+ 分布式 +tomcat+MyBatis
java·jvm·spring
偶尔贪玩的骑士2 天前
Kioptrix Level 1渗透测试
linux·开发语言·网络安全·php
それども2 天前
忽略Lombok构建警告
java·开发语言·jvm
迎風吹頭髮2 天前
Linux服务器编程实践58-getnameinfo函数:通过socket地址获取主机名与服务名
开发语言·数据库·php
探索宇宙真理.2 天前
WordPress Flex QR Code Generator文件上传 | CVE-2025-10041 复现&研究
经验分享·php·安全漏洞