了解java IO,使用JFileChooser打开/关闭文件以及打开/关闭/保存二进制文件

时间:2014-11-10 18:11:54

标签: java file-io jfilechooser

我的教授已经为我分配了一个Java项目,并且按照惯例,他没有教我们如何使用我们完成工作所需的工具。所以我试着教自己文件操作的基础知识以及如何使用JFileChooser,我很困惑。

在这个项目中,他希望我们创建一个JMenuBar,其中包含3 JMenus(文件,批处理,交互处理)。在文件JMenu下,我有5个JMenuItems(打开二进制文件,关闭二进制文件,保存二进制文件,创建报告,退出)。我列出了这些,希望能够了解应用程序正在尝试完成的任务。

以下是一些教学片段,这就是我一直在解释并试图搞砸的内容:

1)全局声明并创建JFileChooser类的对象: JFileChooser jfc = new JFileChooser();

2)完成actionPerformed,如下所示: 对于所选的每个JMenuItem,您将调用方法或执行操作:

OpenMI:调用OpenFile方法打开二进制访问文件以进行输入

CloseMI:提示警告(JOptionPane)首先保存,如果是,则关闭二进制文件并重新绘制

SaveMI:调用方法打开二进制文件输出然后调用方法输出到它

ReportMI:调用方法打开文本文件并输出到它

ExitMI:System.exeit(0);

PopulateBatchMI:调用方法从已打开的二进制顺序文件读取并将数据放入工具对象数组(我们之前创建的类)

DisplayMI:在此屏幕上的JTextArea中显示toolsarray的内容

HideMI:隐藏显示工具列表内容的JTextArea的内容

* 3)根据文本和讲座中给出的注释编写每种方法!

第4部分接下来,完成以下操作:(BSAF =二进制序列访问文件)*

1.在其中编写一个名为SaveBSAFile的方法 一个。创建DataOutputStream的对象 湾创建JFileChooser的对象。包括所有JFileChooser代码,使用“保存”选项 1.打开二进制顺序文件以进行输出 2.打印一条消息,说明它已打开(使用JOptionPane) C。单击SaveFile菜单项时调用SaveBSAFile方法

我无法理解如何将FileInputStream / FileOutputStream DataInputStream/DataOutputStream类与JFileChooser结合使用。到目前为止我所学到的所有内容都不在本网站或其他网站上,所以我对这些课程如何工作的理解,特别是在一起,让我感到困惑。如果有人想给我一个解释,我会非常感激。

这是我到目前为止一直在使用的代码,虽然它似乎没有正常工作。当用户单击其中一个菜单选项时,会使用actionPerformed(),并调用我在此处尝试写入的方法:

public void saveBSAFile()
    {
        filename = JOptionPane.showInputDialog("Please specify a file name for the " 
                                             + " file you wish to save");

        try
        {
            FileOutputStream FOStream = new FileOutputStream(filename);
            DataOutputStream DOStream = new DataOutputStream(FOStream);
        }
        catch (FileNotFoundException e)
        {
            System.out.println("file name was not found");
        }

        jfc.setDialogTitle("Specify a file to save");
        int userSelection = jfc.showSaveDialog(this);

        if (userSelection == jfc.APPROVE_OPTION)
        {
            File filename = jfc.getSelectedFile();
            JOptionPane.showMessageDialog(null, "File to save " + filename,
                                         "Save Review", JOptionPane.INFORMATION_MESSAGE);
        }
        else if (userSelection == jfc.CANCEL_OPTION)
        {
            return;
        }

    }

    public void openBSAFile()
    {
        int status = jfc.showOpenDialog(this);

        if (status == JFileChooser.APPROVE_OPTION)
        {
            File selectedFile = jfc.getSelectedFile();
            filename = selectedFile.getAbsolutePath();
            JOptionPane.showMessageDialog(null, "You selected " + filename, 
                                         "File Review",
                                         JOptionPane.INFORMATION_MESSAGE);
            try
            {
                FileInputStream fstream = new FileInputStream(filename);
                DataInputStream dstream = new DataInputStream(fstream);
            }
            catch (FileNotFoundException e)
            {
                JOptionPane.showMessageDialog(null, "File not found. Please select a " +
                                             "valid file to open", "File Not found",
                                             JOptionPane.ERROR_MESSAGE);
                System.err.println(e);
                e.printStackTrace();
            }

        }
    }

没有错误,但似乎没有发生任何事情。 saveBSAFile方法具有误导性,因为它的目的似乎是创建一个文件并从工具对象数组中保存数据(工具对象具有ID,price,numberInStock等数据成员)。

没有创建文件,当我尝试打开我创建和指定的文件时,也没有任何反应。

2 个答案:

答案 0 :(得分:1)

除了阅读教程,StackOverflow问题,Javadocs以及一般的试验和错误之外,我对基于Swing的GUI和I / O的了解大部分来自Introduction to Programming Using Java,David Eck的免费教科书。他提供very readable working code,如果后面的内容不清楚,我建议在源代码中阅读SimplePaintWithFiles.java。

请记住,变量仅存在于声明它的代码部分中,而不管变量的类型如何。在这种情况下,这意味着fstream和dstream仅存在于您的try块中,因此您只能在那里使用它们。还要了解何时为方法使用公共,受保护和私有访问修饰符。

