我在 netbeans 中创建了一个 Java 项目,该项目使用 excel 表中的数据。我的项目中有允许用户读取和写入 Excel 工作表的功能。我已经使用 Apache POI 库来执行此操作。该程序在 Netbeans IDE 17 中运行良好,但是当我尝试在 JAR 文件中执行相同操作时,我无法写入 excel 表。
这是我的代码最初的样子:
if(addordel.equals("add")){
File file = new File("./src/Pick4list.xlsx");
Workbook workbook;
try {
workbook = new XSSFWorkbook(new FileInputStream(file));
Sheet sheet = workbook.getSheetAt(0);
int rowNum = -1;
for (Row row : sheet) {
if (row.getCell(0).getStringCellValue().equals(datenum)) {
rowNum = row.getRowNum();
break;
}
}
if (rowNum >= 0) {
for (int i = 1; i < 10000; i++) {
Cell cell = sheet.getRow(rowNum).getCell(i);
if (cell == null || cell.getCellType() == CellType.BLANK) {
if (i - 1 < dateslist.size()) {
String dateStr = dateslist.get(i - 1);
cell = sheet.getRow(rowNum).createCell(i);
cell.setCellValue(dateStr);
} else {
break;
}
}
}
}
FileOutputStream out = new FileOutputStream(file);
workbook.write(out);
out.close();
workbook.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Pick4gen.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Pick4gen.class.getName()).log(Level.SEVERE, null, ex);
}
}
我已经阅读了 stackoverflow 的答案并将我的代码更改为以下内容:
if(addordel.equals("add")){
InputStream file = getClass().getResourceAsStream("/data/Pick4list.xlsx");
Workbook workbook;
try {
workbook = new XSSFWorkbook(file);
Sheet sheet = workbook.getSheetAt(0);
int rowNum = -1;
for (Row row : sheet) {
if (row.getCell(0).getStringCellValue().equals(datenum)) {
rowNum = row.getRowNum();
break;
}
}
if (rowNum >= 0) {
for (int i = 1; i < 10000; i++) {
Cell cell = sheet.getRow(rowNum).getCell(i);
if (cell == null || cell.getCellType() == CellType.BLANK) {
if (i - 1 < dateslist.size()) {
String dateStr = dateslist.get(i - 1);
cell = sheet.getRow(rowNum).createCell(i);
cell.setCellValue(dateStr);
} else {
break;
}
}
}
}
FileOutputStream out = new FileOutputStream(file);
workbook.write(out);
out.close();
workbook.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Pick4gen.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Pick4gen.class.getName()).log(Level.SEVERE, null, ex);
}
}
此后我已经构建了项目。使用 WinRAR 打开 jar 文件,创建一个名为“数据”的文件夹并将我的 Excel 工作表放在那里。这似乎有效,因为我有另一个代码片段,它只是从 excel 中读取数据并将数据存储在 HashMap 中(我可以打印 HashMap 中的数据,所以我知道该程序可以读取 excel 表)。我需要有关如何更改代码的帮助,以便我可以写入 JAR 中的 Excel 工作表。
我想以这样的方式创建这个程序,无论我在哪台计算机上运行 JAR 文件,我都希望能够从 excel 表中读取并且能够对其进行更改(必须保存更改) .请指导我。
虽然有些操作系统(咳嗽 windows 咳嗽)是,或者至少曾经是,从根本上来说是不安全的设计,一般来说应用程序可以写入自己的数据文件的想法是一个非常糟糕的主意,因此未损坏的操作系统不允许您这样做。即使是倾向于与“你有例如”的部署模型一起使用的窗口
C:\Program Files\MyApp
和 myapp 将用户数据及其配置文件(可在应用程序本身中编辑)存储在那里',现在正在远离这个,使用'我的文档'文件夹,其中文档和设置而不是应用程序自己的'程序文件的文件夹。
结论是“我可以写我自己的罐子吗”是绝对不能的。在某些操作系统上你可能可以,但是编写你的应用程序这样“我需要修改我自己的 jar 否则我不工作”意味着你的应用程序只能在不安全的操作系统/现在安全的操作系统上工作,但前提是你使用不安全的旧版部署模型。
那么真正的解决方案是什么?
模板制作.
当用户想要一个excel表并就地编辑时,流程是这样的:
用户表示他们想这样做。可能,“首次启动您的应用程序”就足够了。可能他们在某个地方点击了某个按钮。
您像现在一样在 Excel 表格中阅读 - 使用
.getResource
。你没有正确使用它,它是MyClass.class.getResource
,而不是getClass().getResource
(如果你继承,后者会中断,前者不会)。
然后您将其保存不是保存到您的 jar 文件,而是保存到文档文件夹。不幸的是,找到正确的位置有些棘手,因为您最终将不得不编写一些与平台相关的代码(如果用户在 Windows 上,保存在这里。如果在 Mac 上,保存在那里,等等)。但基本要点是:
使用
System.getProperty("user.home")
找到用户的主目录。保存在那里,或者可能是“好”并保存在子目录中。例如在 Mac 上你最好会这样做:
Path p = Paths.get(System.getProperty("user.home"), "Documents");
并保存在那里。那个“文档”的东西更具体。
jar 文件中的“模板”XLS 永远不会改变。 (它不能;它在您的进程无法写入或至少不应写入的文件中)。 因此得名“模板”。