前言:
最近在作一个学习阶段的总结,回顾了下自己这段时间所做的一些程序,把以前的思路理了下觉得还有很多的地方安排的不是很好,写这篇博客,一则是锻炼下自己写博客的能力,再则也确实是想将自己对于文件操作(可能说的有点大了)的认识和大家分享下,觉得看完后留下点了什么东西也就知足了。
对于Java文件处理个人的理解:
文件的操作 个人理解就是对于文件的读取 修改以及保存,在Java的机制中 我们对于电脑硬件的访问是通过Java虚拟机这个平台完成的,比如 要读一个文件 首先将命令解释成能被虚拟机理解的指令,虚拟机按事先确定的方式去执行,最后对存取器进行访问。也就是说虚拟机在这中间起到中介的作用(这也是Java的一个突出的优点),但虚拟机对于用户来说是透明的。在这里我主要说下我对于文件保存方面的理解。顾名思义,文件保存就是将自己需要的信息以文件的形式保存在存取器中的过程。
需要牵涉到的知识点:
文件的保存就需要io流的知识,文件结构的理解。
io流就相当于是一个管道,连通了程序和存储介质 直接点说就是 当你要往存储介质传输信息的时候(也就是保存文件)就需要将信息先写入到这个管道中,再通过管道传输到指定的存储介质。文件结构:现在有各式各样的文件类型,比如说.txt .bmp .gif 等等 大相径庭 这些文件肯定是依据固有的规律来读取及保存的,一般情况下一种文件类型 包含了文件头和文件体,这些都没有一个定式的,用的人多了也就成了一种文件体了-_-
所用到的载体:
之前就有说 是总结前段时间的程序时有所想所以才想到写这篇文章的,用到的当然是一个简单的程序啦 呵呵 卖了这么多的关子 还是先看下我的这个程序吧:一个简单的具有保存功能的画板
功能比较的简单,但就和你们见到的能够将自己所画的图片以自己的格式保存在文件中,涉及到的代码:
程序部分:
第1部分:事先io序列化 也就是通过data类型的stream实现对对象的操作 这段代码借鉴了网上的高手,在这感谢下
package src;
import java.awt.Color;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
/**
* 实现IO流中的序列化;
*
* @author Administrator
*
*/
class model implements java.io.Serializable {
public void write() {
}
public void read() {
}
}
public class Object_class extends model {
// 保存画的形状 坐标 颜色;
int x1, y1, x2, y2, sign,red,green,blue;
public void read(DataInputStream input) {
try {
this.x1 = input.readInt();
this.y1 = input.readInt();
this.x2 = input.readInt();
this.y2 = input.readInt();
this.sign = input.readInt();
this.red= input.readInt();
this.green= input.readInt();
this.blue= input.readInt();
} catch (IOException e) {
e.printStackTrace();
}
}
public void write(DataOutputStream output) {
try {
output.writeInt(x1);
output.writeInt(y1);
output.writeInt(x2);
output.writeInt(y2);
output.writeInt(sign);
output.writeInt(red);
output.writeInt(green);
output.writeInt(blue);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
第2部分:窗口的初始化
package src;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class DrawUI extends JFrame {
private Graphics g;
//将监听器生成的队列传过来;
ArrayList<Object_class> arrobc = new ArrayList<Object_class>();
public static void main(String[] args) {
DrawUI d = new DrawUI();
d.draw();
}
// 生成基本框架;
public void draw() {
this.setTitle("具有保存功能的画板");
this.setSize(800, 600);
this.setLayout(new FlowLayout());
// 在窗体上添加组件;
// 菜单
JMenuBar menubar = new JMenuBar();
JMenu file = new JMenu("File");
JMenuItem open = new JMenuItem("打开");
JMenuItem save = new JMenuItem("保存");
file.add(open);
file.add(save);
menubar.add(file);
this.setJMenuBar(menubar);
// 生成左右2个编辑框;
JPanel left = new JPanel();
left.setPreferredSize(new Dimension(200, 780));
left.setLayout(new FlowLayout());
left.setBackground(Color.gray);
// 在左边容器上放入一个形状选择按钮,颜色选择器,
javax.swing.JComboBox jcbox = new JComboBox();
jcbox.addItem("line");
jcbox.addItem("oral");
jcbox.addItem("recle");
left.add(jcbox);
// 按钮当点击时弹出颜色选择框;
JButton colorchoose = new JButton("选择颜色");
left.add(colorchoose);
// 右边容器为画图区,需要添加鼠标监听器,设置其背景;
JPanel right = new JPanel();
right.setPreferredSize(new Dimension(580, 780));
right.setBackground(Color.white);
this.add(left);
this.add(right);
this.setVisible(true);
g = right.getGraphics();
Action_listen al = new Action_listen(g,this);
this.arrobc=al.arrobc;
colorchoose.addActionListener(al);
open.addActionListener(al);
save.addActionListener(al);
jcbox.addActionListener(al);
right.addMouseListener(al);
this.setDefaultCloseOperation(3);
this.setResizable(false);
this.setLocationRelativeTo(null);
}
// 重绘;
public void paint(Graphics g) {
super.paint(g);
for(int i=1;i<arrobc.size();i++){
Object_class obj=arrobc.get(i);
Color c=new Color(obj.red,obj.green,obj.blue);
draw(obj.x1,obj.y1,obj.x2,obj.y2,obj.sign,c);
}
}
// 画图形;
public void draw(int x1, int y1, int x2, int y2, int sign, Color choose) {
g.setColor(choose);
// 根据选择图性在右边容器中画图形;
if (sign == 0) {// 画直线;
g.drawLine(x1, y1, x2, y2);
}
if (sign == 1) {// 画圆;
int b = (int) Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1)
* (y2 - y1));
g.drawOval((x1 + x2) / 2 - b / 2, (y1 + y2) / 2 - b / 2, b, b);
}
if (sign == 2) {// 画矩形;
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1),
Math.abs(y2 - y1));
}
}
}
第3部分:事件监听
package src;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
public class Action_listen extends java.awt.event.MouseAdapter implements
java.awt.event.ActionListener {
private Color choose = new Color(100, 100, 100);
// 鼠标点击的顺序;点击的位置;
int turn = 0;
int x1, y1, x2, y2;
// 要画的形状;
int sign;
// 保存画图对象;
Object_class obc = new Object_class();
// 读取文件时的次数;
long count = 0;
// 用队列保存所有的画图对象;
ArrayList<Object_class> arrobc = new ArrayList<Object_class>();
private JFrame jf;
private Graphics g;
// 将画布传进来
public Action_listen(Graphics g, JFrame jf) {
this.jf = jf;
this.g = g;
}
// 事件监听包括 下拉框 菜单框 颜色选择按钮;
public void actionPerformed(ActionEvent e) {
// 分析事件源;
Object obj = e.getSource();
// 判断是什么;
if (obj instanceof JButton) {// 如果是按钮,弹出颜色选择
JColorChooser cho = new JColorChooser();
choose = cho.showDialog(null, "选择颜色", Color.black);
// 得到选择的颜色;如果没选择颜色 则将颜色设置成黑色;
if(choose==null){
choose=Color.black;
}
System.out.println(choose);
}
if (obj instanceof JMenuItem) {// 如果是菜单
JMenuItem item = (JMenuItem) obj;
String s = item.getActionCommand();
// 判断是保存还是打开;
if ("打开".equals(s)) {
// 首先将已经有的队列给清零;
for (int j = 0; j < arrobc.size(); j++) {
arrobc.remove(j);
}
jf.repaint();
// 弹出文件选择;
JFileChooser jfc = new JFileChooser();
jfc.showOpenDialog(null);
// 得到选择的文件;
File select = jfc.getSelectedFile();
// 如果,没选择文件则将是null;
if (null != select) {
// 生成输入流;
try {
DataInputStream input = new DataInputStream(
new FileInputStream(select));
int k = input.readInt();
System.out.println(k);
// 将输入流中的数据以对象的形式读进来;
while (k > 0) {
obc = new Object_class();
obc.read(input);
arrobc.add(obc);
k--;
}
jf.repaint();
} catch (Exception ef) {
ef.printStackTrace();
}
} else {
String opens = javax.swing.JOptionPane.showInputDialog(jf,
"请输入需要打开的文件 不输入就要报空指针了", "C:");
//先生成指定的文件 确保文件不是空的
File openfile=new File(opens);
//-_-一直循环到这家伙输入正确的文件地址;
if(openfile==null){
System.out.println("______");
opens = javax.swing.JOptionPane.showInputDialog(jf,
"请输入需要打开的文件 不输入就要报空指针了", "C:");
openfile=new File(opens);
}
try {
DataInputStream input = new DataInputStream(
new FileInputStream(opens));
int k = input.readInt();
System.out.println(k);
// 将输入流中的数据以对象的形式读进来;
while (k > 0) {
obc = new Object_class();
obc.read(input);
arrobc.add(obc);
k--;
}
jf.repaint();
} catch (Exception ef) {
ef.printStackTrace();
}
}
}
if ("保存".equals(s)) {
// 弹出文件窗口;
JFileChooser jfc = new JFileChooser();
jfc.showSaveDialog(null);
File select = jfc.getSelectedFile();
// 输出;把运行时保存的队列写入输出流中;
try {
DataOutputStream output = new DataOutputStream(
new FileOutputStream(select));
// 作为长度标志;
output.writeInt(arrobc.size() - 1);
// 将队列中的数据依此输出;
for (int i = 1; i < arrobc.size(); i++) {
obc = arrobc.get(i);
System.out.println("运行了几次" + i);
obc.write(output);
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
// 下拉框监听;
if (obj instanceof JComboBox) {
JComboBox jcb = (JComboBox) obj;
sign = jcb.getSelectedIndex();
// 得到选择的是哪项 0表示是直线;1,圆;2,矩形;并将选择的赋给属性;
}
}
// 右边画图区域的鼠标监听;
public void mouseReleased(MouseEvent e) {
int x = e.getX();
int y = e.getY();
// 判断是第几次点击;
if (turn == 0) {
x1 = x;
y1 = y;
turn++;
} else {
x2 = x;
y2 = y;
turn--;
// 开始画;
draw(x1, y1, x2, y2, sign, choose);
// 保存这次画的图形;
save(x1, y1, x2, y2, sign, choose);
System.out.println("队列的长度为:" + arrobc.size());
}
}
// 画图形;
public void draw(int x1, int y1, int x2, int y2, int sign, Color choose) {
g.setColor(choose);
// 根据选择图性在右边容器中画图形;
if (sign == 0) {// 画直线;
g.drawLine(x1, y1, x2, y2);
}
if (sign == 1) {// 画圆;
int b = (int) Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1)
* (y2 - y1));
g.drawOval((x1 + x2) / 2 - b / 2, (y1 + y2) / 2 - b / 2, b, b);
}
if (sign == 2) {// 画矩形;
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1),
Math.abs(y2 - y1));
}
}
// 将画图信息保存在队列中;
public void save(int x1, int y1, int x2, int y2, int sign, Color choose) {
obc = new Object_class();
obc.x1 = x1;
obc.y1 = y1;
obc.x2 = x2;
obc.y2 = y2;
obc.sign = sign;
obc.red = choose.getRed();
obc.green = choose.getGreen();
obc.blue = choose.getBlue();
arrobc.add(obc);
}
}
呵呵 这程序是不是很头晕,我也觉的- -,希望对你有点帮助 菜鸟级 不要喷!还是用母语说下吧 当我们在画板上画下了以个图形 相应的就将图形的信息保存在一个队列中 其中包括了单个图形的形状 坐标 颜色等信息 保存的时候先将图形的多少写进去 再分别以对象为单位写入每个图形的信息 先写个个数标志主要是 在文件读取的时候 如果没这个标志 要判断文件的结尾就有点困难 大家都知道的 读取文件的时候 是以字节为单位读取的 如果是最后个则返回-1 但自己实现对象为单位读取的话 结尾标志再以这个为基准不太好处理 自己写文件的时候给个标志来得方便 当然如果你想创建自己的文件头之类的也是可行的 但道理就和我给加一个标志是一样的 到网上拷贝个bmp文件格式 解析bmp文件用的着 :
位图文件头(bitmap-file header) BITMAPFILEHEADER bmfh
位图信息头(bitmap-information header) BITMAPINFOHEADER bmih
彩色表(color table) RGBQUAD aColors[]
图象数据阵列字节 BYTE aBitmapBits[]
呵呵拷多了不好 有兴趣的百度下 很多