[英]Understanding java IO, opening/closing files using JFileChooser and opening/closing/saving binary files
我的教授给我分配了一个Java项目,并且通常,他没有教我们如何使用完成工作所需的工具。 因此,我试图自学文件操作的基本知识以及如何使用JFileChooser
,我感到很困惑。
在这个项目中,他希望我们创建一个带有3个JMenus
(文件,批处理,交互式处理)的JMenuBar
。 在File 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中显示工具数组的内容
HideMI:隐藏显示工具数组内容的JTextArea的内容
* 3)根据课文和讲座中给出的注释编写每种方法!
第4部分接下来,完成以下操作:(BSAF = Binary Sequentia Access File)*
1.在其中写入一个名为SaveBSAFile的方法。 创建一个DataOutputStream对象b。 创建JFileChooser的对象。 包括所有JFileChooser代码,使用“保存”选项1.打开二进制顺序文件以输出2.打印一条消息以指出它已打开(使用JOptionPane)c。 单击SaveFile菜单项时,调用SaveBSAFile方法
我在理解如何与JFileChooser
结合使用FileInputStream
/ FileOutputStream
DataInputStream/DataOutputStream
类时遇到麻烦。 到目前为止,我所学到的全部内容都不在该站点或其他站点范围内,所以我对这些类如何工作(尤其是一起工作)的理解使我感到困惑。 如果有人想给我一个解释,我将不胜感激。
这是到目前为止我一直在使用的代码,尽管它似乎无法正常工作。 当用户单击菜单选项之一并调用我尝试在此处编写的方法时,将使用一个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等数据成员)。
没有创建文件,当我尝试打开已创建并指定的文件时,也没有任何反应。
除了阅读教程,StackOverflow问题,Javadocs和一般性的试错之外,我对基于Swing的GUI和I / O的大部分了解还来自David Eck的免费教科书“ 使用Java编程入门” 。 他提供了非常易读的工作代码 ,如果以下内容不清楚,我建议您从源代码中阅读SimplePaintWithFiles.java。
请记住,无论变量的类型如何,变量仅存在于声明它的代码部分中。 在这种情况下,这意味着fstream和dstream仅存在于try块中,因此只能在其中使用它们。 还要重提一下何时将公共,保护和专用访问修饰符用于方法。
据我所知,下面是I / O的高级步骤的流程图。 它包含故意不在上下文中的简单代码段,因为它们出现在太多不同的上下文中,无法在此处包含。
File someFile = new File("/a/hardcoded/absolute/path");
这种方法不灵活,不易于维护,也不一定对分发代码安全,但是对于单元测试,快速又肮脏的脚本以及答案和论坛中的小片段(派发者认为读者知道比投入一百万美元要好得多)非常有用。整个代码中的文字。 scnr
范围内,则String thePath = scnr.next();
在将Path传递给其他方法(包括构造函数)之前,在此之后添加检查代码,以确定ThePath确实是您的用例可接受的路径。 JFileChooser jfc = new // whatever constructor is best for your use case;
通常是全局声明的。 它总是在范围内; 菜单项都具有关于最后选择的文件的信息的单个存储库,因此它们的actionPerformed方法可以彼此“交谈”; 并且诸如openBSAFile()之类的私有实用程序方法可以查询File targetFile = jfc.getSelectedFile();
以便对文件进行操作。 这取决于所选地址上的磁盘上是否已经有文件,以及您是否希望文件存在于此。 这是保持指向当前活动文件的指针的原因之一,因此可以根据需要调用它的exist()方法,mkdir()等。
仅仅因为您调用了dstream.writeChars("Content of some string-type variable you need to save");
并不意味着您的变量实际上已发送到磁盘。 在关闭,返回或假设数据已安全到达之前,请调用dstream.flush()。 有关刷新何时可以解决错误的一些出色示例,请参见上面第二个链接中的TextIO.java。
什么时候关闭开放流? 简短的答案是“完成后”,但这就像说“一根绳子只要您需要就可以了”一样含糊。 那你怎么知道什么时候完成的呢? “用流完成”有两大类。 我仍然不完全了解何时隐式关闭流,因此当有疑问时,我倾向于添加可能多余的close()语句。 关于未封闭的流是否可以公平地称为“内存泄漏”,存在一些争论,但是它们确实占用了稀缺的资源。
现在是隐喻时间。 使用文件打开流就像在电话上呼叫某人。 如果未引发异常并打开了流,请考虑“拿起电话”。 您打来电话,他们接了,现在轮到您说些什么了。 说些什么可能意味着从流中读取数据,或者可能意味着向其中写入数据。 无论哪种方式,请完成您所打电话的业务,然后挂断电话。
即使输入流没有引发错误,事情仍然可能出错。 如果应该从文件中读取整数列表,并且该文件实际上包含Moby Dick,则说明Java的内置I / O类无法检测到某些错误。 作为程序员,我们的工作是包括检查来自文件的数据的语义正确性的代码,出于同样的原因,我们必须包含检查案例2.2中获得的路径名的语义正确性的代码。 只有您知道数据的“正确性”是什么样,仅依靠文件扩展名是不够的。
问题中提供的分配规范不要求序列化。 但是,它们确实需要一组已知的字段以及这些字段的已知表示形式。 我对二进制保存数据所做的大多数搜索都建议使用序列化,因为您不必做太多手工编码。 但是,这样的任务不仅会使您更加努力。 可以说没有序列化,保存文件将更加有用。 我没有足够的空间在此处进行详细说明,也没有尝试打开基于意见的蠕虫罐。 取而代之的是,您可以看看.xcf文件格式的非官方规范,以启发您如何手工保存方式以及以什么顺序手动保存重新创建给定对象所需的数据。
您正在打开流,但不使用它们。 由于流是在( try
)块中声明的,因此它们仅在try块中有效且可见。 您对流的操作应在try块内进行。 此外,您应该使用try-with-resources语句。 在这里,您可以找到有关如何使用基本I / O流的教程。 您可以使用JFileChooser
处理打开的对话框。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.