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行のサイズです。

そのような各行のバッチ( ...)は、バッチのヘッダーに示されている関連するMyISAMrec_xyzテーブル名にインポートする必要があります( )TableX

私は、シェルコマンドを使用してストリームをLOADDATAコマンドにパイプラインするオプションに精通しています。

このファイルを解析し、毎回(forループで、場合によってはseekコマンドを使用して)レコードの単一バッチに対してLOADDATAを実行する単純なjavasnipetコードに興味があります。

今のところ、IGNORE LINESを使用して処理済みのレコードをジャンプしようとしていますが、下の行を無視するオプションがあるかどうかわかりません。

このタイプのファイルを解析してDBにロードするためのより効率的な方法はありますか?

編集

JDBCはLOAD DATA5.1.3から始まる入力ストリームをサポートしていることを読みましたが、それを使用して入力ストリームでファイルを反復処理し、LOAD DATA毎回ステートメントを変更できますか?

4

1 に答える 1

1

解決策としてコードを添付していますが、

このソリューションは、MySQL Connector/J 5.1.3 以降で追加された追加機能( )に基づいています。setLocalInfileInputStream

LOAD DATA INTO直接のファイル URL を使用する代わりに、input-stream をステートメントにパイプラインしています。

追加情報: 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 に答える