在 Java 中將 JDBC 結果集轉換為 CSV
一、簡介
在使用與資料庫互動的 Java 應用程式時,我們經常需要將查詢結果匯出為易於使用或共用的格式。用於此目的的常見格式是 CSV(逗號分隔值)。為了實現這一點,我們可以將 JDBC ResultSet
(用於保存資料庫查詢結果的資料結構)轉換為 CSV 檔案。
在本文中,我們將探討將ResultSet
轉換為 CSV 格式的兩種方法。
2. 設定
出於測試目的,我們將使用具有以下架構的Employees
表:
CREATE TABLE EMPLOYEES (
id SERIAL PRIMARY KEY ,
first_name VARCHAR(50),
last_name VARCHAR(50),
salary DECIMAL(10, 2)
);
3. 使用自訂邏輯
在這種方法中,首先,我們查詢Employees
表中的記錄:
正如我們在上面看到的, Employees
表記錄包含特殊字元。然後我們迭代ResultSet
並將每筆記錄轉換為 CSV:
List<String> toCsv(Connection connection) throws SQLException {
List<String> csvRecords = new ArrayList<>();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM employees");
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
String eachRecord = formatForCsv(resultSet.getString("first_name")) + "," +
formatForCsv(resultSet.getString("last_name")) + "," +
"\"" + resultSet.getDouble("salary") + "\"";
csvRecords.add(eachRecord);
}
return csvRecords;
}
對於每筆記錄,我們將每一列(例如first_name
、 last_name
等)作為字串讀取。我們建立了formatForCSV()
輔助方法,它使用 ( \\n
) 轉義換行符 ( \n
n ),使用 ( \\r
) 轉義回車符 ( \r
),使用 ( “”
) 轉義雙引號( “
):
String formatForCsv(String value) {
return "\"" + value
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\"", "\"\"")
+ "\"";
}
如果我們執行我們的邏輯,我們將得到ResultSet
轉換後的 CSV 結果:
我們可以編寫單元測試來驗證我們的邏輯是否如預期般運作:
@Test
void givenEmployeeRecordsInEmployeeTable_whenResultSetToCSVInvoked_thenReturnsCSV() throws SQLException, IOException {
insertRecords();
ResultSetToCSV logic = new ResultSetToCSV();
List<String> csvRecords = logic.toCsv(connection);
Files.write(Paths.get("/Users/surajmishra/Documents/work-space/employee.csv"), csvRecords);
assertThat(csvRecords.size()).isEqualTo(3);
for (int i = 1; i <= 2; i++) {
assertThat(csvRecords.get(i - 1))
.isEqualTo("\"first" + i + "\"," + "\"last" + i + "\"," + "\"" + String.format("%.1f", 100.00 * i) + "\"");
}
assertThat(csvRecords.get(2))
.isEqualTo("\"\"\"first\\nfirst1\\nfirst2!\"\"1\"," + "\"\"\"last!\\nlast1!\"\"1\"," + "\"100.0\"");
}
4.使用第三方依賴
有不同的開源函式庫可以幫助我們將ResultSet
轉換為 CSV。 OpenCSV是受歡迎的函式庫之一。
我們可以將其新增到pom.xml
檔案中:
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.9</version>
</dependency>
在下面的邏輯中,我們從資料庫中讀取所有Employees
記錄作為ResultSet,
然後使用 OpenCSV 將它們轉換為 CSV:
String toCsvWithOpenCsv(Connection connection) throws SQLException {
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM employees");
ResultSet resultSet = preparedStatement.executeQuery();
StringWriter stringWriter = new StringWriter();
CSVWriter csvWriter = new CSVWriter(stringWriter,
CSVWriter.DEFAULT_SEPARATOR,
CSVWriter.DEFAULT_QUOTE_CHARACTER, // Default quote character is double quote
CSVWriter.DEFAULT_ESCAPE_CHARACTER, // Default escape character is double quote
CSVWriter.DEFAULT_LINE_END);
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
String[] row = new String[columnCount-1];
while (resultSet.next()) {
row[0] = resultSet.getString("first_name")
.replace("\n", "\\n")
.replace("\r", "\\r");
row[1] = resultSet.getString("last_name")
.replace("\n", "\\n")
.replace("\r", "\\r");
row[2] = String.valueOf(resultSet.getDouble("salary"));
csvWriter.writeNext(row);
}
return stringWriter.toString();
}
在上面的邏輯中,我們也會對列值中的任何特殊字元(例如換行符、回車符或雙引號)轉義每一行。我們使用csvWriter
為 CSV 寫入行數組。然後,為了取得String,
我們使用toString()
方法將包含 CSV 資料的stringWriter
轉換為String
。
我們可以編寫單元測試來驗證我們的邏輯是否如預期般運作:
@Test
void givenEmployeeRecordsInEmployeeTable_whenResultSetToCSVWithOpenCsvInvoked_thenReturnsCSV() throws SQLException {
insertRecords();
ResultSetToCSV logic = new ResultSetToCSV();
String csvRecords = logic.toCsvWithOpenCsv(connection);
String[] split = csvRecords.split("\n");
assertThat(split.length).isEqualTo(3);
for (int i = 1; i <= 2; i++) {
assertThat(split[i - 1])
.isEqualTo("\"first" + i + "\"," + "\"last" + i + "\"," + "\"" + String.format("%.1f", 100.00 * i) + "\"");
}
assertThat(split[2])
.isEqualTo("\"\"\"first\\nfirst1\\nfirst2!\"\"1\"," + "\"\"\"last!\\nlast1!\"\"1\"," + "\"100.0\"");
}
5. 結論
在本教程中,我們學習了使用 OpenCSV 和自訂邏輯將 JDBC ResultSet
轉換為 CSV 的兩個選項。雖然我們始終可以使用 OpenCSV 等第三方依賴項來執行轉換,但編寫自訂邏輯並不是那麼糟糕。
與往常一樣,範例程式碼可以在 GitHub 上取得。