1. 完整工具代码 (sqlite_reader.php)

<?php
/**
 * SQLite 数据库读取工具
 * 功能:连接SQLite数据库,执行查询,查看表结构和数据
 */

class SQLiteReader {
    private $db;
    private $dbPath;
    private $lastError;
    
    /**
     * 构造函数
     * @param string $dbPath 数据库文件路径
     */
    public function __construct($dbPath = null) {
        $this->db = null;
        $this->dbPath = $dbPath;
        $this->lastError = '';
        
        if ($dbPath) {
            $this->connect($dbPath);
        }
    }
    
    /**
     * 连接到SQLite数据库
     * @param string $dbPath 数据库文件路径
     * @return bool 连接是否成功
     */
    public function connect($dbPath) {
        try {
            // 检查文件是否存在
            if (!file_exists($dbPath)) {
                $this->lastError = "数据库文件不存在: $dbPath";
                return false;
            }
            
            // 尝试连接数据库
            $this->db = new SQLite3($dbPath);
            $this->db->enableExceptions(true);
            $this->dbPath = $dbPath;
            
            // 测试连接
            $this->db->query('SELECT 1');
            
            return true;
        } catch (Exception $e) {
            $this->lastError = "连接失败: " . $e->getMessage();
            return false;
        }
    }
    
