2

我的文件具有以下格式:

Table1; Info
rec_x11;rec_x21;rec_x31;rec_x41
rec_x12;rec_x22;rec_x32;rec_x42
...
\n
Table2; Info
rec_x11;rec_x21;rec_x31;rec_x41
rec_x12;rec_x22;rec_x32;rec_x42
...
\n
Table3; Info
rec_x11;rec_x21;rec_x31;rec_x41
rec_x12;rec_x22;rec_x32;rec_x42
...

每批记录从 TableX 标头之后的下一行开始并以空行分隔符结束,大小约为 700-800 行。

每一批这样的行 ( rec_xyz...) 都需要导入到批头中指示的相关MyISAMTableX表名中 ( )

我熟悉使用 shell 命令将流传输到 LOAD DATA 命令的选项。

我对简单的java snipet代码感兴趣,它将解析这个文件并每次为一批记录执行LOAD DATA(在for循环中,可能使用seek命令)。

现在我正在尝试使用 IGNORE LINES 来跳过处理过的记录,但是我不熟悉是否可以选择忽略 BELOW 中的行?

有没有更有效的方法来解析这种类型的文件并将其加载到数据库中?

编辑

我读过 JDBC 支持LOAD DATA从 5.1.3 开始的输入流,我可以用它用输入流迭代文件并LOAD DATA每次更改语句吗?

4

1 回答 1

1

我附上我的代码作为解决方案,

此解决方案基于MySQL Connector/J 5.1.3 及更高版本添加的附加功能( )。setLocalInfileInputStream

我将输入流管道化到LOAD DATA INTO语句中,而不是使用直接文件 URL。

附加信息:我使用 BoneCP 作为连接池

public final void readFile(final String path)
        throws IOException, SQLException, InterruptedException {
    File file = new File(path);

    final Connection connection = getSqlDataSource().getConnection();
    Statement statement = SqlDataSource.getInternalStatement(connection.createStatement());

    try{
        Scanner fileScanner = new Scanner(file);
        fileScanner.useDelimiter(Pattern.compile("^$", Pattern.MULTILINE));

        while(fileScanner.hasNext()){
            String line;
            while ((line = fileScanner.nextLine()).isEmpty());

            InputStream is = new ByteArrayInputStream(fileScanner.next().getBytes("UTF-8"));
            String [] tableName = line.split(getSeparator());
            setTable((tableName[0]+"_"+tableName[1]).replace('-', '_'));

            String sql = "LOAD DATA LOCAL INFILE '" + SingleCsvImportBean.getOsDependantFileName(file) + "' " 
                    + "INTO TABLE " + SqlUtils.escape(getTable()) 
                    + "FIELDS TERMINATED BY '" + getSeparator() 
                    + "' ESCAPED BY '' LINES TERMINATED BY '" + getLinefeed() + "' ";
            sql += "(" + implodeStringArray(getFields(), ", ") + ")";       
            sql += getSetClause();

            ((com.mysql.jdbc.Statement) statement).setLocalInfileInputStream(is);
            statement.execute(sql);         
        }
    }finally{
        statement.close();
        connection.close();
    }   
}
于 2012-10-14T17:02:36.330 回答