黑马程序员--Java基础--IO基本操作

基本IO操作


1. InputStream与OutputStream

1.1. 输入与输出

我们编写的程序除了自身会定义一些数据信息外,经常还会引用外界的数据,或是将自身的数据发送到外界。比如,我们编写的程序想读取一个文本文件,又或者我们想将程序中的某些数据写入到一个文件中。这时我们就要使用输入与输出。

  • 什么是输入:输入是一个从外界进入到程序的方向,通常我们需要“读取”外界的数据时,使用输入。所以输入是用来读取数据的。
  • 什么是输出:输出是一个从程序发送到外界的方向,通常我们需要”写出”数据到外界时,使用输出。所以输出是用来写出数据的。

1.2. 节点流与处理流

  • 按照流是否直接与特定的地方 (如磁盘、内存、设备等) 相连,分为节点流和处理流两类。

    ①节点流:可以从或向一个特定的地方(节点)读写数据。

    ②处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。

  • 处理流的构造方法总是要带一个其他的流对象做参数。
  • 一个流对象经过其他流的多次包装,称为流的链接。

1.3. InputStream与OutputStream常用方法

InputStream是所有字节输入流的父类,其定义了基础的读取方法,常用的方法如下: int read()

读取一个字节,以int形式返回,该int值的”低八位”有效,若返回值为-1则表示EOF。

int read(byte[] d)

尝试最多读取给定数组的length个字节并存入该数组,返回值为实际读取到的字节量。

OutputStream是所有字节输出流的父类,其定义了基础的写出方法,常用的方法如下:

void write(int d)

写出一个字节,写的是给定的int的”低八位”

void write(byte[] d)

将给定的字节数组中的所有字节全部写出。

2. 文件流

2.1. 创建FIS对象

FileInputStream是文件的字节输入流,我们使用该流可以以字节为单位读取文件内容。

FileInputStream有两个常用的构造方法:

①FileInputStream(File file):

创建用于读取给定的File对象所表示的文件FIS

例如:

File file =newFile("demo.dat");
FileInputStream fis
=newFileInputStream(file);//创建一个用于读取demo.dat文件的输入流

②FileInputStream(String name):

创建用于读取给定的文件系统中的路径名name所指定的文件的FIS

例如

//创建一个用于读取demo.dat文件的输入流
=newFileInputStream("demo");

2.2. 创建FOS对象(重写模式)

FileOutputStream是文件的字节输出流,我们使用该流可以以字节为单位将数据写入文件。

构造方法:

FileOutputStream(File file):

创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

例如:

FIle file =newFile("demo.dat");
FileOutputStream fos =newFileOutputStream(file);

FileOutputStream(String filename):

创建一个向具有指定名称的文件中写入数据的输出文 件流。

例如:

FileOutputStream fos =newFileOutputStream("demo.dat");

  • 若指定的文件已经包含内容,那么当使用FOS对其写入数据时,会将该文件中原有数据全部清除。

2.3. 创建FOS对象(追加模式)

通过上一节的构造方法创建的FOS对文件进行写操作时会覆盖文件中原有数据。若想在文件的原有数据之后追加新数据则需要以下构造方法创建FOS

构造方法:

FileOutputStream(File file,boolean append):

创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

例如:

File file =newFile("demo.dat");
FileOutputStream fos =newFileOutputStream(file,true);

FileOutputStream(String filename,boolean append):

创建一个向具有指定名称的文件中写入数据的输出文 件流。

例如:

FileOutputStream fos =newFileOutputStream("demo.dat",true);

  • 以上两个构造方法中,第二个参数若为true,那么通过该FOS写出的数据都是在文件末尾追加的。

2.4. read()和write(int d)方法

  • FileInputStream继承自InputStream,其提供了以字节为单位读取文件数据的方法read。

    int read()

    从此输入流中读取一个数据字节,若返回-1则表示EOF(End Of File).

  • FileOutputStream继承自OutputStream,其提供了以字节为单位向文件写数据的方法write。

    void write(int d)

    将指定字节写入此文件输出流。,这里指写给定的int值的”低八位”

    例如

fos.write(‘A‘);//这里要注意,char占用2个字节,但这里只写入了1个字节。

2.5. read(byte[] d)和write(byte[] d)方法

FileInputStream也支持批量读取字节数据的方法:

int read(byte[] b)

从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中

FileOutputStream也支持批量写出字节数据的方法:

void write(byte[] d)

将 b.length 个字节从指定 byte 数组写入此文件输出流中。

例如:

FileOutputStream fos =newFileOutputStream("demo.txt");
byte[] data ="HelloWorld".getBytes();
fos.write(data);//会将HelloWorld的所有字节写入文件。
void write(byte[] d,int offset,int len)//将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。

例如:

FileOutputStream fos =newFileOutputStream("demo.txt");
byte[] data ="HelloWorld".getBytes();
fos.write(data,5,5);//只会将world这5个字节写入文件。

3. 缓冲流

3.1. BIS基本工作原理

在读取数据时若以字节为单位读取数据,会导致读取次数过于频繁从而大大的降低读取效率。为此我们可以通过提高一次读取的字节数量减少读写次数来提高读取的效率。

  • BufferedInputStream是缓冲字节输入流。其内部维护着一个缓冲区(字节数组),使用该流在读取一个字节时,该流会尽可能多的一次性读取若干字节并存入缓冲区,然后逐一的将字节返回,直到缓冲区中的数据被全部读取完毕,会再次读取若干字节从而反复。这样就减少了读取的次数,从而提高了读取效率。
  • BIS是一个处理流,该流为我们提供了缓冲功能。

3.2. BOS基本工作原理

与缓冲输入流相似,在向硬件设备做写出操作时,增大写出次数无疑也会降低写出效率,为此我们可以使用缓冲输出流来一次性批量写出若干数据减少写出次数来提高写 出效率。

  • BufferedOutputStream缓冲输出流内部也维护着一个缓冲区,每当我们向该流写数据时,都会先将数据存入缓冲区,当缓冲区已满时,缓冲流会将数据一次性全部写出。

3.3. 使用BIS与BOS实现缓冲输入输出

使用缓冲流来实现文件复制:

FileInputStream fis =newFileInputStream("java.zip");
BufferedInputStream bis =newBufferedInputStream(fis);
FileOutputStream fos =newFileOutputStream("copy_java.zip");
BufferedOutputStream bos =newBufferedOutputStream(fos);
int d =-1;
while((d = bis.read())!=-1){
    bos.write(d);
}
bis.close();//读写完毕后要关闭流,只需要关闭最外层的流即可
bos.close();

3.4. flush方法

使用缓冲输出流可以提高写出效率,但是这也存在着一个问题,就是写出数据缺乏即时性。有时我们需要需要在执行完某些写出操作后,就希望将这些数据确实写出,而非在缓冲区中保存直到缓冲区满后才写出。这时我们可以使用缓冲流的一个方法flush。

void flush()

清空缓冲区,将缓冲区中的数据强制写出。

例如:

BufferedOutputStream bos
=newBufferedOutputStream(
newFileOutputStream("demo.dat")
);
bos.write(‘a‘);//并没有向磁盘写出,而是写入到了BOS的缓存中
bos.flush();//强制将缓存中的数据一次性写出,这时‘a’才会被写入磁盘
bos.close();//实际上,close()方法在变比缓冲流前也调用了flush()

4. 对象流

对象是存在于内存中的。有时候我们需要将对象保存到硬盘上,又有时我们需要将对象传输到另一台计算机上等等这样的操作。这时我们需要将对象转换为一个字节序列,而这个过程就称为对象序列化。相反,我们有这样一个字节序列需要将其转换为对应的对象,这个过程就称为对象的反序列化。

4.1. 使用OOS实现对象序列化

ObjectOutputStream是用来对对象进行序列化的输出流。

其实现对象序列化的方法为:

void writeObject(Object o)

该方法可以将给定的对象转换为一个字节序列后写出。

例如:

Emp emp =newEmp("张三",12,"男");
FileOutputStream fos =newFileOutputStream("Emp.obj");
ObjectOutputStream oos =newObjectOutputStream(fos);
oos.writeObject(emp);//将emp对象序列化后写入文件
oos.close();

4.2. 使用OIS实现对象反序列化

ObjectInputStream是用来对对象进行反序列化的输入流。

其实现对象反序列化的方法为:

ObjectreadObject()

该方法可以从流中读取字节并转换为对应的对象。

例如:

FileInputStream fis =newFileInputStream("Emp.obj");
ObjectInputStream ois =newObjectInputStream(fis);
Emp emp =(Emp)ois.readObject();//将Emp对象从文件中读取并反序列
....
ois.close();

4.3. Serializable接口

  • ObjectOutputStream在对对象进行序列化时有一个要求,就是需要序列化的对象所属的类必须实现Serializable接口。
  • 实现该接口不需要重写任何方法。其只是作为可序列化的标志。
  • 通常实现该接口的类需要提供一个常量serialVersionUID,表明该类的版本。若不显示的声明,在对象序列化时也会根据当前类的各个方面计算该类的默认serialVersionUID,但不同平台编译器实现有所不同,所以若向跨平台,都应显示的声明版本号。
  • 如果声明的类序列化存到硬盘上面,之后随着需求的变化更改了类别的属性(增加或减少或改名),那么当反序列化时,就会出现InvalidClassException,这样就会造成不兼容性的问题。 但当serialVersionUID相同时,它就会将不一样的field以type的预设值反序列化,可避开不兼容性问题。

    例如:

publicclass Emp implements Serializable{
privatestaticfinal long serialVersionUID =1L;
privateString name;
private int age;
privateString gender;
//getter and setter and other
...
}

4.4. transient关键字

对象在序列化后得到的字节序列往往比较大,有时我们在对一个对象进行序列化时可以忽略某些不必要的属性,从而对序列化后得到的字节序列”瘦身”。

关键字 transient

被该关键字修饰的属性在序列化时其值将被忽略.

例如:

publicclass Emp implements Serializable{
privatestaticfinal long serialVersionUID =1L;
privateString name;
privatetransient int age;//该属性在序列化时会被忽略
privateString gender;
//getter and setter and other
...
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 14:53:46

黑马程序员--Java基础--IO基本操作的相关文章

黑马程序员——Java基础---IO(下)

黑马程序员——Java基础---IO(下) ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java除了基本的字节流.字符流之外,还提供了File类.properties类.打印流.序列流等和输入输出相关的类,它们能够帮助我们更好的处理信息.下面将对它们进行简单的介绍. 一.正

黑马程序员——java基础---IO(input output)流字符流

黑马程序员——java基础---IO(input output)流字符流 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- io(input output)流特点: 1,io流用来处理数据之间的传输 2,java对数据的操作是通过流的方式: 3,java用于操作流的对象都在io包中: 4,流按操作数据分为两种:字节流和字符流: 5,流按流向分为:输入流和输出流. 注意:流只能操作数据,而不能操作文件. 3.IO流的常用基类: 1)字节流的抽象

黑马程序员——Java基础---io(上)

黑马程序员——Java基础---io(上) ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java I/O系统负责处理程序的输入和输出,I/O类库位于java.io包中,它对各种常见的输入流和输出流进行了抽象.如果数据流中最小的数据单元是字节,那么称这种流为字节流:如果数据流

黑马程序员——Java基础--IO流(一)---字符流和字节流

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.IO流的介绍及体系 IO流用来处理设备之间的数据传输.java对数据的操作是通过流的方式.java用于操作流的对象都在IO包中. 输入流和输出流相对于内存设备而言:将外设中的数据读取到内存中:输入.将内存中的数据写出到外设中:输出. 流按照操作数据分为两种:字节流和字符流. 字符流的由来:其实就是字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字,再对这个文字进行操作

黑马程序员——Java基础---IO(二)---IO字节流、流操作规律

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! -------   字节流 一.概述 1.字节流和字符流的基本操作是相同的,但字节流还可以操作其他媒体文件. 2.由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流动作. 3.读写字节流:Inpu

黑马程序员——Java基础--IO流(一)---File类以及其他流对象

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.File类 File类是将文件系统中的文件和文件夹封装成了对象.提供了更多的属性和行为可以对这些文件和文件夹进行操作.这些是流对象办不到的,因为流只操作数据.File对象可以作为参数传递给流对象的构造函数.File 类的实例是不可变的:也就是说,一旦创建,File 对象表示的抽象路径名将永不改变. 1.File类中的方法 (1).File类的构造方法以及字段 1 new File(Stri

黑马程序员——java基础IO流——字符流缓冲区和字节流

字符流的缓冲区 l  缓冲区的出现提高了对数据的读写效率. l  对应类 ?    BufferedWriter ?    BufferedReader l  缓冲区要结合流才可以使用. l  在流的基础上对流的功能进行了增强. 1, BufferedWriter 每次可以写入一行,缓冲区的出现是为了提高流的操作效率而出现的.所以在创建缓冲区之前,必须要先有流对象.该缓冲区中提供了一个跨平台的换行符,newLine(); /* 缓冲区的出现是为了提高流的操作效率而出现的. 所以在创建缓冲区之前,

黑马程序员-java基础-IO(二)

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ 一.概述 Java除了基本的字节流.字符流之外,还提供了File类.properties类.打印流.序列流等和输入输出相关的类,它们能够帮助我们更好的处理信息.下面将对它们进行简单的介绍. 一.正文 1.File类       File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹.它的特点是:用来将文件或文件夹封装成对象:方便于对文件与文件夹的属性信息进行操

黑马程序员——Java基础——IO流(二)——File类、Properties类、打印流、序列流

第一件 File类 一.File类 a.用于将文件或者文件夹封装成对象 b.方便对文件与文件夹的属性信息进行操作 c.File对象可以作为参数传递给流的构造函数 d.了解File类中的常用方法 二.File对象的创建 a.File f=new File("a:\\a.txt"): b.File f2=new File("C:\\abc","a.txt");//分开的好处是后一个参数能够使用其他对象如string c.File d=new File