Writing to an excel sheet in a JAR file.

huangapple go评论53阅读模式
英文:

Writing to an excel sheet in a JAR file

问题

我看到你的问题了。你的目标是能够在JAR文件中读取和写入Excel表格,确保无论在哪台计算机上运行JAR文件,都能正常操作。你已经成功将Excel文件放在JAR文件中,下面是关于如何修改代码的建议:

首先,要注意你使用了InputStream来读取Excel文件,但是却尝试使用FileOutputStream来写入文件。在JAR文件中,资源是以只读方式加载的,所以你不能直接使用FileOutputStream来写入。你需要将修改后的Excel数据保存在不同的位置。

一种解决方案是将修改后的数据保存到用户的本地文件系统。你可以在运行时检查用户的操作系统,并在用户的文档目录或应用程序数据目录中创建一个文件夹,将Excel文件保存在其中。然后,在程序下次运行时,检查是否存在本地文件,如果存在,则加载本地文件并进行写入操作。

这种方式可以确保在不同计算机上运行JAR文件时都能正常工作。但请注意,这可能需要一些额外的代码来管理文件的创建和保存。

如果你需要示例代码来执行这些操作,请告诉我,我可以为你提供一些示例代码。

英文:

I made a Java project in netbeans that uses data from an excel sheet. There is functionality in my project that allows the user to read and write to the excel sheet. I have used the Apache POI library to do this. The program works well in Netbeans IDE 17 but when I try to do the same in a JAR file, I cannot write to the excel sheet.

this is what my code initially looked like:

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);
            }
        }

I've read answers from stackoverflow and changed my code to the following:

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);
            }
        }

I've build the project after this. Opened the jar file using WinRAR, created a folder called "data" and placed my Excel sheet there. This seems to be working since I have another snippet of code that simply reads data from the excel and stores the data in a HashMap (I could print the data from the HashMap so I understood that the program could read the excel sheet). I need help as to how I can change the code so that I can write to the excel sheet in the JAR.

I want to create this program in such a way that no matter on which computer I run the JAR file, I want to be able to read from the excel sheet and also be able to make changes to it (the changes must be saved). Please guide me.

答案1

得分: 1

以下是翻译好的部分:

尽管一些操作系统(咳咳Windows咳咳)在设计上或至少曾经是不安全的,总的来说,一个应用程序可以写入其自己的数据文件的概念是一个非常糟糕的想法,因此非破损的操作系统不会让你这样做。即使是Windows,以前采用的部署模型是'你有例如C:\Program Files\MyApp,而我的应用程序会将用户数据和其配置文件(在应用程序本身可编辑)存储在其中',现在也在摒弃这种模式,采用了一个'我的文档'文件夹,用于存放文档和设置,而不是应用程序自己的'程序文件'文件夹。

结论是'我可以写入我的jar文件吗'是明确的NO。在某些操作系统上,您可能可以这样做,但编写应用程序以便'我需要修改我的jar文件,否则我无法工作'意味着您的应用程序仅在不安全的操作系统上工作/现在安全的操作系统上也只有在使用不安全的旧部署模型时才能工作。

那么真正的解决方案是什么?

模板

当用户想要一个Excel表格并在其中编辑时,流程如下:

  • 用户表示他们想要这样做。也许,'第一次启动您的应用程序'就足够了。也许他们在某个地方点击了某个按钮。

  • 您像现在一样使用.getResource来读取Excel表格。但是您没有完全正确使用它,应该使用MyClass.class.getResource,而不是getClass().getResource(如果您曾经子类化,后者会出问题,前者不会)。

  • 然后,将其保存__不是到您的jar文件,而是到文档文件夹__。不幸的是,找到正确的位置有些棘手,因为您最终将不得不编写一些依赖于平台的代码(如果用户在Windows上,保存在这里。如果在Mac上,保存在那里,依此类推)。但基本思路是:

  • 使用System.getProperty("user.home")来找到用户的主目录。然后在那里保存,或者可能要'友好'地保存在子目录中。例如,在Mac上,您最好这样做:

Path p = Paths.get(System.getProperty("user.home"), "Documents");

然后在那里保存。那个"Documents"是更具体的。

  • 或者,弹出一个保存对话框,让用户选择保存位置。

您jar文件中的'模板'XLS文件__永远不会更改__。(它不能;它在一个您的进程不能写入的文件中,或者至少不应该写入)。
因此,它被称为'模板'。

英文:

Whilst some OSes (cough windows cough) are, or at least used to be, fundamentally unsafely designed, in general the notion that an app can write to its own data files is a very bad idea, and thus non-broken OSes don't let you. Even windows which tended to go with the deployment model of 'you have e.g. C:\Program Files\MyApp and myapp stores user data and its config file (that is editable in the app itself) in there', is now moving away from this, with a 'My Documents' folder where docs and settings go instead of the app's own 'program files' folder.

The conclusion is that 'can I write to my own jar' is a definitely NO. On some OSes you might be able to, but writing your app such that 'I need to modify my own jar or I do not work' means your app only works on unsafe OSes / now-safe OSes but only if you use the unsafe legacy deployment model.

So what's the real solution?

Templating.

When the user wants an excel sheet and edit it in place, the flow goes like this:

  • User indicates they want to do this. Possibly, 'start your app for the first time' is enough of an indication. Possibly they click some button someplace.

  • You read in an excel sheet as you do now - using .getResource. Which you didn't quite use correctly, it's MyClass.class.getResource, not getClass().getResource (the latter breaks if you ever subclass, the former wouldn't).

  • You then save it not to your jar file but to the documents folder. Unfortunately finding the right place is somewhat tricky, in that you'll end up having to write some platform-dependent code (if user is on windows, save here. If on mac, save there, and so on). But the basic gist is:

  • Use System.getProperty("user.home") to find the user's home dir. Save there, or possibly be 'nice' and save in a subdir. For example on mac you optimally would do:

Path p = Paths.get(System.getProperty("user.home"), "Documents");

and save there. That "Documents" thing is more specific.

  • Alternatively, pop open a save dialog and let the user choose where to save it.

The 'template' XLS in your jar file never changes. (It can't; its in a file your process cannot write to, or at least should not write to).
Hence the name 'template'.

huangapple
  • 本文由 发表于 2023年5月6日 19:16:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76188567.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定