Java IO

在整个java.io包中最重要的就是5个类和1个接口,5个类指的是File、OutputStream、InputStream、Writer、Reader;1个接口指的是Serializable。

1.操作文件的类-File类(文件本身)

在整个io包中,唯一与文件本身有关的类就是File类。
使用File类可以进行创建或删除文件等常用操作。
要想使用File类,则必须向File类的构造方法中传递一个文件路径。
构造方法:public File(String pathname)

File类中的主要方法和常量
这里写图片描述

(1)创建一个新文件
public boolean createNewFile() throws IOException
File类的实例化对象完成之后,就可以使用createNewFile()创建一个新文件,但是此方法使用了throws关键字声明,所以在使用中,必须使用try…catch进行异常的处理。
注:windows中使用反斜杠表示目录的分隔符“\”
Linux中使用正斜杠表示目录的分隔符“/”。
在操作文件时一定要使用File.separator表示分隔符。

(2)删除一个指定的文件
File类中也支持文件的操作,如果要删除一个文件,则可以使用File类中的delete()方法。
判断一个文件是否存在可以直接使用File类提供的exists()方法,此方法返回boolean类型。

(3)创建一个文件夹
使用File类创建一个文件夹,直接使用mkdir()方法就可以完成。

(4)列出指定目录的全部文件
public String[] list():列出全部名称,返回一个字符串数组;
public File[] listFiles():列出完整的路径,返回一个File对象数组。
使用listFiles()方法列出目录中的内容更加方便。

(5)判断一个给定的路径是否是目录
直接使用isDirectory()方法判断给定的一个路径是否是目录。

2.RondomAccessFile类(文件内容)

File类只是针对文件本身进行操作,如果要对文件内容进行操作,则可以使用RandomAccessFile类,此类属于随机读取类,可以随机地读取一个文件中指定位置的数据。

常用操作方法:
这里写图片描述

注:如果使用rw方式声明RandomAccessFile类时,要写入的文件不存在,系统将自动进行创建。

读取时直接使用r的模式即可,以只读的方式打开文件。
读取时所有的字符串只能按照byte数组的方式读取出来,而且所有的长度是8位。

随机读写流可以实现对文件内容的操作,但是却过于复杂,所以一般情况下操作文件内容往往会使用字节或字符流。

3.字节流与字符流基本操作

在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据时要使用输入流读取数据,而当程序需要将一些数据保存起来时,就要使用输出流。
在java.io包中流的基本操作主要有字节流、字符流两大类,两类都有输入和输出操作。在字节流中输出数据主要使OutputStream类完成,输入使用的是InputStream类。在字符流中输出主要是使用Writer类完成,输入主要是使用Reader类完成。

其中主要操作流程:
①使用File类打开一个文件;
②通过字节流或字符流的子类指定输出的位置;
③进行读/写操作;
④关闭输入/输出。
使用File类操作的时候一定要有路径的问题,注意分隔符。
以上4个操作类都是抽象类,IO操作属于资源操作,对于资源操作,操作的最后必须关闭,否则就有可能出现未知的错误。

(1)字节流
字节流主要是操作byte类型数据,以byte数组为准,主要操作类是OutputStream、InputStream。
1)字节输出流:OutputStream
OutputStream是整个IO包中字节输出流的最大父类,定义如下:

public abstract class OutputStream extends Object implements Clostable,Flushable

此类是一个抽象类,如果要想使用此类的话,则首先必须通过子类实例化对象,如果要操作的是一个文件,则可以使用FileOutputStream。通过向上转型之后,可以为OutputStream实例化。
Cloneseable表示可以关闭的操作,因为程序运行到最后肯定要关闭。
Flushable表示刷新,清空内存中的数据。
常用方法:

要想使用以上方法,必须使用子类实例化,此时使用FileOutputStream子类,此类的构造方法是:

public FileOutputStream(File file) throws FileNotFoundException

可以直接将一个字符串变为byte数组,然后将byte数组直接写入到文件中,当然也可以通过循环把每一个字节一个个地写入到文件之中。

