★文件流

文件操作是最简单最直接也是最容易想到的一种方式,我们说的文件操作不仅仅是通过FileInputStream/FileOutputStream这么“裸”的方式直接把数据写入到本地文件(像我以前写的一个扫雷的小游戏JavaMine就是这样保存一局的状态的),这样就比较“底层”了。

主要类与方法和描述

1. FileInputStream.read() //从本地文件读取二进制格式的数据

2. FileReader.read() //从本地文件读取字符(文本)数据

3. FileOutputStream.write() //保存二进制数据到本地文件

4. FileWriter.write() //保存字符数据到本地文件

★XML

和上面的单纯的I/O方式相比,XML就显得“高档”得多,以至于成为一种数据交换的标准。以DOM方式为例,它关心的是首先在内存中构造文档树,数据保存在某个结点上(可以是叶子结点,也可以是标签结点的属性),构造好了以后一次性的写入到外部文件,但我们只需要知道文件的位置,并不知道I/O是怎么操作的,XML操作方式可能多数人也实践过,所以这里也只列出相关的方法,供初学者预先了解一下。主要的包是javax.xml.parsers,org.w3c.dom,javax.xml.transform。

主要类与方法和描述

1. DocumentBuilderFactory.newDocumentBuilder().parse() //解析一个外部的XML文件,得到一个Document对象的DOM树

2. DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() //初始化一棵DOM树

3. Document.getDocumentElement().appendChild() //为一个标签结点添加一个子结点

4. Document.createTextNode() //生成一个字符串结点

5. Node.getChildNodes() //取得某个结点的所有下一层子结点

6. Node.removeChild()  //删除某个结点的子结点

7. Document.getElementsByTagName() 查找所有指定名称的标签结点

8. Document.getElementById() //查找指定名称的一个标签结点,如果有多个符合,则返回某一个,通常是第一个

9. Element.getAttribute() //取得一个标签的某个属性的的值

10. Element.setAttribute() //设置一个标签的某个属性的的值

11. Element.removeAttribute() //删除一个标签的某个属性

12. TransformerFactory.newInstance().newTransformer().transform() //将一棵DOM树写入到外部XML文件

★序列化

使用基本的文件读写方式存取数据,如果我们仅仅保存相同类型的数据,则可以用同一种格式保存,譬如在我的JavaMine中保存一个盘局时,需要保存每一个方格的坐标、是否有地雷,是否被翻开等,这些信息组合成一个“复合类型”;相反,如果有多种不同类型的数据,那我们要么把它分解成若干部分,以相同类型(譬如String)保存,要么我们需要在程序中添加解析不同类型数据格式的逻辑,这就很不方便。于是我们期望用一种比较“高”的层次上处理数据,程序员应该花尽可能少的时间和代码对数据进行解析,事实上,序列化操作为我们提供了这样一条途径。

序列化(Serialization)大家可能都有所接触,它可以把对象以某种特定的编码格式写入或从外部字节流(即ObjectInputStream/ObjectOutputStream)中读取。序列化一个对象非常之简单,仅仅实现一下Serializable接口即可,甚至都不用为它专门添加任何方法:

1. public class MySerial implements java.io.Serializable

2. {

3.   //...

4. }

但有一个条件:即你要序列化的类当中,它的每个属性都必须是是“可序列化”的。这句话说起来有点拗口,其实所有基本类型(就是int,char,boolean之类的)都是“可序列化”的,而你可以看看JDK文档,会发现很多类其实已经实现了Serializable(即已经是“可序列化”的了),于是这些类的对象以及基本数据类型都可以直接作为你需要序列化的那个类的内部属性。如果碰到了不是“可序列化”的属性怎么办?对不起,那这个属性的类还需要事先实现Serializable接口,如此递归,直到所有属性都是“可序列化”的。

主要类与方法和描述

1. ObjectOutputStream.writeObject() //将一个对象序列化到外部字节流

2. ObjectInputStream.readObject() //从外部字节流读取并重新构造对象

从实际应用上看来,“Serializable”这个接口并没有定义任何方法,仿佛它只是一个标记(或者说像是Java的关键字)而已,一旦虚拟机看到这个“标记”,就会尝试调用自身预定义的序列化机制,除非你在实现Serializable接口的同时还定义了私有的readObject()或writeObject()方法。这一点很奇怪。不过你要是不愿意让系统使用缺省的方式进行序列化,那就必须定义上面提到的两个方法:

1. public class MySerial implements java.io.Serializable

2. {

3.   private void writeObject(java.io.ObjectOutputStream out) throws IOException

4.   {

5.     //...

6.   }

7.   private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException

8.   {

9.     //...

10.   }

11.   //...

12. }

