mysql(49) : 大数据导出为csv_按分区

文章详细展示了如何使用Java编写程序,通过Mysql8Instance连接数据库,执行SQL查询,按指定日期分区,将结果集导出到CSV文件中,支持数据分页和时间耗时计算。

代码


import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

public class 大数据导出为csv_按分区 {

    // 分区字段
    public static List<Integer> partitions = new ArrayList<>();
    public static Mysql8Instance m;
    public static Integer onCount = 10000;
    public static String fields;
    public static String table;

    public static void main(String[] args) throws Exception {
        大数据导出为csv_按分区 t = new 大数据导出为csv_按分区();
        t.partitions.add(2023122410);
        t.partitions.add(2023122411);
        t.m = new Mysql8Instance("127.0.0.1", 3306, "test", "root", "123456");
        t.m.setReturnColumnName(true);
        t.fields = "*";
        t.table = "test";
        t.handle(t.table + ".csv");
    }

    public static String getSql(Integer start, Integer date) {
        return "SELECT \n" + fields + " FROM    " + table + " where  sdate=" + date + "  limit " + start + "," + onCount;
    }

    public static void handle(String filePath) throws Exception {
        long currentTimeMillis = System.currentTimeMillis();
        File file = new File(filePath);
        // TODO 先删除再创建文件,避免文件有其他内容
        file.delete();
        file.createNewFile();
        BufferedWriter output = new BufferedWriter(new FileWriter(file, true));// true,则追加写入text文本
        long total = 0;
        boolean addTitle = false;
        for (Integer partition : partitions) {
            int start = 0;
            List<List<String>> rs;
            while ((rs = getData(m, getSql(start, partition))).size() > 1) {
                if (!addTitle) {
                    addTitle = true;
                } else {
                    rs.remove(0);
                }
                System.out.println("导出分区:[" + partition + "] ,limit:[" + start + "," + onCount + "]");
                for (List<String> r : rs) {
                    String str = join(r, ",");
                    output.write(str);
                    output.write("\r\n");// 换行
                }
                total += rs.size();
                start += onCount;
            }
            output.flush();
        }
        output.close();
        m.close();
        System.out.println("数据导出完成,总数量:" + total + ", 耗时:" + getHaoShi(System.currentTimeMillis() - currentTimeMillis));
    }

    public static List<List<String>> getData(Mysql8Instance m, String sql) {
        return m.query(sql);
    }

    /**
     * 计算耗时
     *
     * @param t 毫秒
     * @return
     */
    public static String getHaoShi(double t) {
        double d7 = t / 1000.0 / 60 / 60 / 24 / 30 / 12 / 100;
        if (d7 > 1) return round(d7, 1) + "纪元";
        double d6 = t / 1000.0 / 60 / 60 / 24 / 30 / 12;
        if (d6 > 1) return round(d6, 1) + "年";
        double d5 = t / 1000.0 / 60 / 60 / 24 / 30;
        if (d5 > 1) return round(d5, 1) + "月";
        double d4 = t / 1000.0 / 60 / 60 / 24;
        if (d4 > 1) return round(d4, 1) + "天";
        double d3 = t / 1000.0 / 60 / 60;
        if (d3 > 1) return round(d3, 1) + "小时";
        double d2 = t / 1000.0 / 60;
        if (d2 > 1) return round(d2, 1) + "分钟";
        double d1 = t / 1000.0;
        if (d1 > 1) return round(d1, 1) + "秒";
        return t + "毫秒";
    }

    public static String join(List<String> list, String separator) {
        Iterator<String> iterator = list.iterator();
        if (iterator == null) {
            return null;
        } else if (!iterator.hasNext()) {
            return "";
        } else {
            Object first = iterator.next();
            if (!iterator.hasNext()) {
                return Objects.toString(first, "");
            } else {
                StringBuilder buf = new StringBuilder(256);
                if (first != null) {
                    buf.append(first);
                }

                while (iterator.hasNext()) {
                    if (separator != null) {
                        buf.append(separator);
                    }

                    Object obj = iterator.next();
                    if (obj != null) {
                        buf.append(obj);
                    }
                }

                return buf.toString();
            }
        }
    }

    public static Double round(Double data, int amount) {
        if (data == null) return null;
        //利用BigDecimal来实现四舍五入.保留一位小数
        double result = new BigDecimal(data).setScale(amount, BigDecimal.ROUND_HALF_UP).doubleValue();
        //1代表保留1位小数,保留两位小数就是2,依此累推
        //BigDecimal.ROUND_HALF_UP 代表使用四舍五入的方式
        return result;
    }