2)追加新内容
以上的所有操作,如果重新执行程序,肯定会覆盖文件中的已有内容,此时FileOutputStream类的另外一个构造方法进行实例化,这样在写入的时候就表示向文件中追加内容,此构造方法定义:

pubic FileOutputStream(File file,boolean append) throws FileNotFoundException

在构造方法中,如果将append的值设置为true,则表示在文件的末尾追加内容。

3)字节输入流InputStream
可以通过InputStream从文件中把内容读取进来,其定义是:

public abstract class InputStream extends Object implements Closeable

与OutputStream类一样,InputStream本身也是一个抽象类,必须依靠其子类,如果现在从文件中读取,子类肯定是FileInputStream。
其方法定义为public FileInoutStream(File file) throws FileNotFoundException

常用方法:
这里写图片描述
如果要想知道文件大小,直接使用File类即可。

public long length()
byte b[]=new byte[(int)f.length]

如果不知道要输入的内容有多大,则只能通过判断是否读到文件末尾的方式来读取文件。

(2)字符流
在程序中一个字符等于两个字节,Java提供了Reader和Writer两个专门操作字符流的类。
1)字符输出流Writer
Writer本身是一个字符流的输出类,定义如下:
public abstract class Writer extends Object implements Appendable,Closeable,Flushable
此类本身也是一个抽象类,如果要使用此类,则肯定使用其子类,此时如果想文件中写入内容,应该使用FileWriter的子类。
FileWriter的构造方法:public FileWriter(File file) throws IOException

常用方法:
这里写图片描述

字符流的操作比字节流操作好在一点就是可以直接输出字符串,不用再像之前那样进行转换操作了。

2)使用FileWriter追加文件的内容
可以使用FileWriter类的另一个构造方法进行追加:

public FileWriter(File file,boolean append)throws IOException

3)字符输入流Reader
Reader是使用字符的方式从文件中取出数据。
其定义如下:

public abstract class Reader extends Object implements Readable,Closeable

Reader本身也是抽象类,如果现在要从文件中读取内容,则可以直接使用FileReader子类。
FileReader的构造方法定义:

public FileReader(File file) throws FileNotFoundException

常用方法:
这里写图片描述

(3)字节流和字符流的区别
字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的。
这里写图片描述

字符流操作时使用到了缓冲区,而在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果程序没有关闭,则缓冲区中的内容是无法输出的。

什么是缓冲区?
缓冲区可以简单地理解为一段内存区域。
某些情况下,如果一个程序频繁地操作一个资源(如文件或数据库),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域之中,以后直接从此区域中读取数据即可,因为读取内存速度会比较快,这样可以提升程序的性能。
在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所有使用了缓冲区暂存数据。

如果想在不关闭时也可以将字符流的内容全部输出,则可以使用Writer类中的flush()方法完成,此方法可以强制性清空缓冲区中的内容。

关于使用字符流好还是字符流好?
推荐使用字节流。
所有的文件在硬盘或在传输时都说以字节方式进行的,包括图片等都是按字节的方式存储的,而字符是只有在内存中才会形成,所有在开发中,字节流使用更广泛。

4.转换流-OutputStreamWriter类与InputStreamReader类

在整个IO包实际上分为字节流和字符流,但是除了这两个流之外,还存在一组字节流-字符流的转换类。
OutputStreamWriter:是Writer的子类,将输出的字符流变为字节流,即将一个字符流的输出对象变为字节流的输出对象。
InputStreamReader:是Reader的子类,将输入的字节流变为字符流,即将一个字节流的输入对象变为字符流的输入对象。

如果以文件操作为例,则在内存中的字符数据需要通过OutputSteamWriter变为字节流才能保存在文件之中,读取的时候需要将读入的字节流通过InputStreamReader变为字符流。
这里写图片描述

不管如何操作,最终全部是以字节的形式保存在文件中。
OutputStreamWriter的构造方法:

public OutputStreamWriter(OutputStream out)

FileOutStream是OutputStream的直接子类,FileInStream是InputStream的直接子类,但是在字符流中文件的两个操作类却有一些特殊,FileWriter并不直接是Writer的子类,而是OutputStream的子类,而FileReader也不直接是Reader的子类,而是InputStream的子类,两个子类中间都需要进行转换的操作。
基于如上可以发现,不管是使用字节流还是字符流实际上最终都是以字节的形式操作输入/输出流的。

