2013-11-04 52 views
0

我想將csv文件的內容傳輸到mysql。在我的csv文件中,有包含逗號的文本的列。解析csv文件中的文本中存在的逗號,同時將內容從csv文件傳輸到mysql

我使用下面的代碼來傳輸內容

`

import java.io.FileNotFoundException; 
import java.io.FileReader; 
import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.util.Date; 

import org.apache.commons.lang.StringUtils; 

import au.com.bytecode.opencsv.CSVReader; 




public class CSVLoader { 


    static int count; 
    private static final 
     String SQL_INSERT = "INSERT INTO ${table}(${keys}) VALUES(${values})"; 
    private static final String TABLE_REGEX = "\\$\\{table\\}"; 
    private static final String KEYS_REGEX = "\\$\\{keys\\}"; 
    private static final String VALUES_REGEX = "\\$\\{values\\}"; 

    private Connection connection; 
    private char seprator; 

    /** 
    * Public constructor to build CSVLoader object with 
    * Connection details. The connection is closed on success 
    * or failure. 
    * @param connection 
    */ 
    public CSVLoader(Connection connection) { 
     this.connection = connection; 
     //Set default separator 
     this.seprator = ','; 
    } 

    /** 
    * Parse CSV file using OpenCSV library and load in 
    * given database table. 
    * @param csvFile Input CSV file 
    * @param tableName Database table name to import data 
    * @param truncateBeforeLoad Truncate the table before inserting 
    *   new records. 
    * @throws Exception 
    */ 
    public void loadCSV(String csvFile, String tableName, 
      boolean truncateBeforeLoad) throws Exception { 

     CSVReader csvReader = null; 
     if(null == this.connection) { 
      throw new Exception("Not a valid connection."); 
     } 
     try { 

      csvReader = new CSVReader(new FileReader(csvFile), this.seprator); 

     } catch (Exception e) { 
      e.printStackTrace(); 
      throw new Exception("Error occured while executing file. " 
        + e.getMessage()); 
     } 

     //String[] headerRow = csvReader.readNext(); 
     String[] headerRow = csvReader.readNext(); 
     count++; 
     if (null == headerRow) { 
      throw new FileNotFoundException(
        "No columns defined in given CSV file." + 
        "Please check the CSV file format."); 
     } 

     String questionmarks = StringUtils.repeat("?,", headerRow.length); 
     System.out.println(headerRow.length); 
     questionmarks = (String) questionmarks.subSequence(0, questionmarks 
       .length() - 1); 

     String query = SQL_INSERT.replaceFirst(TABLE_REGEX, tableName); 
     query = query 
       .replaceFirst(KEYS_REGEX, StringUtils.join(headerRow, ",")); 
     query = query.replaceFirst(VALUES_REGEX, questionmarks); 

     System.out.println("Query: " + query); 

     String[] nextLine; 
     Connection con = null; 
     PreparedStatement ps = null; 
     try { 
      con = this.connection; 
      con.setAutoCommit(false); 
      ps = con.prepareStatement(query); 

      if(truncateBeforeLoad) { 
       //delete data from table before loading csv 
       con.createStatement().execute("DELETE FROM " + tableName); 
      } 

      final int batchSize = 1000; 
      int count = 0; 
      Date date = null; 
      while ((nextLine = csvReader.readNext()) != null) { 

       if (null != nextLine) { 
        int index = 1; 
        for (String string : nextLine) { 
         date = DateUtil.convertToDate(string); 
         if (null != date) { 
          ps.setDate(index++, new java.sql.Date(date 
            .getTime())); 
         } else { 
          ps.setString(index++, string); 
         } 
        } 
        System.out.println(count); 
        ps.addBatch(); 
        System.out.println(count); 
       } 
       if (++count % batchSize == 0) { 
        System.out.println(count); 
        ps.executeBatch(); 
       } 
      } 
      ps.executeBatch(); // insert remaining records 
      con.commit(); 
     } catch (Exception e) { 
      con.rollback(); 
      e.printStackTrace(); 
      throw new Exception(
        "Error occured while loading data from file to database." 
          + e.getMessage()); 
     } finally { 
      if (null != ps) 
       ps.close(); 
      if (null != con) 
       con.close(); 

      csvReader.close(); 
     } 
    } 

    public char getSeprator() { 
     return seprator; 
    } 

    public void setSeprator(char seprator) { 
     this.seprator = seprator; 
    } 

} 

` 當執行它我收到錯誤爲「爲參數23指定值」。 我的數據庫表有22列,csv文件也有22列。所以我猜測,在第一行本身有一個文本中有一個逗號,它不能解析它,因此它假設爲23列,而不是22. 任何人都可以幫助我澄清問題並提供解決方案。

+1

>所以我猜測,在第一行本身有一個文本,其中有一個逗號......那麼,有沒有或沒有?我會假設你可以檢查這個。我們當然不能,這是這個難題的重要信息。 – Medo42

+0

你可能會發現有用[LOAD DATA INFILE語句](http://dev.mysql.com/doc/refman/5.1/en/load-data.html) – alko

+0

是的,第一行本身有逗號。我的意思是通過在帖子中說是我猜測它正在考慮23列,因爲這個逗號 – user2916886

回答

-1

CSV文件中有兩種逗號類型。一種類型的逗號分隔字段,另一種類型的逗號是文本的一部分,總是在引號之間出現。您需要在引號之外解析逗號與逗號之間的逗號不同。你的代碼似乎沒有這樣做。也許是這樣的:

repeat 
    c <-read next character 
    if (c == '"') 
    parse quoted field // May include commas. 
    else 
    parse non-quoted field // Will not include commas. 
    endif 
until file all read. 

用不同的方法來解析引用和不帶引號的領域可以很容易地正確對待這兩種類型的逗號。

+0

這不是這裏的問題。他正在使用CSV閱讀庫來正確處理這個問題。 – Medo42

+0

是的,我認爲csvreader處理它,但它仍然拋出錯誤。 – user2916886

0

我認爲當前的問題是,在將它們插入到SQL語句中時,您不會轉義列名。你所創建的這種形式的語句:

INSERT INTO sometable(key1,key2,key3) VALUES(?,?,?) 

現在,如果你有一個標題行逗號(比方說,一個關鍵是「科,Y3」來代替),即使它是由你的正確讀取CSV庫,你會喜歡這個被創造一些:

INSERT INTO sometable(key1,key2,ke,y3) VALUES(?,?,?) 

現在,你必須在值數和列數不匹配。請注意,對於其他字符也可能發生這種情況:也許您在一個被解釋爲參數佔位符的鍵中有問號?

解決方案:爲了節省您的一些頭痛,如果可能的話,請儘量避免使用這些字符。我不知道如何以及如果MySQL能夠正確處理它們,但是如果它確實如此,那麼在插入它們之前至少需要轉義列名。我不知道你會怎麼做是正確和安全(防止SQL注入),但由於這顯然是一個一次性的工具,在反引號包裹列名這應該是足夠好:

INSERT INTO sometable(`key1`,`key2`,`ke,y3`) VALUES(?,?,?)