简单记事本功能实现
2018-9-8
使用IO流来实现,先了解一下流
什么是流
流,字面意思就是流动的意思,可以理解为数据的流动,从一个地方流动到另一个地方。所以IO也依它们的流动方向分为了输入流和输出流。
- 输入流
就是数据从磁盘“流动”到内存,—->读取 - 输出流
数据从内存”流动”到磁盘, —->写入
字节输入流 InputStream
因为InputStream自身是一个抽象类,无法实例化,所以我们如果想要使用到输入流就需要去创建它的子类对象。在它的实现子类中我们最常用到的就是FileInputStream。
FileInputStream(String name) ,我们可以使用它的构造方法,传入一个抽象路径来实现与一个文件建立关联。建立关联之后使用它的read方法来实现文件的读取。它的文件读取分为一下几种方式:
- int read() :一次读取一个字节,读到文档末尾则返回-1。通常读取文件内容时我们使用循环去读取
- int read(byte[] b) : 每次读取b.length()个字节数据,即b有多长我们一次就读多少,每次读取都会覆盖数组中上次读到的数据
还有一种方式就不多介绍了,常用就以上两种
字节输出流 OutputStream
同样的OutputStream自身也是一个抽象类,我们需要使用它的子类对象FileOutputStream。
FileOutputStream(String name) :与指定抽象路径文件关联。建立关联之后使用它的方法write来实现文件的写入(磁盘)。同样的它长用的有两种方式:
- void write() : 一次写入一个字节的数据,到达文档末尾返回-1
- void write(byte[] b) : 一次写入b长度个字节的数据,每次都会覆盖数组中上次读到的数据
字符输入流 FileReader
字符输入流,它操作的数据单位与字节流不一样,它操作的单位是字符
FileReader(String fileName) : 与指定的抽象路径文件建立连接,关联之后使用read方法读取文件
- int read() : 每次读取一个字符长度的数据,读到文档末尾返回-1
- int read(char[] c) : 每次读取c长度个字符的数据,读到文档末尾返回-1,每次读取都会覆盖数组中上次读到的数据
字符输出流 FileWriter
FileWriter(String fileName) :与指定抽象路径的文件建立连接,关联之后使用write方法实现文件内容写入(磁盘)。当然,我这里只是使用了最简单的构造方法来构建,以上所有流都是还有其他的构建方式的。
- void write() : 每次写入一个字符长度数据,写入的时候注意要使用flush方法或者使用close方法刷新流(close方法会刷新流)
- void write(String s) : 字符输出流特殊一点就是可以直接写入字符串
- void write(char[] c) : 每次输出c长度的字符数据
无论使用哪种方式写入都要注意刷新流,否则不会有写入效果
流的选择
那么,平时使用的时候要怎么选择呢?我们主要看要传输的文档类型,如果是文本文档最好是使用字符流,如果是多媒体文件最好使用字节流
了解了流之后我们就可以开始使用它们来实现一些简单的记事本功能了。在这主要实现记事本的打开、保存、和另存功能。
思路:
- 打开:
就是从磁盘读取文件内容,显示到记事本文本框中 - 保存
需要判断要保存的文件是否是新建的文件(即不是本地已有文件),如果是新建的文件则弹出保存对话框。如果不是,直接保存到源文件中 - 另存
选择文件路径保存
好了,直接上代码!
Frame界面
import java.awt.TextArea;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JTextArea;
public class FrameDemo extends JFrame{
private TextArea texts;
private String title;
public FrameDemo() {
init();
}
private void init() {
title = "无标题";
JFrame frame = new JFrame(title);
frame.setVisible(true);
frame.setSize(600, 500);
frame.setResizable(true);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);//3
addJMenuBarToFrame(frame);
addTextAreaToFrame(frame);
}
private void addTextAreaToFrame(JFrame frame) {
// TODO Auto-generated method stub
JMenuBar menuBar = new JMenuBar();
JMenu file = new JMenu("文件(F)");
JMenu edit = new JMenu("编辑(E)");
JMenu format = new JMenu("格式(O)");
JMenu view = new JMenu("查看(V)");
JMenu help = new JMenu("帮助(H)");
//文件
JMenuItem newFile = new JMenuItem("新建(N) CTRL+N");
JMenuItem open = new JMenuItem("打开(O) CTRL+O");
JMenuItem save = new JMenuItem("保存(S) CTRL+S");
JMenuItem saveAs = new JMenuItem("另存为(A)");
JMenuItem pageSettings = new JMenuItem("页面设置(U)");
JMenuItem print = new JMenuItem("打印(P) CTRL+P");
JMenuItem exit = new JMenuItem("退出(E)");
file.add(newFile);
file.add(open);
//给打开文件添加监听器
OpenActionListener oal = new OpenActionListener(frame,texts);
open.addActionListener(oal);
file.add(save);
//保存事件监听
SaveActionListener sal = new SaveActionListener(texts, frame);
save.addActionListener(sal);
file.add(saveAs);
//添加另存监听器
SaveAsActionListener saal = new SaveAsActionListener(frame,texts);
saveAs.addActionListener(saal);
file.addSeparator();
file.add(pageSettings);
file.add(print);
file.addSeparator();
file.add(exit);
//给退出添加时间监听器
ExitActionListener eal = new ExitActionListener();
exit.addActionListener(eal);
menuBar.add(file);
menuBar.add(edit);
menuBar.add(format);
menuBar.add(view);
menuBar.add(help);
frame.setJMenuBar(menuBar);
}
private void addJMenuBarToFrame(JFrame frame) {
// TODO Auto-generated method stub
texts = new TextArea();
frame.add(texts);
}
}
打开功能
import java.awt.FileDialog;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream.GetField;
import javax.swing.JFrame;
public class OpenActionListener implements ActionListener {
private JFrame frame;
private TextArea textArea;
public static String realepath;
public OpenActionListener(JFrame frame,TextArea textArea) {
super();
this.frame = frame;
this.textArea = textArea;
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
FileDialog fd = new FileDialog(frame,"open",FileDialog.LOAD);
//FileDialog默认不可见
fd.setVisible(true);
realepath = fd.getDirectory()+fd.getFile();
if(fd.getFile() != null) {
//打开时将记事本标题替换
frame.setTitle(fd.getFile());
readFile(realepath,textArea);
}
}
private static void readFile(String path,TextArea textArea){
if("nullnull".equals(path) || !new File(path).exists()) {
return;
}
textArea.setText("");
// TODO Auto-generated method stub
//获取要读取文件的目录
File file = new File(path);
try {
//指定读取文件
FileInputStream fin = new FileInputStream(file);
/*byte[] b = new byte[fin.available()];
fin.read(b);
//将字符数组转成字符串
String s = new String(b);*/
byte[] b = new byte[5];
int len;
while((len = fin.read(b)) != -1) {
textArea.append(new String(b,0,len));
}
// textArea.setText(s);
fin.close();
} catch (FileNotFoundException e) {
// TODO: handle exception
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
保存功能
/**
* 保存功能
* 点击保存之后,
* 调用保存方法,将从打开问价时获取到的文件路径传入,
* 创建字符输出流对象将记事本文本框中的内容写入到源文件中
* 实现了保存
* 如果是打开的本地文件,直接保存
* 如果要保存的文件是新建的文件(在本地没有存档)
* 可以将记事本的标题栏默认设置为无标题,如果打开了文件则将标题替换
* 保存时查询标题即可知道是否是本地文件
* 是本地文件直接获取文本框内容保存
* 不是本地文件,直接调用另存
*
*/
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JFrame;
public class SaveActionListener implements ActionListener {
TextArea ta;
JFrame frame = new JFrame();
public SaveActionListener(TextArea ta, JFrame frame) {
super();
this.ta = ta;
this.frame = frame;
}
@Override
public void actionPerformed(ActionEvent e) {
if(frame.getTitle().equals("无标题")) {
new SaveAsActionListener(frame, ta).actionPerformed(e);
}else {
saveFile(OpenActionListener.realepath);
}
}
private void saveFile(String path) {
FileWriter fw;
try {
fw = new FileWriter(path);
fw.write(ta.getText());
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
另存功能
import java.awt.FileDialog;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JTextArea;
/**
* 另存为功能
* 获取到要保存的路径
* 创建FileOutputStream
*
* @author xer
*
*/
public class SaveAsActionListener implements ActionListener{
JFrame frame = new JFrame();
private TextArea txArea;
String realPath;
public SaveAsActionListener(JFrame frame, TextArea txArea) {
super();
this.frame = frame;
this.txArea = txArea;
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
try {
FileDialog fd = new FileDialog(frame,"save",FileDialog.SAVE);
fd.setVisible(true);
realPath = fd.getDirectory()+fd.getFile();
writeFile(realPath, txArea);
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
private void writeFile(String path,TextArea textArea) {
if("nullnull".equals(path)) {
return;
}
//输出流
File file = new File(path);
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
//获取记事本文本框内的内容写入到要保存的文件中
fileOutputStream.write(txArea.getText().getBytes());
fileOutputStream.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
退出功能
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ExitActionListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.exit(0);
}
}
记录一些遗漏:最开始没有考虑到在打开或者保存对话框时没有判断文件名是否合法,导致出现一些异常