    /**
     * 获取所有表名
     * @return array 表名数组
     */
    public function getTables() {
        if (!$this->db) {
            $this->lastError = "未连接到数据库";
            return [];
        }
        
        try {
            $result = $this->db->query("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name");
            $tables = [];
            
            while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
                $tables[] = $row['name'];
            }
            
            return $tables;
        } catch (Exception $e) {
            $this->lastError = "获取表列表失败: " . $e->getMessage();
            return [];
        }
    }
    
    /**
     * 获取表结构
     * @param string $tableName 表名
     * @return array 表结构信息
     */
    public function getTableStructure($tableName) {
        if (!$this->db) {
            $this->lastError = "未连接到数据库";
            return [];
        }
        
        try {
            // 获取创建表的SQL语句
            $result = $this->db->query("SELECT sql FROM sqlite_master WHERE type='table' AND name='$tableName'");
            $row = $result->fetchArray(SQLITE3_ASSOC);
            $createSql = $row['sql'] ?? '';
            
            // 获取表信息
            $result = $this->db->query("PRAGMA table_info('$tableName')");
            $columns = [];
            
            while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
                $columns[] = [
                    'cid' => $row['cid'],
                    'name' => $row['name'],
                    'type' => $row['type'],
                    'notnull' => $row['notnull'],
                    'dflt_value' => $row['dflt_value'],
                    'pk' => $row['pk']
                ];
            }
            
            // 获取索引信息
            $result = $this->db->query("PRAGMA index_list('$tableName')");
            $indexes = [];
            
            while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
                $indexName = $row['name'];
                $indexResult = $this->db->query("PRAGMA index_info('$indexName')");
                $indexColumns = [];
                
                while ($indexRow = $indexResult->fetchArray(SQLITE3_ASSOC)) {
                    $indexColumns[] = $indexRow['name'];
                }
                
                $indexes[] = [
                    'name' => $indexName,
                    'unique' => $row['unique'],
                    'columns' => $indexColumns
                ];
            }
            
            return [
                'table_name' => $tableName,
                'create_sql' => $createSql,
                'columns' => $columns,
                'indexes' => $indexes
            ];
        } catch (Exception $e) {
            $this->lastError = "获取表结构失败: " . $e->getMessage();
            return [];
        }
    }
    
    /**
     * 执行SQL查询
     * @param string $sql SQL查询语句
     * @param bool $returnArray 是否返回数组(默认true)
     * @return array|SQLite3Result 查询结果
     */
    public function query($sql, $returnArray = true) {
        if (!$this->db) {
            $this->lastError = "未连接到数据库";
            return $returnArray ? [] : false;
        }
        
        try {
            $result = $this->db->query($sql);
            
            if (!$returnArray) {
                return $result;
            }
            
            // 将结果转换为数组
            $rows = [];
            while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
                $rows[] = $row;
            }
            
            return $rows;
        } catch (Exception $e) {
            $this->lastError = "查询执行失败: " . $e->getMessage();
            return $returnArray ? [] : false;
        }
    }
    
    /**
     * 获取表数据
     * @param string $tableName 表名
     * @param int $limit 限制行数(0表示无限制)
     * @param int $offset 偏移量
     * @return array 表数据
     */
    public function getTableData($tableName, $limit = 100, $offset = 0) {
        if (!$this->db) {
            $this->lastError = "未连接到数据库";
            return [];
        }
        
        try {
            $limitClause = $limit > 0 ? " LIMIT $limit OFFSET $offset" : "";
            $sql = "SELECT * FROM `$tableName` $limitClause";
            return $this->query($sql);
        } catch (Exception $e) {
            $this->lastError = "获取表数据失败: " . $e->getMessage();
            return [];
        }
    }
    
    /**
     * 统计表行数
     * @param string $tableName 表名
     * @return int 行数
     */
    public function getRowCount($tableName) {
        if (!$this->db) {
            $this->lastError = "未连接到数据库";
            return 0;
        }
        
        try {
            $result = $this->db->query("SELECT COUNT(*) as count FROM `$tableName`");
            $row = $result->fetchArray(SQLITE3_ASSOC);
            return $row['count'] ?? 0;
        } catch (Exception $e) {
            $this->lastError = "统计行数失败: " . $e->getMessage();
            return 0;
        }
    }
    
    /**
     * 导出数据为CSV格式
     * @param string $tableName 表名
     * @param string $filename 输出文件名
     * @return bool 是否成功
     */
    public function exportToCSV($tableName, $filename = null) {
        if (!$this->db) {
            $this->lastError = "未连接到数据库";
            return false;
        }
        
        if (!$filename) {
            $filename = $tableName . '_' . date('Ymd_His') . '.csv';
        }
        
        try {
            // 获取数据
            $data = $this->getTableData($tableName, 0, 0);
            if (empty($data)) {
                return false;
            }
            
            // 设置HTTP头以触发下载
            header('Content-Type: text/csv; charset=utf-8');
            header('Content-Disposition: attachment; filename="' . $filename . '"');
            
            // 打开输出流
            $output = fopen('php://output', 'w');
            
            // 添加BOM以支持Excel中的中文
            fwrite($output, "\xEF\xBB\xBF");
            
            // 写入表头
            fputcsv($output, array_keys($data[0]));
            
            // 写入数据
            foreach ($data as $row) {
                fputcsv($output, $row);
            }
            
            fclose($output);
            return true;
        } catch (Exception $e) {
            $this->lastError = "导出CSV失败: " . $e->getMessage();
            return false;
        }
    }
    
    /**
     * 导出数据为JSON格式
     * @param string $tableName 表名
     * @param bool $download 是否直接下载
     * @return string|bool JSON字符串或是否成功
     */
    public function exportToJSON($tableName, $download = false) {
        if (!$this->db) {
            $this->lastError = "未连接到数据库";
            return false;
        }
        
        try {
            // 获取数据
            $data = $this->getTableData($tableName, 0, 0);
            
            // 转换为JSON
            $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
            
            if ($download) {
                header('Content-Type: application/json; charset=utf-8');
                header('Content-Disposition: attachment; filename="' . $tableName . '_' . date('Ymd_His') . '.json"');
                echo $json;
                return true;
            }
            
            return $json;
        } catch (Exception $e) {
            $this->lastError = "导出JSON失败: " . $e->getMessage();
            return false;
        }
    }
    
    /**
     * 获取数据库信息
     * @return array 数据库信息
     */
    public function getDatabaseInfo() {
        if (!$this->db) {
            $this->lastError = "未连接到数据库";
            return [];
        }
        
        try {
            $tables = $this->getTables();
            $tableCount = count($tables);
            $totalRows = 0;
            
            // 计算总行数
            foreach ($tables as $table) {
                $totalRows += $this->getRowCount($table);
            }
            
            // 获取数据库大小
            $fileSize = file_exists($this->dbPath) ? filesize($this->dbPath) : 0;
            
            return [
                'path' => $this->dbPath,
                'file_size' => $this->formatBytes($fileSize),
                'table_count' => $tableCount,
                'total_rows' => $totalRows,
                'tables' => $tables
            ];
        } catch (Exception $e) {
            $this->lastError = "获取数据库信息失败: " . $e->getMessage();
            return [];
        }
    }
    
    /**
     * 关闭数据库连接
     */
    public function close() {
        if ($this->db) {
            $this->db->close();
            $this->db = null;
        }
    }
    
    /**
     * 获取最后的错误信息
     * @return string 错误信息
     */
    public function getLastError() {
        return $this->lastError;
    }
    
    /**
     * 格式化字节大小
     * @param int $bytes 字节数
     * @return string 格式化后的字符串
     */
    private function formatBytes($bytes) {
        if ($bytes <= 0) return '0 B';
        
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $i = floor(log($bytes, 1024));
        
        return round($bytes / pow(1024, $i), 2) . ' ' . $units[$i];
    }
    
    /**
     * 析构函数
     */
    public function __destruct() {
        $this->close();
    }
}

