【问题标题】:Importing a .csv or .xlsx file into mysql DB using Java?使用 Java 将 .csv 或 .xlsx 文件导入 mysql DB?
【发布时间】:2018-02-16 06:35:23
【问题描述】:

是的,听起来像是重复的。

我在 Intellij 上练习了一点 Java,并尝试编写一个程序来将 .xls excel 文件导入 mysql 数据库。重复的问题,是的,但是在互联网上拖网并没有多少收获。

我下面的代码目前可以完美地导入任何 xls 文件。不幸的是,它对 .csv 文件和 xlsx 文件都没有任何作用。

当我尝试使用 .csv 文件时,会引发以下错误:

Invalid header signature; read 0x6972702C74786574, expected 0xE11AB1A1E011CFD0 - Your file appears not to be a valid OLE2 document

当使用 xlsx 文件时,会抛出以下错误:

Exception in thread "main" org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:152)
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:140)
at org.apache.poi.poifs.filesystem.NPOIFSFileSystem.<init>(NPOIFSFileSystem.java:302)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:85)
at FileExport.main(FileExport.java:21)

我的代码:

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;




public class FileExport {

public static void main(String[] args) throws Exception {

    try {

        Class forName = Class.forName("com.mysql.jdbc.Driver");
        Connection con = null;
        con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false", "root", "root");
        con.setAutoCommit(false);
        PreparedStatement pstm = null;
        FileInputStream input = new FileInputStream("/Users/User/Desktop/Email/Test.xls");
        POIFSFileSystem fs = new POIFSFileSystem(input);
        Workbook workbook;
        workbook = WorkbookFactory.create(fs);
        Sheet sheet = workbook.getSheetAt(0);
        Row row;
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            row = (Row) sheet.getRow(i);
            String text = row.getCell(0).getStringCellValue();
            int price = (int) row.getCell(1).getNumericCellValue();


            String sql = "INSERT INTO testtable (text, price) VALUES('" + text + "','" + price + "')";
            pstm = (PreparedStatement) con.prepareStatement(sql);
            pstm.setString(1, text);
            pstm.setInt(2, price);
            pstm.execute();
            System.out.println("Import rows " + i);
        }
        con.commit();
        pstm.close();
        con.close();
        input.close();
        System.out.println("Success import excel to mysql table");
    } catch (IOException e) {
    }
}

}

非常感谢任何有关如何调整此代码以导入 .csv 或 xlsx 文件的建议。

【问题讨论】:

  • 您可以读取文件并自行解析,而无需使用 POIFS。解析 .csv 非常简单。只需逐行读取文件,并在分隔符处拆分行(并不总是逗号)。
  • 原谅我的无知,但是你能解释一下解析和这个有什么区别吗?我在我的谷歌冒险中在线看到它,但无法真正了解解析文件的实际作用。
  • @PeterBruins,这是一个糟糕的建议。 CSV 有许多边缘情况。 tburette.github.io/blog/2014/05/25/…也和问题关系不大。

标签: java mysql excel csv intellij-idea


【解决方案1】:

您是否看到证明您确实有一些行要导入的“导入行”消息?

也没有看到任何错误的原因可能是一个“catch”块什么都不做。在里面添加任何输出并观察新结果,即

 System.out.println(e.getMessage());

【讨论】:

  • 我按照你的建议做了,确实弹出了这个错误:无效的标头签名;读取 0x6972702C74786574,预期 0xE11AB1A1E011CFD0 - 您的文件似乎不是有效的 OLE2 文档
  • 那么我建议你考虑用其他解决方案替换 POIFS。或者自己做。应该是大事吗?打开一个文件,逐行读取,用逗号分隔每一行。
【解决方案2】:

您应该使用 PreparedStatement,因为它的用途是:

String sql = "INSERT INTO testtable (text, price) VALUES(?, ?)";       
pstm = (PreparedStatement) con.prepareStatement(sql);
pstm.setString(1, text);
pstm.setInteger(2, text)
pstm.execute();

