Java基础【三】IO流-序列化与反序列化入门
IO流的作用:
在变量,数组和对象中储存的数据都是暂时存在的,程序结束后他们就是丢失
。为了能够永久的保存程序创建的数据,需要将其保存在磁盘文件中,这样就可以在其它程序中使用他们了的.java的IO技术可以将数据保存到本地文件,二进制文件甚至是ZIP压缩文件中,以达到永久性保存数据的要求。掌握IO处理技术能够提高对数据的处理能力
流概述
流是一组有序的数据序列,根据操作的类型可以将流分为两种 - 输入流I和输出流O.注意:输入输出是以程序为中心:
输入流是指从指定的文件对象中读取,接受数据;输入到我的程序。
输出流是从我的程序中将数据对象输出,写入等。
输入/输出流
InputStream类是字节输入流的抽象类,是所有字节输入流的父类。该类中所有方法遇到错误时都会引发IOException异常。以下是InputStream类的具体结构(出自API 1.8):
的InputStream类中的方法:
INT |
可用() 返回从该输入流中可以读取(或跳过)的字节数的估计值,而不会被下一次调用此输入流的方法阻塞。 |
空虚 |
关闭() 关闭此输入流并释放与流相关联的任何系统资源。 |
空虚 |
mark(int readlimit) 标记此输入流中的当前位置。 |
布尔 |
测试这个输入流是否支持标记和重置方法。 |
抽象的int |
读() 从输入流读取数据的下一个字节。 |
INT |
读(byte [] b) 从输入流读取一些字节数,并将它们存储到缓冲区b。 |
INT |
read(byte [] b,int off,int len) 从输入流读取最多len字节的数据到一个字节数组。 |
空虚 |
重置() 将此流重新定位到上次在此输入流上调用标记方法时的位置。 |
长 |
跳过(长n) 跳过并丢弃来自此输入流的n字节数据。 |
//并不是所有的子类都支持这些方法,如跳过(),标记(),复位()等方法只对某些子类有用
输出流
为OutputStream类是字节输出流的抽象类,此抽象类是所有输出流的所有类的超类。
OutputStream所有的方法返回值都是void,在遇到错误时会引发IOException异常。
OutputStream类中的方法:
void |
close() 关闭此输出流并释放与此流相关联的任何系统资源。 |
void |
flush() 刷新此输出流并强制任何缓冲的输出字节被写出。 |
void |
write(byte[] b) 将 b.length字节从指定的字节数组写入此输出流。 |
void |
write(byte[] b, int off, int len) 从指定的字节数组写入 len个字节,从偏移 off开始输出到此输出流。 |
abstract void |
write(int b) 将指定的字节写入此输出流。 |
File类
File类是java.io包中唯一代表磁盘文件本身的对象。File类定义了一些与平台无关的方法来操作文件,可以通过调用File类中的方法,实现文件创建、删除、重命名文件等操作。File类的对象主要用来获取文件本身的一些信息,如在文件所在的目录、文件的长度、文件的读写权限等。数据流可以将数据写入到文件中,文件也是数据流最常用的数据媒体。
文件的基本操作:
File的构造方法:
File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例。 |
通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。 |
File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例。 |
通过将给定的 file: URI转换为抽象路径名来创建新的 File实例。 |
File f=new File("E:\\tes.txt");
try {
if (f.exists()){//判断文件是否存在
f.delete();//文件删除
System.out.println("文件以删除");
}else {
f.createNewFile();//文件创建
System.out.println("创建成功");
}
} catch (IOException e) {
}
File类提供了好多方法可以获取文件本身的信息,带颜色的为常用的
boolean |
测试应用程序是否可以执行此抽象路径名表示的文件。 |
boolean |
canRead() 测试应用程序是否可以读取由此抽象路径名表示的文件。 |
boolean |
canWrite() 测试应用程序是否可以修改由此抽象路径名表示的文件。 |
int |
比较两个抽象的路径名字典。 |
boolean |
当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。 |
static File |
createTempFile(String prefix, String suffix) 在默认临时文件目录中创建一个空文件,使用给定的前缀和后缀生成其名称。 |
static File |
createTempFile(String prefix, String suffix, File directory) 在指定的目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。 |
boolean |
delete() 删除由此抽象路径名表示的文件或目录。 |
void |
请求在虚拟机终止时删除由此抽象路径名表示的文件或目录。 |
boolean |
测试此抽象路径名与给定对象的相等性。 |
boolean |
exists() 测试此抽象路径名表示的文件或目录是否存在。 |
返回此抽象路径名的绝对形式。 |
|
返回此抽象路径名的绝对路径名字符串。 |
|
返回此抽象路径名的规范形式。 |
|
返回此抽象路径名的规范路径名字符串。 |
|
long |
返回分区未分配的字节数 named此抽象路径名。 |
getName() 返回由此抽象路径名表示的文件或目录的名称。 |
|
返回此抽象路径名的父 null的路径名字符串,如果此路径名未命名为父目录,则返回null。 |
|
返回此抽象路径名的父,或抽象路径名 null如果此路径名没有指定父目录。 |
|
getPath() 将此抽象路径名转换为路径名字符串。 |
|
long |
通过此抽象路径名返回分区 named的大小。 |
long |
返回上的分区提供给该虚拟机的字节数 named此抽象路径名。 |
int |
hashCode() 计算此抽象路径名的哈希码。 |
boolean |
测试这个抽象路径名是否是绝对的。 |
boolean |
测试此抽象路径名表示的文件是否为目录。 |
boolean |
isFile() 测试此抽象路径名表示的文件是否为普通文件。 |
boolean |
isHidden() 测试此抽象路径名命名的文件是否为隐藏文件。 |
long |
返回此抽象路径名表示的文件上次修改的时间。 |
long |
length() 返回由此抽象路径名表示的文件的长度。 |
String[] |
list() 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。 |
String[] |
list(FilenameFilter filter) 返回一个字符串数组,命名由此抽象路径名表示的目录中满足指定过滤器的文件和目录。 |
File[] |
返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件。 |
File[] |
listFiles(FileFilter filter) 返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。 |
File[] |
listFiles(FilenameFilter filter) 返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。 |
static File[] |
列出可用的文件系统根。 |
boolean |
mkdir() 创建由此抽象路径名命名的目录。 |
boolean |
mkdirs() 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。 |
boolean |
重命名由此抽象路径名表示的文件。 |
boolean |
setExecutable(boolean executable) 为此抽象路径名设置所有者的执行权限的便利方法。 |
boolean |
setExecutable(boolean executable, boolean ownerOnly) 设置该抽象路径名的所有者或每个人的执行权限。 |
boolean |
setLastModified(long time) 设置由此抽象路径名命名的文件或目录的最后修改时间。 |
boolean |
setReadable(boolean readable) 一种方便的方法来设置所有者对此抽象路径名的读取权限。 |
boolean |
setReadable(boolean readable, boolean ownerOnly) 设置此抽象路径名的所有者或每个人的读取权限。 |
boolean |
标记由此抽象路径名命名的文件或目录,以便只允许读取操作。 |
boolean |
setWritable(boolean writable) 一种方便的方法来设置所有者对此抽象路径名的写入权限。 |
boolean |
setWritable(boolean writable, boolean ownerOnly) 设置此抽象路径名的所有者或每个人的写入权限。 |
toPath() 返回从此抽象路径构造的java.nio.file.Path对象。 |
|
toString() 返回此抽象路径名的路径名字符串。 |
|
toURI() 构造一个表示此抽象路径名的 file: URI。 |
文件的输入、输出流
FileInputStream 与 FileOutputStream 类都是用来操作磁盘文件的。如果用户的文件读取读取需求比较简单,则可以使用FileInputStream,继承InputStream类。 FileInputStream 与 FileOutputStream 类是相互对应的,提供了基本的写入功能。FileOutputStream是FileOutputStream 的子类。
FileInputStream(File file) 通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 |
FileInputStream(FileDescriptor fdObj) 创建 FileInputStream通过使用文件描述符 fdObj ,其表示在文件系统中的现有连接到一个实际的文件。 |
FileInputStream(String name) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。 |
操作步骤如下:
输入流FileInputStream 读取数据
try {
//构建一个文件输入流对象
FileInputStream fis=new FileInputStream("test.txt");
//使用输入流类的方法读取文本的数据
int data;
while ((data=fis.read())!=-1){
System.out.print((char)data);
}
//输出结果是一个字节类型的 a-97 b-98 在输出时进行转换可得到对应的内容
//关闭对象
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
注意: >read()方法返回整数,如果读取的是字符串,会乱码
>流对象使用完需要关闭
输出流FileOutputStream 写入数据
try {
//构建一个文件输出流对象
FileOutputStream fos=new FileOutputStream("test.txt");
//使用输出流类的方法写入文本的数据
String data="使用FileOutputStream的writer()方法写入数据";
//write()要求写入的是字节类型,所以需要将字符串转换成一个数组
byte[] bytes=data.getBytes();// getBytes()返回一个byte数组
fos.write(bytes);
//关闭流-不关闭流的情况下文件为空,流会一直在等待继续写入,所以不会将数据写入到文件
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
注意:
>在创建FileOutputStream类读文件时,如果文件不存在,就会自动创建一个空文件
>如果对象指向的文件路径存在,但是代表的是一个文件夹,会报空指针异常
>默认情况下,FileOutputStream(name,append)-append为假即不拼接,覆盖
手动添加true,在能读取得到的字节末尾添加数据
字符串处理 Reader-Writer
Java中的字符是Unicode编码格式,是双字节的。InputStream是用来处理字节的,并不适合处理字符文本。Java为字符文本输入专门提供了一套单独的类Reader,但Reader类并不是InputStream类的替换者,只是处理字符串是简化了编程。Reader类是字符输入流的抽象类,所有字符输入流的实现都是他的子类。以下是Reader类的具体结构(出自API 1.8):
Writer类是字符输出流的抽象类,所有字符输出类的实现都是他的子类。Writer类的层次结构:
使用字符流BufferedWriter 和 FileWriter 写入本地文件
BufferedWriter 和 FileWriter 都是字符Writer 输出流的子类的子类
以字符流的方式通过缓冲区把数据写入文本文件,提高了写文本的效率。
try {
//创建一个FileWriter对象
FileWriter fw=new FileWriter("test.txt");
//创建一个BufferedWriter对象
BufferedWriter bfw=new BufferedWriter(fw);
String data="使用BufferedWriter的writer()方法写入数据";
//新的一行
bfw.newLine();
//写入
bfw.write(data);
//刷新缓冲区
bfw.flush();
//关闭流-不关闭流的情况下文件为空,流会一直在等待继续写入,所以不会将数据写入到文件
bfw.close();
} catch (IOException e) {
e.printStackTrace();
}
使用字符流BufferedReader 和 FileReader 读取本地文件
BufferedWriter 和 FileWriter 都是字符Reader 输出流的子类的子类
以字符流的方式读取文件,并使用缓冲区,大大提高了写文本的效率。
// 创建一个FileReader对象
FileReader fr= null;
try {
fr = new FileReader("test.txt");
//创建一个BufferedReader对象
BufferedReader bfr=new BufferedReader(fr);
String data;//
while ((data=bfr.readLine())!=null){
System.out.println(data);
}
//关闭
bfr.close();
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
读写二进制文件
常见的文件读写还有一种二进制文件的读写。常用类:DataInputStream-DataOutputStream
try {
FileOutputStream fos=new FileOutputStream("test.txt");
DataOutputStream dos=new DataOutputStream(fos);
dos.write(1);
dos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileInputStream fis=new FileInputStream("test.txt");
DataInputStream dis=new DataInputStream(fis);
System.out.println(dis.read());
dis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
在使用二进制传输音乐,视频等文件时速度快,效率高,实现代码都与上面的一样,而传输文件的只是没有输出,将输出语句改为写入
try {
FileOutputStream fos=new FileOutputStream("testcopy.txt");
DataOutputStream dos=new DataOutputStream(fos);
FileInputStream fis=new FileInputStream("test.txt");
DataInputStream dis=new DataInputStream(fis);
int temp;
while ((temp=dis.read())!=-1){//读取
dos.write(temp);//写入到目标文件
}
dos.close();
dis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
序列化与反序列化
序列化是将对象的状态储存到特定储存介质(文件)中的过程,也就是将对象状态转换为可保持或者可传输格式的过程。使用序列化的意义就是能将的Java对象序列化后,可以将其转换为字节序列,可以保存在磁盘上,也可以在网络上进行传输,同时对象保存的是二进制状态,这样实现了平台无关性,可以在各种系统进行反序列化后得到相同的对象,而无需担心显示异常。
对象需要实现Serializable接口接口类才能被序列化.JDK类库中的包装类,字符串,日期类等都是实现了序列化接口。
序列化
ObjectOutputStream oos=null;
try {
oos=new ObjectOutputStream(new FileOutputStream("ObjectTest.txt"));
//写入对象,示范。在对象类中要实现 Serializable接口
oos.writeObject(new HashMap());
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
反序列化
try {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("ObjectTest.txt"));
//读取出来需要进行强制类型转换,存进去什么类型,读取就是什么类型强转
Map map=(Map)ois.readObject();
ois.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
上一篇: 5、offset家族