5.内存操作流

前面的内容输入和输出都是从文件中来的,当然也可以将输入和输出的位置设置到内存上,此时要使用ByteArrayInputStream、ByteArrayOutputStream来完成内存的输入和输出功能。

ByteArrayInputStream主要完成将内容写入到内存中;ByteArrayOutputStream主要将内存的内容进行输出。
这里写图片描述
注:内存操作流的操作对象一定是以内存为准的。
内存操作流一般在生成一些临时信息时才会使用,如果将这些临时信息保存在文件中,则代码执行完后肯定还要删除这个临时文件会比较麻烦,这时使用内存操作流是最合适的。

6.管道流(线程通信流)

管道流的主要作用是可以进行两个线程间的通讯,分为管道输出流(PipeOutputStream)、管道输入流(PipedInputStream),如果要想进行管道输出,则必须把输出流连在输入流上,在PipedOutputStream类上有如下的一个方法用于连接管道:

public void connect(PipedInputStream snk) throws IOException

这里写图片描述

7.打印流

在整个IO包中,打印流是输出信息最方便的类,主要包含字节打印流(PrintStream)和字符打印流(PrintWriter)。
打印流提供了非常方便的打印功能,可以打印任何的数据类型,如小数、整数、字符串等。
PrinfStream类的常用方法:
这里写图片描述
在这个类中定义了很多的print()或println()方法,System.out.println(),此方法可以打印任何的数据类型。

在PrintStream中定义的构造方法中可以清楚的发现有一个构造方法可以直接结算OutputStream类的实例,这是因为与OutputStream相比起来,PrintStream可以更加方便的输出数据,这就好比将OutputStream类重新包装了与喜爱,使之输出更加方便。
这里写图片描述

在JDK1.5之后,Java又对PrintStream类进行了扩充,增加了格式化的输出方式,直接使用printf()方法就可以完成操作,但是在进行格式化输出的时候需要知道其输出的数据类型。
这里写图片描述

8.System类对IO的支持(★★★)

System类对IO给予了一定的支持。
这里写图片描述
(1)System.out
System.out是PrintStream的对象,在PrintStream中定义了一些了的print()和println()方法,所以之前使用的System.out.println()或System.out.print()语句调用的实际上就是PrintStream类的方法。
使用System,out输出的时候就是将输出的位置定义在了显示器之中。
OutputStream的哪个子类为其实例化,就具备了向哪里输出的能力。FileoutputStream是定位在文件里,而System,out是定位在屏幕上。
PrintStream是OutputStream的子类。

(2)System.err
System.err表示的是错误信息输出,如果程序出现错误,则可以直接使用System,err进行输出。

System,out和System,in的区别
System.out和System.err的输出结果是一样的,两者只能从概念上理解。
System.out和System.err都是PrintStream的实例化对象,而且通过实例代码可以发现两者都可以输出错误信息,但是一般来讲System.out是将信息显示给用户看,是正常的信息显示,而System.err的信息正好相反是不希望用户看到的,会直接在后台打印,专门显示错误的。
一般来讲,如果要想输出错误信息的时候最好不要使用System,out而是直接使用System,in,这一点只能从其概念上划分。
这里写图片描述

(3)System.in
System.in实际上是一个键盘的输入流,其本身是InputStream类型的对象。那么,此时可以利用System,in完成从键盘读取数据的功能。

如果输入的是英文字母,是没有任何的问题,而如果输入的是中文,则会产生乱码,因为数据是一个个字节的方式读进来的,一个汉字是分两次读取的,所以造成了乱码。
最好的输入放是将全部输入的数据暂时放到一块内存之中,之后一次性的从内存中读取出数据,这样所有数据只读了一次,则不会造成乱码,而且也不会受长度的限制。
这里写图片描述

(4)输入/输出重定向
System类提供的重定向方法:
这里写图片描述
①为System.out输出重定向