以下是I / O的高级步骤的流程图,正如我所理解的那样。它包含故意脱离上下文的简单代码片段,因为它们出现在太多不同的上下文中以包含在这里。

1。选择与I / O交互的路径

  1. 通过代码中的字符串文字
  2. 通过System.in,扫描程序或其他一些输入流
  3. 通过GUI对象,例如JFileChooser
  4. 2。构造指向该路径名的File对象(并且可能保留指向它的指针)

    1. case 1.1:将String文字(或用它声明的变量)传递给File构造函数 例如File someFile = new File("/a/hardcoded/absolute/path");这对于可分发的代码来说不灵活,易于维护或必然安全,但对于单元测试,快速和脏脚本以及海报的答案和论坛中的小小片段都很方便假设读者知道更好而不是在他们的代码上放置一百万个文字。
    2. 案例1.2:假设某个扫描程序在scnr的范围内,String thePath = scnr.next(); 在此之后输入检查代码,以确定该路径确实是您的用例可接受的路径,在将Path传递给其他方法之前,包括构造函数。
    3. 案例1.3:这就是JFileChooser jfc = new // whatever constructor is best for your use case;通常全局声明的原因。它始终在范围内;菜单项都有一个关于最后选择的文件的信息库,所以他们的actionPerformed方法可以" talk"对彼此; 私有实用程序方法(如openBSAFile())可以查询File targetFile = jfc.getSelectedFile();以便操作文件。
    4. 3。现在我有一个文件!我该怎么办?

      这取决于所选地址上是否已存在磁盘上的文件以及您是否希望文件存在。这是保持指向当前活动文件的指针的一个原因,因此您可以根据需要调用它的exists()方法,mkdir()等。

      1. 如果文件已存在于磁盘上,请执行interaction0。输出方法应该抛出错误或要求允许覆盖。输入法可能会正常进行。
      2. 如果磁盘上不存在该文件,请执行interaction1。输入方法可能会抛出错误(并且可能会捕获自己的错误,例如显示对话框)。输出方法可能会正常进行。
      3. 4。记得要冲洗

        仅仅因为您已调用dstream.writeChars("Content of some string-type variable you need to save");并不意味着您的变量实际上已发送到磁盘。在关闭,返回或以其他方式假设数据已安全到达之前调用dstream.flush()。请参阅上面第二个链接中的TextIO.java,了解一些很好的例子,说明何时刷新是解决bug的方法。

        5。关闭你的开放溪流! (这让我最困惑)

        何时关闭开放流?简短的回答是#34;当你完成它时,"但是,只要你需要它,就像一条绳子一样含糊不清。"所以你怎么知道你什么时候做的?有两个大类的"用流完成。"我仍然不能完全理解流被隐式关闭的情况,所以当有疑问时,我倾向于添加可能多余的close()语句。关于未封闭的流是否可以公平地被称为“内存泄漏”,存在一些争论,"但他们确实占用了稀缺的资源。

        1. 发生IOException,之后您的代码无法正常运行。除了抛出异常,捕获异常,显示对话框等之外,您还可以完成流。在上面的代码中,调用dstream.close()也将关闭fstream,因为dstream是它的包装器。
        2. 您的代码已正常完成与流的交互。在这种情况下,您已经编写或读取了所需的所有数据,没有发生任何错误,并且使用该流的方法即将返回。
        3. 对案例3.1,3.2和5.1的深入讨论

          这是比喻的时间。 使用文件打开流就像在电话上呼叫某人。如果没有抛出异常并打开流,请考虑"拿起电话。"你打电话,他们接了,现在轮到你说些什么了。说某事可能意味着从流中读取数据,或者可能意味着将数据写入其中。无论哪种方式,完成您所要求的业务,然后挂断电话。

          即使输入流没有发生错误,事情仍然可能出错。如果您应该从文件中读取整数列表,并且该文件实际上包含Moby Dick,那么Java的内置I / O类无法检测到的错误。作为程序员,我们的工作是包含代码来检查我们从文件中读取的数据的语义正确性,出于同样的原因,我们必须包含代码来检查在案例2.2中获得的路径名的语义正确性。只有你知道"正确性"看起来像你的数据,并依赖文件扩展是不够的。

          除了二进制保存文件:

          问题中提供的分配规范不需要序列化。但是,他们确实需要一组已知的字段和这些字段的已知表示。我所做的关于二进制保存数据的大部分搜索建议使用序列化,因为您不必进行如此多的手动编码。但是,这样的任务并不仅仅会让你更加努力;如果没有序列化,可以使您的保存文件更有用。我没有足够的空间在这里详细介绍,我也没有尝试打开基于意见的蠕虫病毒。相反,您可以查看the unofficial specification of the .xcf file format,了解如何以及以何种顺序手动保存重新创建任何给定对象所需的数据。

答案 1 :(得分:0)

您正在打开流,但您不使用它们。由于流是在(try - )块中声明的,因此它们只在try块中存活且可见。您对流的操作应该在try-block中进行。此外,您应该使用try-with-resources语句。 Here您找到了有关如何使用基本I / O流的教程。您可以使用JFileChooser来处理打开的对话框。