    /**
     CREATE TABLE test.`test1` (
     `pkid` bigint NOT NULL AUTO_INCREMENT COMMENT '主键id',
     `sys_create_time` datetime DEFAULT NULL COMMENT '创建时间',
     `sys_modify_time` datetime DEFAULT NULL COMMENT '修改时间',
     `lng` double DEFAULT NULL COMMENT '经度',
     `name` varchar(100) DEFAULT NULL COMMENT '名称',
     `time` bigint DEFAULT NULL COMMENT '时间',
     `age` varchar(100) DEFAULT NULL COMMENT '年龄',
     `speed` double DEFAULT NULL COMMENT '速度',
     `lat` double DEFAULT NULL COMMENT '维度',
     `sdate` int(11) NOT NULL COMMENT '小时(分区键)',
     PRIMARY KEY (`pkid`,`sdate`)
     ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试表1';

     */
}

 Mysql8Instance类如下

mysql(30) : java管理mysql8(开发用轻量版)_java mysql8-CSDN博客

<think>首先,用户的问题是要将MySQL数据库中的表数据导出为TXT文件。参考了站内引用:-引用[1]:提到了使用`mysqlimport`导出到txt,但似乎是关于导入的部分;它也提到了`loaddatalocalinfile`命令,这是用于导入数据的。-引用[2]:描述了使用`mysqldump`导出为SQL文件。用户明确说:“我想将MySQL数据库中的表数据导出为TXT文件的解决方案”,所以我的回答需要聚焦于这个。我在思考如何将数据导出为TXT文件。在MySQL中,标准工具是`SELECT...INTOOUTFILE`语句。让我确认一下:-使用`SELECT...INTOOUTFILE'file_path'`可以将查询结果导出为文本文件。例如:`SELECT*FROMtable_nameINTOOUTFILE'/path/to/output.txt'`。但需要注意:-文件路径必须是MySQL服务器有权限写入的位置。通常,这需要服务器文件系统上的路径。-用户需要有`FILE`权限来执行这个命令。引用[1]中提到了`mysqlimport`,但它用于导入数据导出类似的是`mysqldump`,但它导出为SQL格式。所以,对于TXT导出,`INTOOUTFILE`是正确的。为了全面,我还应该提到客户端工具,如使用MySQL客户端或第三方工具导出CSV/TXT。现在,用户的指令:-系统级指令:使用$...$用于行内数学,$$...$$用于独立公式(但这个问题不涉及数学表达式),使用中文回答,生成相关问题。-用户可见层:回答结构清晰,逐步解决问题,保证真实可靠。参考引用[1]和[2],但由于它们不直接匹配导出到TXT,我需要基于标准知识回答。用户说:“参考站内引用...上述引用仅供参考”,所以我需要用自己的知识回答。结构化回答:1.**介绍方法**:使用`SELECT...INTOOUTFILE`语句简单地将表数据导出为TXT文件。2.**格式指定**:可以通过指定字段分隔符、行结束符等来控制格式。通常默认使用tab分隔,用户想要纯文本。3.**步骤示例**:提供命令示例,如:`SELECT*FROMyour_tableINTOOUTFILE'/tmp/output.txt';`4.**权限问题**:提醒可能需要`FILE`权限,文件路径在服务器上。5.**替代方法**:如果无法使用服务器端导出,使用客户端工具如`mysqldump`但输出SQL,或使用MySQL命令行客户端导出到本地文件。`mysqldump`导出为SQL,不是纯TXT;但用户指定为TXT,所以可能不合适。或者使用`mysql-e"SELECT...">output.txt`在客户端。例如:`mysql-uusername-p-e"SELECT*FROMtable_name"database_name>output.txt`,这会导出为TSV格式,类似TXT。6.**处理格式**:讨论如何指定分隔符,如使用`FIELDSTERMINATEDBY`。7.**注意事项**:服务器权限问题,文件覆盖等。生成相关问题:基于主题,如优化导出、导入方法等。最终回答结构:-简要描述方法。-步骤一:使用`SELECT...INTOOUTFILE`。-步骤二:使用命令行客户端导出。-步骤三:替代方法(如导入)。-相关问题。使用中文回答。</think> ### MySQL 数据库数据导出为 TXT 文件的解决方案 在 MySQL 中,将表数据导出为纯文本(TXT)文件的常用方法有多种。我会基于您的需求,分步介绍最实用的方案,并注意服务器权限和文件格式控制。MySQL 原生支持导出到文本文件,但方法取决于您的访问权限(例如,是否有服务器文件系统的访问权)。下面是三种主要方法的详细说明和示例代码,确保数据以 TXT 格式导出,例如使用制表符(Tab)分隔字段,换行符分隔行,类似于纯文本格式。 #### 方法一:使用 MySQL 的 `SELECT ... INTO OUTFILE` 语句(服务器端导出) 这是 MySQL 的内建命令,直接从数据库服务器生成 TXT 文件。它高效且控制灵活,但需要 MySQL 用户具有 `FILE` 权限和服务器文件系统的写入权限(文件路径必须在服务器上)。 1. **基本语法**: ```sql SELECT * FROM table_name INTO OUTFILE '/path/to/output.txt' FIELDS TERMINATED BY '\t' -- 指定字段分隔符为Tab(默认为Tab,可不写) LINES TERMINATED BY '\n'; -- 指定行结束符为换行符(默认) ``` - **字段分隔符**:默认是 Tab(`\t`),适合 TXT 文件。如果需要其他分隔符(如逗号,适合 CSV),可修改 `FIELDS TERMINATED BY`。 - **文件路径**:必须是服务器绝对路径(如 Linux 的 `/tmp/output.txt` 或 Windows 的 `C:/mysql/data/output.txt`)。MySQL 不允许导出到客户机本地路径,除非使用共享目录。 2. **完整示例**(将表 `employees` 数据导出为 TXT): ```sql -- 1. 登录 MySQL 客户端 mysql -u root -p -- 输入密码后执行 -- 2. 选择数据库导出数据 USE your_database; SELECT * FROM employees INTO OUTFILE '/tmp/employees.txt' FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'; ``` - **结果**:生成的文件 `/tmp/employees.txt` 使用 Tab 分隔字段,例如: ``` 1 John Doe john@example.com 2 Jane Smith jane@example.com ``` 3. **权限要求和注意事项**: - MySQL 用户必须有 `FILE` 权限。授予权限的命令:`GRANT FILE ON *.* TO 'username'@'localhost';`,然后刷新权限:`FLUSH PRIVILEGES;`。 - 文件输出路径必须是服务器端的有效路径。在 Linux,常见目录如 `/tmp/`;在 Windows,可能是 MySQL数据目录(如 `C:\ProgramData\MySQL\MySQL Server 8.0\Data\`)。 - 如果文件已存在,MySQL 会报错,可添加 `OPTIONALLY ENCLOSED BY '"'` 来包含字段引用(如用于文本中的特殊字符),但 TXT 文件通常不需要。 #### 方法二:使用 MySQL 命令行客户端直接导出(客户端导出) 如果您无法访问服务器文件系统或更想在本地工作,这能直接将查询结果输出到本地的 TXT 文件。适合小型表或脚本自动化。命令在终端或命令提示符中执行。 1. **基本语法**: ```bash mysql -u username -p -e "SELECT * FROM database_name.table_name" > /your/local/path/output.txt ``` - 默认导出为 Tab 分隔的文本。 - `/your/local/path/` 可以是本机路径(如 Windows 的 `D:\output.txt` 或 Linux 的 `~/output.txt`)。 2. **完整示例**(导出 `employees` 表到本地 TXT 文件): ```bash mysql -u root -p123456 -e "SELECT * FROM your_database.employees" > D:\employees.txt ``` - **结果**:文件 `D:\employees.txt` 自动以 Tab 分隔字段,例如: ``` id name email 1 John Doe john@example.com ``` 3. **优化格式控制**: - 如果需要自定义分隔符,使用 `sed` 或 `awk` 后处理(Linux/macOS),或直接在查询中指定字段: ```bash mysql -u root -p -e "SELECT id, name, email FROM your_database.employees" | sed 's/\t/,/g' > output.csv ``` 但用户要求 TXT 格式,通常不需要修改默认 Tab 分隔。 #### 方法三:使用 `mysqldump` 工具导出数据为文本格式 引用[2]提到 `mysqldump` 用于导出 SQL 文件,但可以配置导出数据为纯文本(不包含结构)。虽然不是原生 TXT 导出,但通过处理输出可转为 TXT。 1. **基本命令**: ```bash mysqldump -u username -p --tab=/path/to/output/dir --fields-terminated-by="\t" database_name table_name ``` - `--tab` 参数指定目录,MySQL 服务器会将数据导出为文本文件(如 `table_name.txt`)。 - 文件路径必须服务器可写(类似方法一)。 2. **示例**: ```bash mysqldump -u root -p123456 --tab=/tmp --fields-terminated-by="\t" your_database employees ``` - **结果**:在 `/tmp` 下生成 `employees.txt`,文件内容与方法一类似。 3. **优势**:适合批量导出多个表;劣势:服务器端路径限制。 #### 常见问题和注意事项 - **权限问题**:导出失败多为权限不足。检查 MySQL 错误日志或使用 `SHOW GRANTS FOR 'user'@'host';`。 - **安全考虑**:导出文件不应包含敏感数据在公共目录;建议用完即删。 - **格式调整**:如果数据包含特殊字符(如换行符),使用 `OPTIONALLY ENCLOSED BY '"'` 在 `SELECT ... INTO OUTFILE` 中(例如:`FIELDS OPTIONALLY ENCLOSED BY '"'`),以确保完整性。 - **性能**:对大表,使用分区或分批查询(如 `WHERE id BETWEEN 1 AND 1000`)避免内存溢出。 如果您无法使用服务器端导出(如共享主机),客户机端方法(方法二)是最通用的。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值