譬如你可以在上面的writeObject()里调用默认的序列化方法ObjectOutputStream.defaultWriteObject();譬如你不愿意将某些敏感的属性和信息序列化,你也可以调用ObjectOutputStream.writeObject()方法明确指定需要序列化那些属性。关于用户可定制的序列化方法,我们将在后面提到。

★Bean

上面的序列化只是一种基本应用,你把一个对象序列化到外部文件以后,用notepad打开那个文件,只能从为数不多的一些可读字符中猜到这是有关这个类的信息文件,这需要你熟悉序列化文件的字节编码方式,那将是比较痛苦的(在《Core Java 2》第一卷里提到了相关编码方式,有兴趣的话可以查看参考资料),某些情况下我们可能需要被序列化的文件具有更好的可读性。另一方面,作为Java组件的核心概念“JavaBeans”,从JDK 1.4开始,其规范里也要求支持文本方式的“长期的持久化”(long-term persistence)。

打开JDK文档,java.beans包里的有一个名为“Encoder”的类,这就是一个可以序列化bean的实用类。和它相关的两个主要类有XMLEcoder和XMLDecoder,显然,这是以XML文件的格式保存和读取bean的工具。他们的用法也很简单,和上面ObjectOutputStream/ObjectInputStream比较类似。

主要类与方法和描述

1. XMLEncoder.writeObject() //将一个对象序列化到外部字节流

2. XMLDecoder.readObject() //从外部字节流读取并重新构造对象

如果一个bean是如下格式:

1. public class MyBean

2. {

3.   int i;

4.   char[] c;

5.   String s;

6.   //...(get和set操作省略)...

7. }

那么通过XMLEcoder序列化出来的XML文件具有这样的形式:

1

a

b

c

fox jump!

像AWT和Swing中很多可视化组件都是bean,当然也是可以用这种方式序列化的,下面就是从JDK文档中摘录的一个JFrame序列化以后的XML文件:

frame1

0

0

200

200

Hello

true

因此但你想要保存的数据是一些不是太复杂的类型的话,把它做成bean再序列化也不失为一种方便的选择。

★Properties

在以前我总结的一篇关于集合框架的小文章里提到过,Properties是历史集合类的一个典型的例子,这里主要不是介绍它的集合特性。大家可能都经常接触一些配置文件,如Windows的ini文件,Apache的conf文件,还有Java里的properties文件等,这些文件当中的数据以“关键字-值”对的方式保存。“环境变量”这个概念都知道吧,它也是一种“key-value”对,以前也常常看到版上问“如何取得系统某某信息”之类的问题,其实很多都保存在环境变量里,只要用一条

1. System.getProperties().list(System.out);

就能获得全部环境变量的列表:

-- listing properties --

java.runtime.name=Java(TM) 2 Runtime Environment, Stand...

sun.boot.library.path=C:\Program Files\Java\j2re1.4.2_05\bin

java.vm.version=1.4.2_05-b04

java.vm.vendor=Sun Microsystems Inc.

java.vendor.url=http://java.sun.com/

path.separator=;

java.vm.name=Java HotSpot(TM) Client VM

file.encoding.pkg=sun.io

user.country=CN

sun.os.patch.level=Service Pack 1

java.vm.specification.name=Java Virtual Machine Specification

user.dir=d:\my documents\项目\eclipse\SWTDemo

java.runtime.version=1.4.2_05-b04

java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment

java.endorsed.dirs=C:\Program Files\Java\j2re1.4.2_05\li...

os.arch=x86

java.io.tmpdir=C:\DOCUME~1\cn2lx0q0\LOCALS~1\Temp\

line.separator=

java.vm.specification.vendor=Sun Microsystems Inc.

user.variant=

os.name=Windows XP

sun.java2d.fontpath=

java.library.path=C:\Program Files\Java\j2re1.4.2_05\bi...

java.specification.name=Java Platform API Specification

java.class.version=48.0

java.util.prefs.PreferencesFactory=java.util.prefs.WindowsPreferencesFac...

os.version=5.1

user.home=D:\Users\cn2lx0q0

user.timezone=

java.awt.printerjob=sun.awt.windows.WPrinterJob

file.encoding=GBK

java.specification.version=1.4

user.name=cn2lx0q0

java.class.path=d:\my documents\项目\eclipse\SWTDemo\bi...

java.vm.specification.version=1.0

sun.arch.data.model=32

java.home=C:\Program Files\Java\j2re1.4.2_05

java.specification.vendor=Sun Microsystems Inc.

user.language=zh

awt.toolkit=sun.awt.windows.WToolkit

java.vm.info=mixed mode