我猜它不起作用,因为您的text 中有一些标点符号。 它也容易发生 SQL 注入。

您还应该使用try-with-resourcesfinally 关闭您的可关闭对象(如果您坚持使用Java 版本7 之前的版本),就像这里所做的那样:

https://stackoverflow.com/a/26516076/3323777

编辑:啊,是的,正如亚历克斯所说的那样,空的 catch 块。也不要那样做。

EDIT2

Apache POI 从未设计为调用 CSV 文件。

https://stackoverflow.com/a/1087984/3323777

Apache 有另一个 CSV 项目:

http://commons.apache.org/proper/commons-csv/

【讨论】:

  • 我按照你们俩说的做了,但是现在有一个我不太明白的新错误:无效的标头签名;读取 0x6972702C74786574,预期 0xE11AB1A1E011CFD0 - 您的文件似乎不是有效的 OLE2 文档
  • 确实,所以我在研究升技并想到这个:转换文件tio xls(是旧格式)然后使用当前代码导入mysql?基本上结合了两个代码。 stackoverflow.com/questions/3189308/convert-csv-to-xls-in-java
  • 恕我直言,这比使用 CSV 库更笨拙。顺便说一句,请随时接受任何(如果)有助于解决您的问题的答案(投票箭头下方答案左侧的复选标记)。
【解决方案3】:

调整为从 .csv 读取

public class FileExport {

public static void main(String[] args) throws Exception {

try {

    Class forName = Class.forName("com.mysql.jdbc.Driver");
    Connection con = null;
    con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false", "root", "root");
    con.setAutoCommit(false);
    PreparedStatement pstm = null;
    FileInputStream input = new FileInputStream("/Users/User/Desktop/Email/Test.csv");
     BufferedReader reader = new BufferedReader(new InputStreamReader(input));
     String row = reader.readLine();
     String text = row.split(";")[0];
     String price = row.split(";")[1];
     reader.close();

        String sql = "INSERT INTO testtable (text, price) VALUES('" + text + "','" + price + "')";
        pstm = (PreparedStatement) con.prepareStatement(sql);
        pstm.execute();
        System.out.println("Import rows " + i);
    }
    con.commit();
    pstm.close();
    con.close();
    input.close();
    System.out.println("Success import excel to mysql table");
} catch (IOException e) {
}

}

【讨论】:

  • 这段代码有些奇怪,例如变量conpstminput 在其范围之外使用。您可能需要重新验证代码。
  • 我从问题中取出了模板。
  • 另外我听说在某些地方使用将文件逐行传输到表格,然后从像 param1;param2;param3 这样的表格内容通过 sql 解析,如:SELECT TRIM(SUBSTR(CON,0,INSTR(CON,CHR(59))-1)) param1, TRIM(SUBSTR(CON,INSTR(CON,CHR(59),1,1)+1,INSTR(CON,CHR(59),1,2)-INSTR(CON,CHR(59),1,1)-1)) param2, TRIM(SUBSTR(CON,INSTR(CON,CHR(59),1,2)+1,INSTR(CON,CHR(59),1,3)-INSTR(CON,CHR(59),1,2)-1)) param3, TRIM(SUBSTR(CON,INSTR(CON,CHR(59),1,3)+1)) param4 FROM ( SELECT ROW_CONTENT CON FROM CONTENT_TABLE WHERE DOC_NAME="doc.csv")
  • 我从问题中获取了模板。 - 好吧,该模板至少是可编译的,你的代码不是。
【解决方案4】:

尝试使用 'poi-ooxml' 创建一个 Workbook 对象,它的 gradle 依赖签名如下:

compile group: 'org.apache.poi', name: 'poi-ooxml', version: '3.14'

以下代码可能对您有所帮助

InputStream inputStream = new FileInputStream("/Users/User/Desktop/Email/Test.xls");
XSSFWorkbook wb = new XSSFWorkbook(inputStream);
XSSFSheet sheet = wb.getSheetAt(0);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    • 2014-07-12
    • 1970-01-01
    • 2013-08-08
    相关资源
    最近更新 更多