System.setOut(new PrintStream(new FileOutputStream(“d:”+File.separator+”red.tex”)));
System.out.println(“hello world”);

②为System.err输出重定向
虽然在System类中提供了setErr()这个错误输出的重定向方法,但是一般情况下,请不要使用这个方法修改System.err的重定向,因为从概念上讲System,err的错误信息是不希望用户看到的。

注:setOut()方法只负责System.out的输出重定向,而setErr()方法只负责System.err的输出重定向,两者不可混用。
③为System.in的输入重定向

System.setIn(new FileOutputStream(“d:”+File.separator+”red.tex”));
InputStream input=System.in;
byte b[]=new byte[1024];
int len=input.read(b);
Sytem,out.println(“输入内容:”+new String(b,0,len));
input.close();

注:对于System.in来讲主要是针对键盘的输入,如果将其修改,肯定要损失其功能,故在开发中不建议修改System.in的操作。
System.in读取的时候会出现中文乱码的问题,则可以通过BufferReader完成读取功能。

9.BufferedReader类

BufferedReader类用于从缓冲区中读取内容,所有的输入字节数据都将放在缓冲区中。
Buffer:表示缓冲区的,缓冲区中的内容可以更改,可以提高效率。
如果要想接收任意长度的数据,而且避免乱码产生,就可以使用BufferedReader。
这里写图片描述
BufferedReader中定义的构造方法只能接收字符输入流的实例,所以必须使用字符输入流和字节输入流的转换类InputStreamReader将字节输入流System.in变为字符流。
这里写图片描述
(1)键盘输入数据的标准格式
将System,in变为字符流放入到BufferedReader后,可以通过readLine()方法等待用户输入信息。

BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
String str=null;
System.out.print(“请输入内容:”);
try{
    str=buf.readLine(); //读取输入内容
}catch(IOException e){
    e.printStackTrace();
}
System.out.println(“输入的内容为:”+str);

可以发现,程序非但没有了长度的限制,也可以正确的接收正文了。

(2)相关操作实例
①加法操作
从键盘接收过来的内容全部是采用字符串的形式存放的,所以直接将字符串通过包装类Integer将字符串变为基本数据类型。
②菜单显示
菜单类调用操作类,而具体的实际操作由操作类完成。

注:在开发中一定要完成功能,之后再考虑类的设计。
主方法就是一个客户端,代码越少越好。

10.Scaner类(★★★)(输入数据类)

(1)简介
在JDK1.5之后Java提供了专门的输入数据类,此类不只可以完成输入数据操作,也可以方便地对输入数据进行验证,此类存放在java.util包中。
常用方法如下:
这里写图片描述
此类不在java.io包中,而在java.util包中,所以此类是一个工具类。
Scanner类中提供了一个可以接收InputStream类型的构造方法,这就表示只要是字节输入流的子类都可以为Scanner类实例化,以进行方便的读取。

(2)使用Scanner类输入数据
①实现基本的数据输入
最简单的数据输入直接使用Scanner类的next()方法即可。

import java.util.Scanner;
public class ScannerDemo01{
public static void main(String []args){
    Scanner scan=new Scanner(System.in);
    System.out.print(“请输入数据:”);
    String str=scan.next();
    System.out.println(“输入的数据为:”+str);
}
}

以上的程序如果输入了带空格的内容,则只能取出空格之前的数据。要想避免这种情况,我们可以试着把分隔符修改为”\n(空格)”

import java.util.Scanner;
public class ScannerDemo02{
public static void main(String []args){
    Scanner scan=new Scanner(System.in);
    scan.useDelinmiter(“\n”);
    System.out.print(“请输入数据:”);
    String str=scan.next();
    System.out.println(“输入的数据为:”+str);
}
}

以上完成了字符串内容的输入,如果要输入int或float类型的数据,在Scanner中也有支持,但是在输入之前最好先使用hasNextXxx()方法进行验证。

