JAVA中的IO流(二)
JAVA中的IO流(一)
OjectInputStream / ObjectOutputStream
对象流:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把JAVA中的对象写入到数据源中,也能把对象从数据源中还原回来。
序列化 :用ObjectOutputStream类保存基本类型数据或对象的机制。
反序列化:用ObjectInputStream类读取基本类型数据或对象的机制。
注意:ObjectOutputStream类和ObjectInputStream类不能序列化static和transient修饰的成员变量。
对象的序列化机制:允许把内存中的JAVA对象转换成平台无关的二进制流,从而允许把这种二进制流持久的保存在磁盘上,或通过网络江浙沪总二进制流传输到另一个网络节点。当其他程序获取了这种二进制流,就可以恢复成原来的JAVA对象。
序列化的好处:可将任何实现了Serializable接口的对象转化为字节数据,使其在保存或传输时可以随时还原。
如果需要让某个对象支持序列化机制,那么就必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,那么该类必须实现如下两个接口:Serializable / Externalizable。否则,会抛出NotSerializableException的异常。
@Test
//序列化过程,将内存中的java对象保存到磁盘中或通过网络传输出去~~
public void test_ObjectOutputStream(){
ObjectOutputStream objectOutputStream = null;
try {
FileOutputStream fileOutputStream = new FileOutputStream("src\\Object.data");
objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(new String("Welcom to the new world!"));
objectOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (objectOutputStream != null){
objectOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
//反序列化过程
public void test_ObjectInputStream(){
ObjectInputStream objectInputStream = null;
try {
FileInputStream fileInputStream = new FileInputStream("src\\Object.data");
objectInputStream = new ObjectInputStream(fileInputStream);
Object object = objectInputStream.readObject();
String str = (String)object;
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (objectInputStream != null) {
objectInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
参考代码:
import java.io.Serializable;
/*
创建一个Person类,将该类对象进行序列化与反序列化操作~~
要想使Person类的对象是可进行序列化操作的,就需要实现标识接口 Serializable
当前类提供一个全局常量——serialVersionUID
保证当前类内部所有属性也必须是可序列化的(默认情况下爱,基本数据类型是可序列化的!)
*/
public class Person implements Serializable {
public static final long serialVersionUID = 475463534532L;
//需要当前类提供一个全局常量
private String name;
private int age;
private boolean isMale;
public Person(String name, int age, boolean isMale) {
this.name = name;
this.age = age;
this.isMale = isMale;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean isMale() {
return isMale;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setMale(boolean male) {
isMale = male;
}
@Override
public String toString() {
return "Person{"+"name='"+ name + '\'' +", age=" +age +", isMale="+ isMale + '}';
}
}
@Test
//序列化过程,将内存中的java对象保存到磁盘中或通过网络传输出去~~
public void test_ObjectOutputStream(){
ObjectOutputStream objectOutputStream = null;
try {
FileOutputStream fileOutputStream = new FileOutputStream("src\\Object.data");
objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(new Person("张三",23,true));
objectOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (objectOutputStream != null){
objectOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
//反序列化过程
public void test_ObjectInputStream(){
ObjectInputStream objectInputStream = null;
try {
FileInputStream fileInputStream = new FileInputStream("src\\Object.data");
objectInputStream = new ObjectInputStream(fileInputStream);
Person person = (Person)objectInputStream.readObject();
System.out.println(person);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (objectInputStream != null) {
objectInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
RandomAccessFile类
RandomAccessFile 声明在java.io包下面,但直接继承于java.lang.Object类,并且它实现了DataInput、DataOutput这两个接口,也就意味着这个类即可以读也可以写。
RandomAccessFile类支持“随机访问”的方式,程序可以直接跳到文件的任意地方来读,写文件。支持只访问文件的部分内容,并且可以向已存在的文件后面追加内容。
构造器:
public RandomAccessFile (File file,String mode)
public RandomAccessFile (String name,String mode)
创建RandomAccessFile类实例需要指定一个mode参数,指定 RandomAccessFile的访问模式:
- r:以只读方式打开(读取的文件必须存在,否则报错)。
- rw:打开以便读取和写入(读取的文件如果不存在就会自己创建)。
- rwd:打开以便读取和写入;同步文件内容更新。
- rws:打开以便读取和写入;同步内容和源数据更新。
参考代码:
public void test(){
RandomAccessFile randomAccessFile_1 = null;
RandomAccessFile randomAccessFile_2 = null;
try {
File srcFile = new File("src\\IU.jpg");
File destFile = new File("src\\IU2.jpg");
randomAccessFile_1 = new RandomAccessFile(srcFile,"r");
randomAccessFile_2 = new RandomAccessFile(destFile,"rw");
byte[] buffer = new byte[1024];
int len;
while((len = randomAccessFile_1.read(buffer)) != -1){
randomAccessFile_2.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (randomAccessFile_1 != null){
randomAccessFile_1.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (randomAccessFile_2 != null){
randomAccessFile_2.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
//指定位置插入元素
public void test2() throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile("test.txt","rw");
randomAccessFile.seek(3);//将指针调到角标为3的位置上
randomAccessFile.write("UVW".getBytes());
randomAccessFile.close();
}
JAVA NIO.2 中的Path 、Paths 、Files
NIO 与原来的IO有相同的作用吧和目的,但是使用的方式完全不同,NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。
JAVA API中提供了两套NIO :一套是针对标准输入输出的NIO;另一套是网络编程NIO。
java.nio.channels.Channel
- FileChannel:处理本地文件;
- SocketChannel:TCP网络编程的客户端Channel;
- ServerSocketChannel:TCP网络编程的服务器端Channel;
- DatagramChannel:UDP网络编程中的发送端和接收端的Channel。
Path
早期JAVA只提供了一个File类来访问文件系统,但File类功能有限,所提供的方法性能也不高,而且,大多方法在错误时并不提供异常信息,为弥补此种不足,我们引入Path接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。
Path可以看成是File类的升级版本,实际引用的资源也可以不存在。
~~未完待续 ~