java.version=1.4.2_05

java.ext.dirs=C:\Program Files\Java\j2re1.4.2_05\li...

sun.boot.class.path=C:\Program Files\Java\j2re1.4.2_05\li...

java.vendor=Sun Microsystems Inc.

file.separator=\

java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport...

sun.cpu.endian=little

sun.io.unicode.encoding=UnicodeLittle

sun.cpu.isalist=pentium i486 i386

主要类与方法和描述

1. load() //从一个外部流读取属性

2. store() //将属性保存到外部流(特别是文件)

3. getProperty() //取得一个指定的属性

4. setProperty() //设置一个指定的属性

5. list() //列出这个Properties对象包含的全部“key-value”对

6. System.getProperties() //取得系统当前的环境变量

你可以这样保存一个properties文件:

1. Properties prop = new Properties();

2. prop.setProperty("key1", "value1");

3. ...

4. FileOutputStream out = new FileOutputStream("config.properties");

5. prop.store(out, "--这里是文件头,可以加入注释--");

★Preferences

如果我说Java里面可以不使用JNI的手段操作Windows的注册表你信不信?很多软件的菜单里都有“Setting”或“Preferences”这样的选项用来设定或修改软件的配置,这些配置信息可以保存到一个像上面所述的配置文件当中,如果是Windows平台下,也可能会保存到系统注册表中。从JDK 1.4开始,Java在java.util下加入了一个专门处理用户和系统配置信息的java.util.prefs包,其中一个类Preferences是一种比较“高级”的玩意。从本质上讲,Preferences本身是一个与平台无关的东西,但不同的OS对它的SPI(Service Provider Interface)的实现却是与平台相关的,因此,在不同的系统中你可能看到首选项保存为本地文件、LDAP目录项、数据库条目等,像在Windows平台下,它就保存到了系统注册表中。不仅如此,你还可以把首选项导出为XML文件或从XML文件导入。

主要类与方法和描述

1. systemNodeForPackage() //根据指定的Class对象得到一个Preferences对象,这个对象的注册表路径是从“HKEY_LOCAL_MACHINE\”开始的

2. systemRoot() //得到以注册表路径HKEY_LOCAL_MACHINE\SOFTWARE\Javasoft\Prefs 为根结点的Preferences对象

3. userNodeForPackage() //根据指定的Class对象得到一个Preferences对象,这个对象的注册表路径是从“HKEY_CURRENT_USER\”开始的

4. userRoot() //得到以注册表路径HKEY_CURRENT_USER\SOFTWARE\Javasoft\Prefs 为根结点的Preferences对象

5. putXXX() //设置一个属性的值,这里XXX可以为基本数值型类型,如int、long等,但首字母大写,表示参数为相应的类型,也可以不写而直接用put,参数则为字符串

6. getXXX() //得到一个属性的值

7. exportNode() //将全部首选项导出为一个XML文件

8. exportSubtree() //将部分首选项导出为一个XML文件

9. importPreferences() //从XML文件导入首选项

你可以按如下步骤保存数据:

1. Preferences myPrefs1 = Preferences.userNodeForPackage(this);// 这种方法是在“HKEY_CURRENT_USER\”下按当前类的路径建立一个注册表项

2. Preferences myPrefs2 = Preferences.systemNodeForPackage(this);// 这种方法是在“HKEY_LOCAL_MACHINE\”下按当前类的路径建立一个注册表项

3. Preferences myPrefs3 = Preferences.userRoot().node("com.jungleford.demo");// 这种方法是在“HKEY_CURRENT_USER\SOFTWARE\Javasoft\Prefs\”下按“com\jungleford\demo”的路径建立一个注册表项

4. Preferences myPrefs4 = Preferences.systemRoot().node("com.jungleford.demo");// 这种方法是在“HKEY_LOCAL_MACHINE\SOFTWARE\Javasoft\Prefs\”下按“com\jungleford\demo”的路径建立一个注册表项

5. myPrefs1.putInt("key1", 10);

6. myPrefs1.putDouble("key2", -7.15);

7. myPrefs1.put("key3", "value3");

8. FileOutputStream out = new FileOutputStream("prefs.xml");

9. myPrefs1.exportNode(out);