// ============================================
// Web界面版本(可选)
// ============================================
if (php_sapi_name() !== 'cli' && isset($_GET['action'])) {
    // 简单的Web界面
    $action = $_GET['action'] ?? '';
    $dbPath = $_GET['db'] ?? 'database.db';
    
    $reader = new SQLiteReader($dbPath);
    
    if (!$reader->connect($dbPath)) {
        die("无法连接到数据库: " . $reader->getLastError());
    }
    
    switch ($action) {
        case 'tables':
            echo json_encode($reader->getTables());
            break;
            
        case 'structure':
            $table = $_GET['table'] ?? '';
            if ($table) {
                echo json_encode($reader->getTableStructure($table));
            }
            break;
            
        case 'data':
            $table = $_GET['table'] ?? '';
            $limit = $_GET['limit'] ?? 100;
            if ($table) {
                echo json_encode($reader->getTableData($table, $limit));
            }
            break;
            
        case 'info':
            echo json_encode($reader->getDatabaseInfo());
            break;
            
        case 'query':
            $sql = $_GET['sql'] ?? '';
            if ($sql) {
                echo json_encode($reader->query($sql));
            }
            break;
            
        case 'export_csv':
            $table = $_GET['table'] ?? '';
            if ($table) {
                $reader->exportToCSV($table);
            }
            break;
            
        case 'export_json':
            $table = $_GET['table'] ?? '';
            if ($table) {
                $reader->exportToJSON($table, true);
            }
            break;
    }
    
    exit;
}
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SQLite 数据库读取工具</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            color: #333;
            background-color: #f5f7fa;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background-color: white;
            border-radius: 10px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
            padding: 30px;
        }
        
        h1 {
            color: #2c3e50;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #3498db;
        }
        
        h2 {
            color: #3498db;
            margin: 25px 0 15px;
        }
        
        .card {
            background-color: #f8f9fa;
            border-radius: 8px;
            padding: 20px;
            margin-bottom: 20px;
            border-left: 4px solid #3498db;
        }
        
        .form-group {
            margin-bottom: 15px;
        }
        
        label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
            color: #2c3e50;
        }
        
        input, select, textarea {
            width: 100%;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 16px;
        }
        
        textarea {
            font-family: monospace;
            min-height: 100px;
            resize: vertical;
        }
        
        button, .btn {
            background-color: #3498db;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s;
        }
        
        button:hover, .btn:hover {
            background-color: #2980b9;
        }
        
        .btn-secondary {
            background-color: #7f8c8d;
        }
        
        .btn-secondary:hover {
            background-color: #636e72;
        }
        
        .btn-success {
            background-color: #27ae60;
        }
        
        .btn-success:hover {
            background-color: #219653;
        }
        
        .table-container {
            overflow-x: auto;
            margin-top: 15px;
        }
        
        table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 20px;
        }
        
        th, td {
            padding: 12px 15px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }
        
        th {
            background-color: #3498db;
            color: white;
            font-weight: bold;
        }
        
        tr:hover {
            background-color: #f5f5f5;
        }
        
        .error {
            background-color: #ffeaea;
            color: #c0392b;
            padding: 10px;
            border-radius: 4px;
            border-left: 4px solid #c0392b;
            margin-bottom: 15px;
        }
        
        .success {
            background-color: #e8f6ef;
            color: #27ae60;
            padding: 10px;
            border-radius: 4px;
            border-left: 4px solid #27ae60;
            margin-bottom: 15px;
        }
        
        .info {
            background-color: #e8f4fc;
            color: #3498db;
            padding: 10px;
            border-radius: 4px;
            border-left: 4px solid #3498db;
            margin-bottom: 15px;
        }
        
        .tab-container {
            margin-bottom: 20px;
        }
        
        .tabs {
            display: flex;
            border-bottom: 1px solid #ddd;
            margin-bottom: 20px;
        }
        
        .tab {
            padding: 10px 20px;
            cursor: pointer;
            background-color: #f1f1f1;
            border: 1px solid #ddd;
            border-bottom: none;
            border-radius: 5px 5px 0 0;
            margin-right: 5px;
        }
        
        .tab.active {
            background-color: white;
            border-bottom: 1px solid white;
            margin-bottom: -1px;
            font-weight: bold;
        }
        
        .tab-content {
            display: none;
        }
        
        .tab-content.active {
            display: block;
        }
        
        .loader {
            border: 4px solid #f3f3f3;
            border-top: 4px solid #3498db;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            animation: spin 1s linear infinite;
            margin: 20px auto;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .action-buttons {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            margin-top: 10px;
        }
        
        .database-info {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 15px;
            margin-bottom: 20px;
        }
        
        .info-item {
            background-color: #f8f9fa;
            padding: 15px;
            border-radius: 6px;
            text-align: center;
        }
        
        .info-label {
            font-size: 14px;
            color: #7f8c8d;
            margin-bottom: 5px;
        }
        
        .info-value {
            font-size: 18px;
            font-weight: bold;
            color: #2c3e50;
        }
        
        .code {
            background-color: #2c3e50;
            color: #ecf0f1;
            padding: 15px;
            border-radius: 6px;
            overflow-x: auto;
            font-family: monospace;
            margin: 15px 0;
        }
        
        @media (max-width: 768px) {
            .container {
                padding: 15px;
            }
            
            .database-info {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div>
        <h1>SQLite 数据库读取工具</h1>
        
        <div>
            <div>
                <div class="tab active" data-tab="connect">连接数据库</div>
                <div data-tab="tables">数据表</div>
                <div data-tab="query">SQL查询</div>
                <div data-tab="export">数据导出</div>
                <div data-tab="info">数据库信息</div>
            </div>
            
            <!-- 连接数据库标签页 -->
            <div id="connect" class="tab-content active">
                <div>
                    <h2>连接到SQLite数据库</h2>
                    <p>输入SQLite数据库文件的路径(相对或绝对路径)</p>
                    
                    <div>
                        <label for="dbPath">数据库文件路径:</label>
                        <input type="text" id="dbPath" placeholder="例如: database.db 或 /path/to/database.db" value="database.db">
                    </div>
                    
                    <button onclick="connectDatabase()">连接数据库</button>
                    
                    <div id="connectResult"></div>
                </div>
                
                <div>
                    <h2>使用说明</h2>
                    <p>这是一个简单的SQLite数据库读取工具,支持以下功能:</p>
                    <ul>
                        <li>查看数据库中的所有表</li>
                        <li>查看表结构和数据</li>
                        <li>执行自定义SQL查询</li>
                        <li>导出数据为CSV或JSON格式</li>
                        <li>查看数据库信息</li>
                    </ul>
                    
                    <h3>示例代码(PHP命令行使用)</h3>
                    <div>
// 引入SQLiteReader类
require_once 'sqlite_reader.php';

// 创建读取器实例
$reader = new SQLiteReader('mydatabase.db');

// 获取所有表
$tables = $reader->getTables();
print_r($tables);

// 获取表结构
$structure = $reader->getTableStructure('users');
print_r($structure);

// 执行查询
$results = $reader->query('SELECT * FROM users LIMIT 10');
print_r($results);

// 导出为CSV
$reader->exportToCSV('users', 'users_export.csv');

// 关闭连接
$reader->close();
                    </div>
                </div>
            </div>
            
            <!-- 数据表标签页 -->
            <div id="tables">
                <div>
                    <h2>数据库表列表</h2>
                    <div id="tablesList"></div>
                </div>
                
                <div>
                    <h2>表结构</h2>
                    <div id="tableStructure"></div>
                </div>
                
                <div>
                    <h2>表数据</h2>
                    <div id="tableData"></div>
                </div>
            </div>
            
            <!-- SQL查询标签页 -->
            <div id="query">
                <div>
                    <h2>执行SQL查询</h2>
                    <div>
                        <label for="sqlQuery">SQL查询语句:</label>
                        <textarea id="sqlQuery" placeholder="例如: SELECT * FROM users WHERE active = 1">SELECT * FROM sqlite_master WHERE type='table'</textarea>
                    </div>
                    
                    <button onclick="executeQuery()">执行查询</button>
                    <button onclick="clearQuery()" class="btn btn-secondary">清空</button>
                    
                    <div id="queryResult"></div>
                </div>
            </div>
            
            <!-- 数据导出标签页 -->
            <div id="export">
                <div>
                    <h2>导出数据</h2>
                    <p>选择要导出的表和格式:</p>
                    
                    <div>
                        <label for="exportTable">选择表:</label>
                        <select id="exportTable"></select>
                    </div>
                    
                    <div>
                        <label for="exportFormat">导出格式:</label>
                        <select id="exportFormat">
                            <option value="csv">CSV (Excel兼容)</option>
                            <option value="json">JSON</option>
                        </select>
                    </div>
                    
                    <button onclick="exportData()" class="btn btn-success">导出数据</button>
                    
                    <div id="exportResult"></div>
                </div>
            </div>
            
            <!-- 数据库信息标签页 -->
            <div id="info">
                <div>
                    <h2>数据库信息</h2>
                    <div id="databaseInfo"></div>
                </div>
            </div>
        </div>
    </div>
    
    <script>
        let currentDatabase = '';
        
        // 标签页切换功能
        document.querySelectorAll('.tab').forEach(tab => {
            tab.addEventListener('click', function() {
                // 移除所有标签的active类
                document.querySelectorAll('.tab').forEach(t => {
                    t.classList.remove('active');
                });
                
                // 隐藏所有内容
                document.querySelectorAll('.tab-content').forEach(content => {
                    content.classList.remove('active');
                });
                
                // 激活当前标签
                this.classList.add('active');
                
                // 显示对应内容
                const tabId = this.getAttribute('data-tab');
                document.getElementById(tabId).classList.add('active');
            });
        });
        
        // 连接数据库
        function connectDatabase() {
            const dbPath = document.getElementById('dbPath').value;
            if (!dbPath) {
                showMessage('connectResult', '请输入数据库文件路径', 'error');
                return;
            }
            
            showLoader('connectResult');
            
            fetch(`?action=tables&db=${encodeURIComponent(dbPath)}`)
                .then(response => response.json())
                .then(data => {
                    currentDatabase = dbPath;
                    
                    if (data && data.length >= 0) {
                        showMessage('connectResult', `成功连接到数据库: ${dbPath}<br>找到 ${data.length} 个表`, 'success');
                        
                        // 填充导出下拉列表
                        populateExportTable(data);
                        
                        // 自动切换到数据表标签页
                        document.querySelector('[data-tab="tables"]').click();
                        
                        // 加载表列表
                        loadTables();
                    } else {
                        showMessage('connectResult', '连接成功但未找到表', 'info');
                    }
                })
                .catch(error => {
                    showMessage('connectResult', '连接失败: ' + error, 'error');
                });
        }
        
        // 加载表列表
        function loadTables() {
            if (!currentDatabase) {
                showMessage('tablesList', '请先连接数据库', 'error');
                return;
            }
            
            showLoader('tablesList');
            
            fetch(`?action=tables&db=${encodeURIComponent(currentDatabase)}`)
                .then(response => response.json())
                .then(tables => {
                    let html = '';
                    
                    if (tables.length > 0) {
                        html = '<p>数据库中的表:</p><div>';
                        
                        tables.forEach(table => {
                            html += `<button onclick="loadTableDetails('${table}')">${table}</button>`;
                        });
                        
                        html += '</div>';
                    } else {
                        html = '<p>数据库中没有表</p>';
                    }
                    
                    document.getElementById('tablesList').innerHTML = html;
                })
                .catch(error => {
                    showMessage('tablesList', '加载表列表失败: ' + error, 'error');
                });
        }
        
        // 加载表详情
        function loadTableDetails(tableName) {
            // 加载表结构
            showLoader('tableStructure');
            fetch(`?action=structure&db=${encodeURIComponent(currentDatabase)}&table=${encodeURIComponent(tableName)}`)
                .then(response => response.json())
                .then(structure => {
                    let html = `<h3>表结构: ${tableName}</h3>`;
                    
                    if (structure.columns && structure.columns.length > 0) {
                        html += '<div><table><thead><tr><th>列名</th><th>类型</th><th>主键</th><th>非空</th><th>默认值</th></tr></thead><tbody>';
                        
                        structure.columns.forEach(col => {
                            html += `<tr>
                                <td><strong>${col.name}</strong></td>
                                <td>${col.type}</td>
                                <td>${col.pk ? '✓' : ''}</td>
                                <td>${col.notnull ? '✓' : ''}</td>
                                <td>${col.dflt_value || ''}</td>
                            </tr>`;
                        });
                        
                        html += '</tbody></table></div>';
                        
                        // 显示创建表的SQL
                        if (structure.create_sql) {
                            html += `<h4>创建表的SQL:</h4><div>${structure.create_sql}</div>`;
                        }
                    } else {
                        html += '<p>未找到表结构信息</p>';
                    }
                    
                    document.getElementById('tableStructure').innerHTML = html;
                    
                    // 加载表数据
                    loadTableData(tableName);
                })
                .catch(error => {
                    document.getElementById('tableStructure').innerHTML = `<p>加载表结构失败: ${error}</p>`;
                });
        }
        
        // 加载表数据
        function loadTableData(tableName) {
            showLoader('tableData');
            
            fetch(`?action=data&db=${encodeURIComponent(currentDatabase)}&table=${encodeURIComponent(tableName)}&limit=50`)
                .then(response => response.json())
                .then(data => {
                    let html = `<h3>表数据: ${tableName} (显示前 ${data.length} 条)</h3>`;
                    
                    if (data.length > 0) {
                        html += '<div><table><thead><tr>';
                        
                        // 表头
                        Object.keys(data[0]).forEach(key => {
                            html += `<th>${key}</th>`;
                        });
                        
                        html += '</tr></thead><tbody>';
                        
                        // 数据行
                        data.forEach(row => {
                            html += '<tr>';
                            Object.values(row).forEach(value => {
                                html += `<td>${value === null ? '<em>NULL</em>' : escapeHtml(value.toString())}</td>`;
                            });
                            html += '</tr>';
                        });
                        
                        html += '</tbody></table></div>';
                    } else {
                        html += '<p>表中没有数据</p>';
                    }
                    
                    document.getElementById('tableData').innerHTML = html;
                })
                .catch(error => {
                    document.getElementById('tableData').innerHTML = `<p>加载表数据失败: ${error}</p>`;
                });
        }
        
        // 执行SQL查询
        function executeQuery() {
            const sql = document.getElementById('sqlQuery').value;
            
            if (!sql) {
                showMessage('queryResult', '请输入SQL查询语句', 'error');
                return;
            }
            
            if (!currentDatabase) {
                const dbPath = document.getElementById('dbPath').value;
                if (!dbPath) {
                    showMessage('queryResult', '请先连接数据库', 'error');
                    return;
                }
                currentDatabase = dbPath;
            }
            
            showLoader('queryResult');
            
            fetch(`?action=query&db=${encodeURIComponent(currentDatabase)}&sql=${encodeURIComponent(sql)}`)
                .then(response => response.json())
                .then(data => {
                    let html = `<h3>查询结果</h3><p>SQL: <code>${escapeHtml(sql)}</code></p>`;
                    
                    if (data.length > 0) {
                        html += `<p>返回 ${data.length} 条记录</p>`;
                        html += '<div><table><thead><tr>';
                        
                        // 表头
                        Object.keys(data[0]).forEach(key => {
                            html += `<th>${key}</th>`;
                        });
                        
                        html += '</tr></thead><tbody>';
                        
                        // 数据行
                        data.forEach(row => {
                            html += '<tr>';
                            Object.values(row).forEach(value => {
                                html += `<td>${value === null ? '<em>NULL</em>' : escapeHtml(value.toString())}</td>`;
                            });
                            html += '</tr>';
                        });
                        
                        html += '</tbody></table></div>';
                    } else {
                        html += '<p>查询成功,但未返回数据</p>';
                    }
                    
                    document.getElementById('queryResult').innerHTML = html;
                })
                .catch(error => {
                    document.getElementById('queryResult').innerHTML = `<p>查询执行失败: ${error}</p>`;
                });
        }
        
        // 清空查询
        function clearQuery() {
            document.getElementById('sqlQuery').value = '';
            document.getElementById('queryResult').innerHTML = '';
        }
        
        // 填充导出表下拉列表
        function populateExportTable(tables) {
            const select = document.getElementById('exportTable');
            select.innerHTML = '';
            
            tables.forEach(table => {
                const option = document.createElement('option');
                option.value = table;
                option.textContent = table;
                select.appendChild(option);
            });
        }
        
        // 导出数据
        function exportData() {
            const table = document.getElementById('exportTable').value;
            const format = document.getElementById('exportFormat').value;
            
            if (!table) {
                showMessage('exportResult', '请选择要导出的表', 'error');
                return;
            }
            
            if (!currentDatabase) {
                showMessage('exportResult', '请先连接数据库', 'error');
                return;
            }
            
            // 根据格式进行导出
            if (format === 'csv') {
                window.open(`?action=export_csv&db=${encodeURIComponent(currentDatabase)}&table=${encodeURIComponent(table)}`, '_blank');
                showMessage('exportResult', '正在导出CSV文件...', 'success');
            } else if (format === 'json') {
                window.open(`?action=export_json&db=${encodeURIComponent(currentDatabase)}&table=${encodeURIComponent(table)}`, '_blank');
                showMessage('exportResult', '正在导出JSON文件...', 'success');
            }
        }
        
        // 加载数据库信息
        function loadDatabaseInfo() {
            if (!currentDatabase) {
                document.getElementById('databaseInfo').innerHTML = '<p>请先连接数据库</p>';
                return;
            }
            
            fetch(`?action=info&db=${encodeURIComponent(currentDatabase)}`)
                .then(response => response.json())
                .then(info => {
                    let html = '<div>';
                    
                    html += `<div><div>数据库路径</div><div>${escapeHtml(info.path || '未知')}</div></div>`;
                    html += `<div><div>文件大小</div><div>${escapeHtml(info.file_size || '0 B')}</div></div>`;
                    html += `<div><div>表数量</div><div>${info.table_count || 0}</div></div>`;
                    html += `<div><div>总行数</div><div>${info.total_rows || 0}</div></div>`;
                    
                    html += '</div>';
                    
                    if (info.tables && info.tables.length > 0) {
                        html += '<h3>表列表</h3><div>';
                        
                        info.tables.forEach(table => {
                            html += `<button onclick="loadTableDetails('${table}')">${table}</button>`;
                        });
                        
                        html += '</div>';
                    }
                    
                    document.getElementById('databaseInfo').innerHTML = html;
                })
                .catch(error => {
                    document.getElementById('databaseInfo').innerHTML = `<p>加载数据库信息失败: ${error}</p>`;
                });
        }
        
        // 显示加载器
        function showLoader(elementId) {
            document.getElementById(elementId).innerHTML = '<div></div>';
        }
        
        // 显示消息
        function showMessage(elementId, message, type) {
            const element = document.getElementById(elementId);
            element.innerHTML = `<div class="${type}">${message}</div>`;
        }
        
        // HTML转义
        function escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }
        
        // 当切换到信息标签页时加载数据库信息
        document.querySelector('[data-tab="info"]').addEventListener('click', loadDatabaseInfo);
        
        // 当切换到导出标签页时加载表列表
        document.querySelector('[data-tab="export"]').addEventListener('click', function() {
            if (currentDatabase) {
                fetch(`?action=tables&db=${encodeURIComponent(currentDatabase)}`)
                    .then(response => response.json())
                    .then(data => {
                        populateExportTable(data);
                    });
            }
        });
        
        // 页面加载时尝试连接默认数据库
        window.addEventListener('DOMContentLoaded', function() {
            const defaultDb = document.getElementById('dbPath').value;
            if (defaultDb) {
                // 自动连接
                connectDatabase();
            }
        });
    </script>
</body>
</html>


2. 命令行使用示例 (cli_example.php)

<?php
// 命令行使用示例
require_once 'sqlite_reader.php';

echo "SQLite 数据库读取工具 - 命令行示例\n";
echo "==================================\n\n";

// 检查是否提供了数据库路径
if ($argc < 2) {
    echo "用法: php cli_example.php <数据库文件路径>\n";
    echo "示例: php cli_example.php test.db\n";
    exit(1);
}

$dbPath = $argv[1];

// 创建读取器实例
$reader = new SQLiteReader($dbPath);

if (!$reader->connect($dbPath)) {
    echo "错误: " . $reader->getLastError() . "\n";
    exit(1);
}

echo "成功连接到数据库: $dbPath\n\n";

// 获取数据库信息
$info = $reader->getDatabaseInfo();
echo "数据库信息:\n";
echo "  文件大小: " . $info['file_size'] . "\n";
echo "  表数量: " . $info['table_count'] . "\n";
echo "  总行数: " . $info['total_rows'] . "\n\n";

// 获取所有表
$tables = $reader->getTables();
echo "数据库中的表 (" . count($tables) . " 个):\n";
foreach ($tables as $i => $table) {
    echo "  " . ($i + 1) . ". $table\n";
}
echo "\n";

// 如果有表,显示第一个表的结构和数据
if (!empty($tables)) {
    $tableName = $tables[0];
    
    // 获取表结构
    echo "表 '$tableName' 的结构:\n";
    $structure = $reader->getTableStructure($tableName);
    
    echo "  列:\n";
    foreach ($structure['columns'] as $column) {
        $pk = $column['pk'] ? " (主键)" : "";
        $notnull = $column['notnull'] ? " NOT NULL" : "";
        $default = $column['dflt_value'] ? " DEFAULT " . $column['dflt_value'] : "";
        echo "    - {$column['name']} {$column['type']}{$pk}{$notnull}{$default}\n";
    }
    echo "\n";
    
    // 获取表数据(前5行)
    echo "表 '$tableName' 的数据 (前5行):\n";
    $data = $reader->getTableData($tableName, 5);
    
    if (!empty($data)) {
        // 显示表头
        $headers = array_keys($data[0]);
        echo "  " . implode(" | ", $headers) . "\n";
        echo "  " . str_repeat("-", (count($headers) * 15)) . "\n";
        
        // 显示数据
        foreach ($data as $row) {
            echo "  " . implode(" | ", array_values($row)) . "\n";
        }
    } else {
        echo "  表中没有数据\n";
    }
    echo "\n";
    
    // 执行自定义查询
    echo "执行示例查询:\n";
    $query = "SELECT COUNT(*) as row_count FROM $tableName";
    $result = $reader->query($query);
    
    if (!empty($result)) {
        echo "  查询: $query\n";
        echo "  结果: " . $result[0]['row_count'] . " 行\n";
    }
    echo "\n";
}

// 导出示例
if (!empty($tables)) {
    echo "导出数据示例:\n";
    $tableName = $tables[0];
    
    // 导出为JSON
    $json = $reader->exportToJSON($tableName, false);
    if ($json) {
        $jsonFile = $tableName . '_export.json';
        file_put_contents($jsonFile, $json);
        echo "  数据已导出到: $jsonFile\n";
    }
    
    // 导出为CSV
    $csvFile = $tableName . '_export.csv';
    ob_start();
    if ($reader->exportToCSV($tableName, $csvFile)) {
        $csvContent = ob_get_clean();
        file_put_contents($csvFile, $csvContent);
        echo "  数据已导出到: $csvFile\n";
    }
    ob_end_clean();
}

// 关闭连接
$reader->close();
echo "\n完成!\n";
?>

3. 简单使用示例 (simple_example.php)

<?php
// 简单使用示例
require_once 'sqlite_reader.php';

// 1. 连接到数据库
$reader = new SQLiteReader();
if (!$reader->connect('example.db')) {
    die("无法连接到数据库: " . $reader->getLastError());
}

// 2. 获取所有表
$tables = $reader->getTables();
echo "数据库中的表:\n";
print_r($tables);

// 3. 获取表结构
if (!empty($tables)) {
    $structure = $reader->getTableStructure($tables[0]);
    echo "\n表 '{$tables[0]}' 的结构:\n";
    print_r($structure);
}

// 4. 获取表数据
if (!empty($tables)) {
    $data = $reader->getTableData($tables[0], 10); // 获取前10行
    echo "\n表 '{$tables[0]}' 的数据 (前10行):\n";
    print_r($data);
}

// 5. 执行自定义查询
$results = $reader->query("SELECT * FROM sqlite_master WHERE type='table'");
echo "\n所有表的元数据:\n";
print_r($results);

// 6. 获取行数
if (!empty($tables)) {
    $count = $reader->getRowCount($tables[0]);
    echo "\n表 '{$tables[0]}' 的行数: $count\n";
}

// 7. 关闭连接
$reader->close();
?>

创建测试数据库 (create_test_db.php)

<?php
// 创建测试数据库和表
$db = new SQLite3('test.db');

// 创建用户表
$db->exec("CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT NOT NULL,
    email TEXT NOT NULL UNIQUE,
    age INTEGER,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)");

// 创建订单表
$db->exec("CREATE TABLE IF NOT EXISTS orders (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    product TEXT NOT NULL,
    price REAL NOT NULL,
    status TEXT DEFAULT 'pending',
    order_date DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users (id)
)");

// 插入测试数据
$db->exec("INSERT INTO users (username, email, age) VALUES 
    ('张三', 'zhangsan@example.com', 25),
    ('李四', 'lisi@example.com', 30),
    ('王五', 'wangwu@example.com', 28)");

$db->exec("INSERT INTO orders (user_id, product, price) VALUES 
    (1, '笔记本电脑', 4500.00),
    (1, '鼠标', 120.50),
    (2, '手机', 3200.00),
    (3, '平板电脑', 2800.00)");

// 创建索引
$db->exec("CREATE INDEX idx_users_email ON users (email)");
$db->exec("CREATE INDEX idx_orders_user_id ON orders (user_id)");

echo "测试数据库已创建: test.db\n";
echo "包含: users表 (3条记录), orders表 (4条记录)\n";

$db->close();
?>

使用说明

功能特性

  1. 数据库连接:支持连接SQLite数据库文件

  2. 表管理:查看所有表、表结构、表数据

  3. 查询执行:执行自定义SQL查询

  4. 数据导出:导出为CSV或JSON格式

  5. 数据库信息:查看数据库大小、表数量、总行数等

使用方法

Web界面方式:

  1. 将 sqlite_reader.php 上传到Web服务器

  2. 通过浏览器访问该文件

  3. 输入数据库文件路径,点击"连接数据库"

  4. 使用标签页浏览数据库内容

命令行方式:

# 运行命令行示例
php cli_example.php test.db

# 运行简单示例
php simple_example.php

# 创建测试数据库
php create_test_db.php
编程方式:

require_once 'sqlite_reader.php';

// 创建读取器实例
$reader = new SQLiteReader('mydatabase.db');

// 获取所有表
$tables = $reader->getTables();

// 执行查询
$results = $reader->query('SELECT * FROM users');

// 关闭连接
$reader->close();

注意事项

  1. 确保PHP已启用SQLite3扩展

  2. Web服务器需要有数据库文件的读取权限

  3. 对于大型数据库,建议使用分页查询避免内存溢出

  4. 生产环境中请添加适当的权限控制和错误处理

这个工具提供了完整的SQLite数据库读取功能,既可以作为独立的Web工具使用,也可以作为库集成到其他PHP项目中。


评论(0条)

请登录后评论
ziyuan

ziyuan Rank: 16

0

0

0

( 此人很懒并没有留下什么~~ )

首页

栏目

搜索

会员