所谓的流,也就类似于生活中的水流,有一端流入,有一段流出。java中的流对象的源端就是操作系统中的文件,目的端则是控制台或者文件,当我们要在程序里面调用操作系统中的文件的时候,也就是说我们要喝水了,所以要用输入流--InputStream,而我们要自定义文件格式的时候,也就是我们要倒水出去,所以要用OutputStresam。
java中所有流对象都是位于java.io包下,这就说明在调用流对象时一定要处理IO异常!根据处理的对象不同,我们可以把流分为几类:
按基本方法划分:
出流:在类名中必定会带有OutputStream
输入流:在类名中带有InputStream
按性质划分:
字节流:FileInputStream,FileOutputStream
过滤流:缓冲流 BufferedInputStream,BufferedOutputStream事实证明:缓冲流读取的速度远大于字节流
基本数据类型流:DataInputStream和DataOutputStream
对象流:ObjectInputStream和ObjectOutputStream
生活中我们要喝自来水首先得有个自来水厂,然后得有水管。在IO流里面,对象文件就是自来水厂,流对象就是水管,我们很据文件名创建输入流对象,然后打开水管,也就是调用流对象的读取的方法,可以一个字节一个字节的读取,也可以一次性读取所有文件,还可以用缓冲流读取,就这样,文件就流到了控制台中。
InputStream常用的方法有:
int available()
返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。
void close()
关闭此输入流并释放与该流关联的所有系统资源。
read()
从输入流中读取数据的下一个字节。
int read(byte[] b)
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b, int off, int len)
将输入流中最多 len 个数据字节读入 byte 数组。
OutputStream常用的方法有:
void close()
关闭此输出流并释放与此流有关的所有系统资源。
void flush()
刷新此输出流并强制写出所有缓冲的输出字节。
void write(byte[] b)
将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b)
将指定的字节写入此输出流。
根据学习的流的知识,完成了画板的保存和五子棋的保存。画板的保存就是把所画的图形的所有信息:坐标、颜色、形状保存到文件中,读取文件的时候提取信息进行重绘.......当然并不是保存成bmp图片。五子棋的保存和画板的是一样滴,所有就在这里给大家看一下画板的保存:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import javax.swing.JPanel;
import cn.tan.lesson8.Graph;
import cn.tan.lesson8.NJList;
import cn.tan.lessson7.Config;
/**
* 界面类
* *
*/
public class DrawFrame extends javax.swing.JFrame implements Serializable{
private cn.tan.lesson6.NJList njl=null;
private SaveFile sf=new SaveFile();
private DrawFrame df;
private Graph graph;
/**s
* 程序入口
* @param args
*/
public static void main(String[] args) {
//创建一个DrawFrame的对象
DrawFrame df = new DrawFrame();
df.showUI();
}
/**
* 显示画板窗体的类
*/
public void showUI(){
//设置窗体的属性
this.setSize(600, 500);
this.setTitle("简单画板");
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setResizable(false);
//创建主面板对象
JPanel pa=new JPanel();
//设置显示面板的大小和位置
pa.setBounds(0, 0, 500, 500);
//设置主面板的颜色
pa.setBackground(java.awt.Color.GRAY);
//创建一个工具面板
JPanel ta=new JPanel();
//设置工具面板的大小
ta.setBounds(500, 0, 100, 500);
ta.setBackground(java.awt.Color.BLACK);
//添加按钮选项
javax.swing.JButton line = new javax.swing.JButton("直线");
javax.swing.JButton Qline = new javax.swing.JButton("曲线");
javax.swing.JButton rect = new javax.swing.JButton("矩形");
javax.swing.JButton oval = new javax.swing.JButton("圆形");
javax.swing.JButton btnColor = new javax.swing.JButton("颜色");
javax.swing.JButton savefile = new javax.swing.JButton("保存文件");
javax.swing.JButton openfile = new javax.swing.JButton("读取文件");
ta.add(btnColor);
ta.add(Qline);
ta.add(line);
ta.add(rect);
ta.add(oval);
ta.add(savefile);
ta.add(openfile);
this.setLayout(null);
this.add(pa);
this.add(ta);
this.setVisible(true);
//得到事件源上的画布对象
final java.awt.Graphics g = pa.getGraphics();
//创建一个DrawMotionListener类
dml = new DrawListener(g,this);
//给事件源添加鼠标拖动的监听器
pa.addMouseMotionListener(dml);
pa.addMouseListener(dml);
//匿名内部类处理读取事件
openfile.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
String command=e.getActionCommand();
if(command.equals("读取文件")){
njl = sf.openFile();
this. paint(g);
}
}
private void paint(Graphics g) {
if(njl != null){
//获取所画图形的数据
for(int i=0;i<njl.size();i++){
cn.tan.lesson6.Graph graph = njl.get(i);
//判断图形
int value=graph.setvalue();
System.out.println(value);
if(value==2){
//设置颜色
Color cl=new Color(graph.setr(),graph.setg(),graph.setb());
g.setColor(cl);
//画直线
g.drawLine(graph.getX1(), graph.getY1(), graph.getX2(), graph.getY2());
} if(value==1){
//设置颜色
Color cl=new Color(graph.setr(),graph.setg(),graph.setb());
g.setColor(cl);
//画曲线
g.drawLine(graph.getX1(), graph.getY1(), graph.getX2(), graph.getY2());
}if(value==3){
//设置颜色
Color cl=new Color(graph.setr(),graph.setg(),graph.setb());
g.setColor(cl);
g.drawRect(Math.min(graph.getX1(),graph.getX2()),Math.min(graph.getY1(), graph.getY2()),Math.abs(graph.getX2()-graph.getX1()) , Math.abs(graph.getY2()-graph.getY1()));
}if(value==4){
//设置颜色
Color cl=new Color(graph.setr(),graph.setg(),graph.setb());
g.setColor(cl);
//画圆
g.drawOval(Math.min(graph.getX1(),graph.getX2()),Math.min(graph.getY1(), graph.getY2()),Math.abs(graph.getX2()-graph.getX1()) , Math.abs(graph.getY2()-graph.getY1()));
}
}
}
}
});
line.addActionListener(dml);
rect.addActionListener(dml);
oval.addActionListener(dml);
btnColor.addActionListener(dml);
Qline.addActionListener(dml);
savefile.addActionListener(dml);
openfile.addActionListener(dml);
savefile.addMouseListener(dml);
}
/**
* 重写窗体类的重绘方法
*/
public void paint(java.awt.Graphics g){
//首先调用父类的重绘方法
super.paint(g);
//判断dml对象是否为null
if(null != dml){
//获取所画图形的数据
for(int i=0;i<dml.getGraphList().size();i++){
cn.tan.lesson6.Graph graph = dml.getGraphList().get(i);
//判断图形
if(graph.getItem().equals("曲线")){
//设置颜色
g.setColor(graph.getColor());
//画曲线
g.drawLine(graph.getX1(), graph.getY1(), graph.getX2(), graph.getY2());
}
if(graph.getItem().equals("直线")){
//设置颜色
g.setColor(graph.getColor());
//画直线
g.drawLine(graph.getX1(), graph.getY1(), graph.getX2(), graph.getY2());
}
if(graph.getItem().equals("矩形")){
//设置颜色
g.setColor(graph.getColor());
//画矩形
g.drawRect(Math.min(graph.getX1(),graph.getX2()),Math.min(graph.getY1(), graph.getY2()),Math.abs(graph.getX2()-graph.getX1()) , Math.abs(graph.getY2()-graph.getY1()));
}
if(graph.getItem().equals("圆形")){
//设置颜色
g.setColor(graph.getColor());
//画圆
g.drawOval(Math.min(graph.getX1(),graph.getX2()),Math.min(graph.getY1(), graph.getY2()),Math.abs(graph.getX2()-graph.getX1()) , Math.abs(graph.getY2()-graph.getY1()));
}
}
}
if(njl != null){
//获取所画图形的数据
for(int i=0;i<njl.size();i++){
cn.tan.lesson6.Graph graph = njl.get(i);
//判断图形
int value=graph.setvalue();
System.out.println(value);
if(value==2){
//设置颜色
Color cl=new Color(graph.setr(),graph.setg(),graph.setb());
g.setColor(cl);
//画直线
g.drawLine(graph.getX1(), graph.getY1(), graph.getX2(), graph.getY2());
} if(value==1){
//设置颜色
Color cl=new Color(graph.setr(),graph.setg(),graph.setb());
g.setColor(cl);
//画曲线
g.drawLine(graph.getX1(), graph.getY1(), graph.getX2(), graph.getY2());
}if(value==3){
//设置颜色
Color cl=new Color(graph.setr(),graph.setg(),graph.setb());
g.setColor(cl);
g.drawRect(Math.min(graph.getX1(),graph.getX2()),Math.min(graph.getY1(), graph.getY2()),Math.abs(graph.getX2()-graph.getX1()) , Math.abs(graph.getY2()-graph.getY1()));
}if(value==4){
//设置颜色
Color cl=new Color(graph.setr(),graph.setg(),graph.setb());
g.setColor(cl);
//画圆
g.drawOval(Math.min(graph.getX1(),graph.getX2()),Math.min(graph.getY1(), graph.getY2()),Math.abs(graph.getX2()-graph.getX1()) , Math.abs(graph.getY2()-graph.getY1()));
}
}
}
}
//定義一個顏色屬性
private java.awt.Color color;
//定义一个DrawMotionListener类的对象属性
private DrawListener dml = null;
}
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
/**
* 监听器类
* *
*/
public class DrawListener implements java.awt.event.ActionListener, java.awt.event.MouseListener,
java.awt.event.MouseMotionListener {
// 定义四个变量,用来保存坐标
private int x1, y1, x2, y2;
// 定义一个画布对象
private java.awt.Graphics g;
// 定義一個窗體類對象
private DrawFrame df;
// 添加一个计数器
private int count = 0;
// 创建一个自定义队列对象,用来存储所画图形的信息
private GraphNJList graphList = new GraphNJList();
private java.awt.Color color = java.awt.Color.BLACK;
private String command;
private String filename;
// private Graph gh;
private SaveFile sf=new SaveFile();
/**
* 构造函数,初始化画布属性
*
* @param g
*/
public DrawListener(java.awt.Graphics g, DrawFrame df) {
this.g = g;
this.df = df;
}
/**
* 鼠标的按下事件处理方法
*/
public void actionPerformed(ActionEvent e) {
command = e.getActionCommand();
if ("颜色".equals(command)) {
// 弹出颜色选择器,得到选择的颜色
color = javax.swing.JColorChooser.showDialog(null, "请选择颜色",
java.awt.Color.BLACK);
}
}
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
g.setColor(color);
}
public void mouseReleased(MouseEvent e) {
x2 = e.getX();
y2 = e.getY();
if ("直线".equals(command)) {
g.drawLine(x1, y1, x2, y2);
Graph graph = new Graph("直线",color, x1, y1, x2, y2);
//将对象添加到队列中
graphList.add(graph);
}
if ("矩形".equals(command)) {
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1),
Math.abs(y2 - y1));
Graph graph = new Graph("矩形",color, x1, y1, x2, y2);
//将对象添加到队列中
graphList.add(graph);
}
if ("圆形".equals(command)) {
g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1),
Math.abs(y2 - y1));
Graph graph = new Graph("圆形",color, x1, y1, x2, y2);
//将对象添加到队列中
graphList.add(graph);
} if("保存文件".equals(command)){
//调用保存文件的方法
sf.saveFile(this.getGraphList());
System.out.print("调用了");
}
}
/**
* 鼠标按下时的拖动事件处理方法
*/
public void mouseDragged(MouseEvent e) {
x2 = e.getX();
y2 = e.getY();
// 設置顏色
// 开始画曲线了
if ("曲线".equals(command)) {
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
//创建一个Graph类的对象
Graph graph = new Graph("曲线",color, x1, y1, x2, y2);
//将对象添加到队列中
graphList.add(graph);
x1 = x2;
y1 = y2;
}
if("橡皮".equals(command)){
g.setColor(java.awt.Color.WHITE);
g.fillOval(x2, y2, 20, 20);
//创建一个Graph类的对象
Graph graph = new Graph("橡皮",java.awt.Color.WHITE, x1, y1, x2, y2);
//将对象添加到队列中
graphList.add(graph);
}
}
/**
* 返回自定义队列对象
*
* @return graphList
*/
public GraphNJList getGraphList() {
return graphList;
}
public void mouseMoved(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
}
import java.io.Serializable;
/**
* 存储图片的类
*
* *
*/
public class Graph {
private java.awt.Color color;
private String item;
private int x1,x2,y1,y2;
private int value;
private static int R;
private static int G;
private static int B;
// 构造函数用来初始化属性
public Graph(String item, java.awt.Color color, int x1, int y1, int x2,
int y2) {
this.item = item;
this.color = color;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
// 构造函数用来初始化属性
public Graph(int x1, int y1, int x2, int y2, int R, int G, int B, int value) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.R = R;
this.G = G;
this.B = B;
this.value=value;
}
public java.awt.Color getColor() {
return color;
}
public void setColor(java.awt.Color color) {
this.color = color;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public int getX1() {
return x1;
}
public void setX1(int x1) {
this.x1 = x1;
}
public int getY1() {
return y1;
}
public void setY1(int y1) {
this.y1 = y1;
}
public int getX2() {
return x2;
}
public void setX2(int x2) {
this.x2 = x2;
}
public int getY2() {
return y2;
}
public void setY2(int y2) {
this.y2 = y2;
}
public static int setr() {
return R;
}
public static int setg() {
return G;
}
public static int setb() {
return B;
}
public int setvalue(){
System.out.println("*****************"+value);
return value;
}
}
public class GraphNJList implements NJList{
//先来定义一个数组属性(类一级的变量或者全局变量)
private Graph [] array = null;
/**
* 定义一个构造函数,用来初始化属性
*/
public GraphNJList(){
array = new Graph [0];
}
/**
* 向队列的末尾追加元素
*/
@Override
public void add(Graph graph) {
//创建一个新的数组,该数组的大小是属性数组的长度+1
Graph [] temp = new Graph [array.length+1];
//将属性数组中的数据存入到temp数组中
for(int i=0;i<array.length;i++){
//将属性数组中的元素存入到temp中
temp[i] = array[i];
}
//将要追加的元素添加到最后以一个位置
temp[array.length] = graph;
//互换数组
array = temp;
}
/**
* 获取指定索引位置的元素
*/
@Override
public Graph get(int index) {
return array[index];
}
/**
* 获取队列的大小
*/
@Override
public int size() {
return array.length;
}
}
/**
* 接口类
* *
*/
public interface NJList {
/**
* 是向队列中添加一个元素
*/
public void add(Graph graph);
/**
* 获取指定索引位置的元素值
*/
public Graph get(int index);
/**
* 获取自定义队列的大小
*/
public int size();
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 画板保存类
*
* *
*/
public class SaveFile {
/**
* 保存画板地方法
* @param njl
*/
private int x1,x2,y1,y2;
private int value;
public void saveFile(NJList njl) {
String fileName = "src\\cn\\tan\\lesson6\\graph";
try {
FileOutputStream os = new FileOutputStream(fileName);
DataOutputStream dos = new DataOutputStream(os);
// 输出图形的总数到文件
dos.writeInt(njl.size());
// 循环队列中的图形数据
for (int i = 0; i < njl.size(); i++) {
// 得到Graph对象
Graph g = njl.get(i);
// 得到坐标值
int x1 = g.getX1();
int y1 = g.getY1();
int x2 = g.getX2();
int y2 = g.getY2();
//得到颜色的rgb值
int R=g.getColor().getRed();
int G=g.getColor().getGreen();
int B=g.getColor().getBlue();
//得到图形名称
if(g.getItem().equals("曲线")){
value=1;
}else if(g.getItem().equals("直线")){
value=2;
}else if(g.getItem().equals("矩形")){
value=3;
}else if(g.getItem().equals("圆形")){
value=4;
}
// 输出图形的坐标到文件中
dos.writeInt(x1);
dos.writeInt(y1);
dos.writeInt(x2);
dos.writeInt(y2);
dos.writeInt(R);
dos.writeInt(G);
dos.writeInt(B);
dos.writeInt(value);
System.out.println("保存的坐标:"+x1+"\t"+y1+"\t"+x2+"\t"+y2+"颜色"+"\tr:"+R+"\tg:"+G+"\tb:"+B+"图形值:"+value);
}
// 强制写入并关闭
dos.flush();
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 打开文件,并获取存储在文件中的数据
*
* @return 返回所有的数据
*/
public NJList openFile() {
// 实例化一个自定义队列对象
NJList njl = new GraphNJList();
String fileName = "src\\cn\\tan\\lesson6\\graph";
try {
FileInputStream fis = new FileInputStream(fileName);
DataInputStream dis = new DataInputStream(fis);
// 输入图形的总数到文件
int size = dis.readInt();
// 循环队列中的图形数据
for (int i = 0; i < size; i++) {
// 得到坐标值
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
int R=dis.readInt();
int G=dis.readInt();
int B=dis.readInt();
int value=dis.readInt();
System.out.println("读取的坐标:"+x1+"\t"+y1+"\t"+x2+"\t"+y2+"颜色"+"\tr:"+R+"\tg:"+G+"\tb:"+B+"图形值:"+value);
// 实例化Graph对象
Graph g = new Graph(x1, y1, x2, y2,R,G,B,value);
njl.add(g);
}
// 关闭
dis.close();
} catch (Exception e) {
e.printStackTrace();
}
return njl;
}
}