文件I/O:文件流→序列化的更多相关文章

  1. 文件夹和文件、Path类、流、序列化

    循环访问目录树 参考: http://msdn.microsoft.com/zh-cn/library/bb513869.aspx 循环访问目录树”的意思是在指定的根文件夹下,访问每个嵌套子目录中任意 ...

  2. java操作文件常用的 IO流对象

    1.描述:流是字节数据或字符数据序列.Java采用输入流对象和输出流对象来支持程序对数据的输入和输出.输入流对象提供了数据从源点流向程序的管道,程序可以从输入流对象读取数据:输出流对象提供了数据从程序 ...

  3. 文件_ _android从资源文件中读取文件流并显示的方法

    ======== 1   android从资源文件中读取文件流并显示的方法. 在android中,假如有的文本文件,比如TXT放在raw下,要直接读取出来,放到屏幕中显示,可以这样: private ...

  4. java io流(字符流) 文件打开、读取文件、关闭文件

    java io流(字符流) 文件打开 读取文件 关闭文件 //打开文件 //读取文件内容 //关闭文件 import java.io.*; public class Index{ public sta ...

  5. C++学习47 文件的概念 文件流类与文件流对象 文件的打开与关闭

    迄今为止,我们讨论的输入输出是以系统指定的标准设备(输入设备为键盘,输出设备为显示器)为对象的.在实际应用中,常以磁盘文件作为对象.即从磁盘文件读取数据,将数据输出到磁盘文件.磁盘是计算机的外部存储器 ...

  6. C# IO操作(四)大文件拷贝(文件流的使用)、文件编码

         大文件拷贝(文件流的使用).文件编码 首先说一下大文件拷贝和文件流,因为计算机的内存资源是有限的,面对几个G甚至更大的文件,需要通过程序来完成拷贝,就需要用到文件流(因为我们无法做到把文件一 ...

  7. Java学习笔记之I/O流(读取压缩文件以及压缩文件)

    1.读取压缩文件:ZipInputStream 借助ZipFile类的getInputStream方法得到压缩文件的指定项的内容,然后传递给InputStreamReader类的构造方法,返回给Buf ...

  8. 文件是数据的流式IO抽象,mmap是对文件的块式IO抽象

    文件是数据的流式IO抽象,mmap是对文件的块式IO抽象

  9. java 写 Excel(不生成实体文件,写为流的形式)

    java 写 Excel(不生成实体文件,写为流的形式) public String exportReportExcel(String mediaCode, List<SimpleMediaRe ...

  10. java 文件字节和字符流 缓冲流

    流的原理 1) 在 Java 程序中,对于数据的输入/输出操作以“流”(stream) 方式进行:2) J2SDK 提供了各种各样的“流”类,用以获取不同种类的数据:程序中通过标准的方法输入或输出数据 ...

随机推荐

  1. $(document).ready()方法和window.onload()方法

    $(document).ready()方法和window.onload()方法 $(document).ready()方法是JQuery中的方法,他在DOM完全就需时就可以被调用,不必等待这些元素关联 ...

  2. LoadRunner参数化时的各个选项说明

    LoadRunner参数化时的各个选项说明 分类: LoadRunner 2009-03-27 09:32 6294人阅读 评论(1) 收藏 举报 loadrunnerrandomgeneratore ...

  3. Linux 文件系统类型 文件系统结构 与Windows文件系统的比较

    摘自:http://blog.csdn.net/gelivable007/article/details/7249365 Linux 文件系统类型 磁盘文件系统.包括硬盘.CD-ROM.DVD.USB ...

  4. 【原创】说说JSON和JSONP,也许你会豁然开朗,含jQuery用例

    说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服 ...

  5. Android studio 使用心得(三)—从Eclipse迁移到Android studio

    断断续续的也算是把eclipse上的代码成功迁移到android studio上来了,现在,我同事继续用eclipse,我用android studio,svn上还是之前eclipse的项目,迁移成功 ...

  6. STL容器分析--queue

    queue,顾名思义,是指队列.满足先进先出的原则.

  7. Linux - 进程控制 代码(C)

    进程控制 代码(C) 本文地址:http://blog.csdn.net/caroline_wendy 输出进程ID.getpid(). 代码: /*By C.L.Wang * Eclipse CDT ...

  8. PT100三线制恒流源接法

    http://www.eepw.com.cn/article/189480_2.htm 下图为恒流源激励的三线制Pt100的一种典型接法.其基本原理是假设Pt100的三条引线采用相同长度的同型线缆,具 ...

  9. 3.3v转5v开关电源芯片LM2731

    方案一 输入3.3(可为2.7~14v):输出5v,700ma.已经过实际验证. 其中:C1,C2为贴片陶瓷电容,Cf也为贴片陶瓷电容,L1为6.8uH 电感 输出值只和R1,R2的值有关,但手册中又 ...

  10. windows和linux中换行符的转换

    数据开发平台使用上传脚本报错:保存失败,文件编码格式不正确,请修改文件换行符为Unix终束符! 修改方式:DOS系统下,使用文本编译器另存为,然后选择换行符为unix终束符. 解释: windows ...