import java.util.Scanner;
public class ScannerDemo02{
public static void main(String []args){
    Scanner scan=new Scanner(System.in);
    int i=0;
    float f=0.0f;
    System.out.print(“请输入整数:”);
    if(scan.hasNextInt()){
        i=scan.nextInt();
        System.out.println(“整数数据是:”+i);
    }else{
        System.out.println(“输入的不是整数”);
    }
    System.out.print(“请输入小数:”);
    if(scan.hasNextFloat()){
        f=scan.nextFloat();
        System.out.println(“小数数据是:”+f);
    }else{
        System.out.println(“输入的不是小数”);
    }
}
}

②实现日期格式的数据输入
在Scanner类中没有提供专门的日期格式输入操作,所以要想得到一个日期类型的数据,则必须自己编写正则验证,并手工转换。
③从文件中得到数据
如果要从文件中取得数据,则直接将File类的实例传入到Scanner的构造方法即可。

11.数据操作流

在IO包中提供了两个与平台无关的数据操作流,分别为数据输出流(DataOutputStream)和数据输入流(DataInputStream)。通常数据输出流会按照一定的格式将数据输出,再通过数据输入流按照一定的格式将数据读入,这样可以方便地对数据进行处理。
(1)DataOutputStream类
DataOutputStream是OutputStream的子类,此类定义如下:

public class DataOutputStream extends FilterOutputStream implements DataOutput

此类继承自FilterOutputStream类(FilterOutputStream是OutputStream的子类),同时实现了DataOutput接口,在DataOutput接口定义了一系列的写入各种数据的方法。
注:只有在对象序列化的时候才会用到DataOutput接口。

(2)DataInputStream类
DataInputStream是InputStream的子类,专门负责读取使用DataOutputStream输出的数据,此类的定义如下:

public class DataInputStream extends FilterInputStream implements DataInt

此类继承自FilterInputStream类(FilterInputStream是InputStream的子类),同时实现DataInput接口,在DataInput接口中定义了一系列读入各种数据的方法。
注:只有在对象序列化的时候才会用到DataInput接口。

12.合并流

合并流的主要功能是将两个文件的内容合并成一个文件。
如果要实现合并流,则必须使用SequenceInputStream类。
此类的常用方法:
这里写图片描述

13.压缩流

(1)ZIP压缩输入/输出流简介
ZIP是一种较为常见的压缩格式,在Java中要想实现ZIP的压缩需要导入java.util.zip包,可以使用此包中的ZipFile、ZipOutputStream、ZipInputStream和ZipEntry这几个类完成。

JAR及GZIP文件格式的压缩输入、输出流
在Java IO中,不仅可以实现ZIP压缩格式的输入、输出,也可以实现JAR及GZIP文件格式的压缩:
★JAR压缩的文件类保存在java,util.jar包中,常用的类有如下几个:

●JAR压缩输出流:JarOutputStream
●JAR压缩输入流:JarInputStream
●JAR文件:JARFile
●JAR实体:JAREntry

★GZIP是Unix系统的压缩文件,在Linux中经常会用到*.gz的文件,就是GZIP格式,GZIP压缩的支持类保存在java.util.zip包中,常用的类有如下两个:

●GZIP压缩输出流:GZIPOutputStream
●GZIP压缩输入流:GZIPInputStream

在每一个压缩文件中都会存在多个子文件,那么这每一个的子文件在Java中就使用ZipEntry表示。
ZipEntry类的常用方法:
这里写图片描述
在实例化ZipEntry的时候,要设置名称,此名称实际上就是压缩文件中每一个元素的名称。

正常情况下在IO操作中,所有的类库都是在io包中。
压缩的输入/输出流也属于InputStream或OutputStream的子类,但是却没有定义在java.io包中,而是以一种工具类的形式提供的,在操作时还需要使用java.io包的支持。

(2)ZipOutputStream类
如果要完成一个文件或文件夹的压缩,则要使用ZipOutputStream类。ZipOutputStream是OutputStream的子类。
常用的操作方法:
这里写图片描述

(3)ZipFile类(一个专门表示压缩文件的类)
在Java中,每一个压缩文件都可以使用ZipFile表示,还可以使用ZipFile根据压缩后的文件名称找到每一个压缩文件中的ZipEntry并将其进行解压缩操作。
这里写图片描述

(4)ZipInputStream类
ZipInputStream是InputStream的子类,通过此类可以方便地读取ZIP格式的压缩文件。
使用ZipInputStream可以像ZipFile一样取得ZIP压缩文件中的每一个ZipEntry。

14.回退流

在Java IO中所有的数据都是采用顺序的读取方式,即对于一个输入流来讲都是采用从头到尾顺序读取的。如果在输入流中某个不需要的内容被读取进来,则只能通过程序将这些不需要的内容处理掉,为了解决这样的读取问题,在Java中提供了一种回退流(PushbackInputStream、PushbackReader),可以把读取进来的某些数据重新退回到输入流的缓冲区之中。
回退操作机制:
这里写图片描述

回退操作同样分为字节流和字符流。从图上可以看出通过unread()方法将内容重新送回到输入流的缓冲区中。
PushbackInputStream类的常用方法:
这里写图片描述
对于回退操作来说,提供了三个unread()方法,这三个操作方法与InputStream类中的read()方法是一一对应的,所以回退完全是针对于输入流进行操作的。

15.字符编码

在Java程序的开发中最常见的是ISO8859-1、GBK/GB2312、unicode、UTF编码。

ISO8859-1:属于单字节编码,最多只能表示0~255的字符范围,主要在英文上应用。

GBK/GB2312:中文的国际编码,专门用来表示汉字,是双字节编码。如果在此编码中出现中文,则使用ISO8859-1编码,GBK可以表示简体中文和繁体中文,而GB2312只能表示简体中文,GBK兼容2312。

unicode:Java中使用此编码方式,是最标准的一种编码,使用十六进制表示编码。但此编码不兼容ISO8859-1编码。

UTF:由于unicode不支持ISO8859-1编码,而且容易占用更多的空间,而且对于英文字母也需要使用两个字节编码,这样使用unicode不便于传输和存储,因此产生了UTF编码。UTF编码兼容了ISO8859-1编码,同时也可以用来表示所有的语言字符,不过UTF编码是不定长编码,每一个字符的长度为1-6个字节不等。一般在中文网页中使用此编码,可以节省空间。

如果没有处理好编码的事情,则肯定在程序中出现乱码,如果要避免产生乱码,则程序的编码与本地的默认编码保持一致即可,而如果要知道本地的默认编码,则可以使用System类即可。

乱码的产生就一个原因:输出内容的编码与接收内容的编码不一致。

16.对象序列化(★★★★★)

(1)基本简介
对象序列化就是把一个对象变为二进制的数据的一种方法。通过对象序列化可以方便地实现对象的传输或存储。
如果一个类的对象想被序列化,则对象所在的类必须实现java.io.Serializable接口。此接口定义:public interface Serializable()
此接口属于一个标识接口,表示具备了被序列化的能力。

要完成对象的输入或输出,还必须依靠对象输出流(ObjectOutputStream)和对象输入流(ObjectInputStream)。
使用对象输出流输出序列化对象的步骤有时也称为序列化,而使用对象输入流读入对象的过程有时也称为反序列化。
这里写图片描述

(2)对象输出流ObjectOutputStream
一个对象如果要进行输出,则必须使用ObjectOutputStream类,此类的定义:
public class ObjectOutputStream extends OutputStream implements ObjectOutput,ObjectStreamConstants
ObjectOutputStream类属于OutputStream的子类,其常用方法:
这里写图片描述
此类的使用形式与PrintStream非常的相似,在实例化时也需要传入一个OutputStream的子类对象,之后根据传入的OutputStream子类的对象不同,输出的位置也不同。

一个对象被序列化后,到底哪些内容被保存了下来,是属性还是方法?
只有属性被序列化。每个对象都具有相同的方法,但是每个对象的属性不一定相同,也就是说,对象保存的只有属性信息,那么在序列化操作时也同样是这个道理,只有属性被序列化。

(3)对象输入流ObjectInputStream
使用ObjectInputStream可以直接把被序列化好的对象反序列化。
ObjectInputStream的定义如下:

public class ObjectInputStream extends InputStream implements ObjectInput ObjectStreamConstants

常用方法:
这里写图片描述
此类也是InputStream的子类,与PrintStream类的使用类似,此类同样需要接收InputStream类的实例才可以实例化。

如果用户想根据自己的需要选择被序列化的属性,则可以使用另外一种序列化接口-Externalizable接口。

(4)Externalizable接口
被Serializable接口声明的类其对象的内容都将被序列化,如果现在用户希望可以自己指定序列化的内容,则可以让一个类实现Externalizable接口。此接口定义如下:

public interface Externalizable extends Serializable{
    public void writeExternal(ObjectOutput out) throws IOException
    public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException;
}

Externalizable接口是Serializable接口的子接口,在此接口中定义了两个方法,这两个方法如下:

这两个方法的参数类型是ObjectOutput和ObjectInput,两个接口的定义如下:
●ObjectOutput接口定义:

public interface ObjectOutput extends DataOutput

●ObjectInput接口定义:

public interface ObjectInput extends DataInput

可以发现这两个接口分别继承DataOutput和DataInput,这样在这两个方法中就是可以像DataOutputStream和DataInputStream那样直接输出和读取各种类型的数据。

如果一个类要使用Externalizable实现序列化时,在此类时中必须存在一个无参构造方法,因为在反序列化时会默认调用无参构造实例化对象,如果没有此无参构造,则运行时将会出现异常,这一点实现机制与Serializable接口是不同的。
这里写图片描述

在开发中使用Serializable接口是最多的,而Externalizable接口基本上是不会出现的。

(5)transient关键字
Serializable接口实现的操作实际上是将一个对象中的全部属性进行序列化,当然也可以使用Externalizable接口以实现部分属性的序列化,但这样操作比较麻烦。
当使用Serializable接口实现反序列化操作时,如果一个对象中的某个属性不希望被序列化,则可以使用transient关键字进行声明。

(6)序列化一组对象
对象输出时只提供了一个对象的输出操作(writeObject(Object obj)),并没有提供多个对象的输出,所以如果现在要同时序列化多个对象,就可以使用对象数组进行操作。因为数组属于引用数组类型,所以可以直接使用Object类型进行接收。
这里写图片描述

总结:

①对象序列化的作用:对象序列化并不一定都向文件中保存,也有可能面向于其他的输入或输出。
②被序列化对象的类必须实现Serializable接口,如果某个属性不希望被保存下来,则可以使用transient关键字声明。
③ObjectOutputStream序列化对象,ObjectInputStream反序列化对象。
④Externalizable接口的作用:开发人员手工实现序列化的操作。
⑤使用序列化保存一组对象的时候要使用对象数组的形式操作。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java IO(Input/Output)是Java编程语言中用于处理输入和输出的基础库。它提供了一种方便的方式来读取和写入数据,从而与外部世界进行交互。 Java IO库包含多个类和接口,用于在不同的场景下处理输入和输出。这些类和接口可以分为字节流(Byte Stream)和字符流(Character Stream)两种类型。 字节流主要用于处理二进制数据,而字符流则用于处理文本数据。 常用的字节流类有: - InputStream和OutputStream:用于读取和写入字节数据。 - FileInputStream和FileOutputStream:用于读取和写入文件。 - BufferedInputStream和BufferedOutputStream:提供了缓冲功能,以提高读写的效率。 常用的字符流类有: - Reader和Writer:用于读取和写入字符数据。 - FileReader和FileWriter:用于读取和写入文本文件。 - BufferedReader和BufferedWriter:提供了缓冲功能,以提高读写的效率。 除了字节流和字符流之外,Java IO还提供了一些其他的类和接口,用于处理特定类型的输入和输出。例如: - DataInputStream和DataOutputStream:用于读写基本数据类型及字符串。 - ObjectInputStream和ObjectOutputStream:用于读写Java对象。 - PrintWriter:用于格式化输出。 在使用Java IO时,通常需要使用try-catch语句来捕获可能抛出的异常,例如IOException。 总结起来,Java IOJava编程语言中用于处理输入和输出的基础库,提供了字节流和字符流两种类型的处理方式,并且还包含其他一些类和接口,用于处理特定类型的输入和输出

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值