欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java基础【三】IO流-序列化与反序列化入门

程序员文章站 2024-03-07 15:45:21
...

IO流的作用:

在变量,数组和对象中储存的数据都是暂时存在的,程序结束后他们就是丢失

。为了能够永久的保存程序创建的数据,需要将其保存在磁盘文件中,这样就可以在其它程序中使用他们了的.java的IO技术可以将数据保存到本地文件,二进制文件甚至是ZIP压缩文件中,以达到永久性保存数据的要求。掌握IO处理技术能够提高对数据的处理能力

流概述

流是一组有序的数据序列,根据操作的类型可以将流分为两种 - 输入流I和输出流O.注意:输入输出是以程序为中心

输入流是指从指定的文件对象中读取,接受数据;输入到我的程序。

输出流是从我的程序中将数据对象输出,写入等。

 

 

输入/输出流

InputStream类是字节输入流的抽象类,是所有字节输入流的父类。该类中所有方法遇到错误时都会引发IOException异常。以下是InputStream类的具体结构(出自API 1.8):

Java基础【三】IO流-序列化与反序列化入门

的InputStream类中的方法:

INT

可用()

返回从该输入流中可以读取(或跳过)的字节数的估计值,而不会被下一次调用此输入流的方法阻塞。

空虚

关闭()

关闭此输入流并释放与流相关联的任何系统资源。

空虚

mark(int readlimit)

标记此输入流中的当前位置。

布尔

markSupported()

测试这个输入流是否支持标记和重置方法。

抽象的int

()

从输入流读取数据的下一个字节。

INT

(byte [] b)

从输入流读取一些字节数,并将它们存储到缓冲区b。

INT

read(byte [] b,int off,int len)

从输入流读取最多len字节的数据到一个字节数组。

空虚

重置()

将此流重新定位到上次在此输入流上调用标记方法时的位置。

跳过(长n)

跳过并丢弃来自此输入流的n字节数据。

//并不是所有的子类都支持这些方法,如跳过(),标记(),复位()等方法只对某些子类有用

 

 

输出流

为OutputStream类是字节输出流的抽象类,此抽象类是所有输出流的所有类的超类。

Java基础【三】IO流-序列化与反序列化入门

 

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(String pathname)

通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。

File(String parent, String child)

从父路径名字符串和子路径名字符串创建新的 File实例。

File(URI uri)

通过将给定的 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

canExecute()

测试应用程序是否可以执行此抽象路径名表示的文件。

boolean

canRead()

测试应用程序是否可以读取由此抽象路径名表示的文件。

boolean

canWrite()

测试应用程序是否可以修改由此抽象路径名表示的文件。

int

compareTo(File pathname)

比较两个抽象的路径名字典。

boolean

createNewFile()

当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。

static File

createTempFile(String prefix, String suffix)

在默认临时文件目录中创建一个空文件,使用给定的前缀和后缀生成其名称。

static File

createTempFile(String prefix, String suffix, File directory)

在指定的目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。

boolean

delete()

删除由此抽象路径名表示的文件或目录。

void

deleteOnExit()

请求在虚拟机终止时删除由此抽象路径名表示的文件或目录。

boolean

equals(Object obj)

测试此抽象路径名与给定对象的相等性。

boolean

exists()

测试此抽象路径名表示的文件或目录是否存在。

File

getAbsoluteFile()

返回此抽象路径名的绝对形式。

String

getAbsolutePath()

返回此抽象路径名的绝对路径名字符串。

File

getCanonicalFile()

返回此抽象路径名的规范形式。

String

getCanonicalPath()

返回此抽象路径名的规范路径名字符串。

long

getFreeSpace()

返回分区未分配的字节数 named此抽象路径名。

String

getName()

返回由此抽象路径名表示的文件或目录的名称。

String

getParent()

返回此抽象路径名的父 null的路径名字符串,如果此路径名未命名为父目录,则返回null。

File

getParentFile()

返回此抽象路径名的父,或抽象路径名 null如果此路径名没有指定父目录。

String

getPath()

将此抽象路径名转换为路径名字符串。

long

getTotalSpace()

通过此抽象路径名返回分区 named的大小。

long

getUsableSpace()

返回上的分区提供给该虚拟机的字节数 named此抽象路径名。

int

hashCode()

计算此抽象路径名的哈希码。

boolean

isAbsolute()

测试这个抽象路径名是否是绝对的。

boolean

isDirectory()

测试此抽象路径名表示的文件是否为目录。

boolean

isFile()

测试此抽象路径名表示的文件是否为普通文件。

boolean

isHidden()

测试此抽象路径名命名的文件是否为隐藏文件。

long

lastModified()

返回此抽象路径名表示的文件上次修改的时间。

long

length()

返回由此抽象路径名表示的文件的长度。

String[]

list()

返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。

String[]

list(FilenameFilter filter)

返回一个字符串数组,命名由此抽象路径名表示的目录中满足指定过滤器的文件和目录。

File[]

listFiles()

返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件。

File[]

listFiles(FileFilter filter)

返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。

File[]

listFiles(FilenameFilter filter)

返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。

static File[]

listRoots()

列出可用的文件系统根。

boolean

mkdir()

创建由此抽象路径名命名的目录。

boolean

mkdirs()

创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。

boolean

renameTo(File dest)

重命名由此抽象路径名表示的文件。

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

setReadOnly()

标记由此抽象路径名命名的文件或目录,以便只允许读取操作。

boolean

setWritable(boolean writable)

一种方便的方法来设置所有者对此抽象路径名的写入权限。

boolean

setWritable(boolean writable, boolean ownerOnly)

设置此抽象路径名的所有者或每个人的写入权限。

Path

toPath()

返回从此抽象路径构造的java.nio.file.Path对象。

String

toString()

返回此抽象路径名的路径名字符串。

URI

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):

Java基础【三】IO流-序列化与反序列化入门

Writer类是字符输出流的抽象类,所有字符输出类的实现都是他的子类。Writer类的层次结构:

 

Java基础【三】IO流-序列化与反序列化入门

 

使用字符流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家族

下一篇: