I/O流

来源:互联网 发布:筛选法求100以内的数组 编辑:程序博客网 时间:2024/06/03 17:02

问:IO流是什么,用IO流可以做什么?

   IO流指的是InputStream和OutputStream(就是输入/输出流),通过Input输入流,我们可以将外部的(磁盘、光盘上的)文件读入到程序中;通过Output输出流,我们可以将程序中的数据输出到外部设备上。


问:IO流都包括哪些内容?

IO流根据不同的标准可以有不同的分类:


IO流按处理的数据单位划分:以byte为单位的是字节流(InputStream/OutputStream),以char为单位的是字符流(Reader/Writer);按数据流的流向划分:从外部设备读取数据到程序的是输入流(InputStream/Reader),从程序向外部设备输出数据的是输出流(OutputStream/Writer);按流的角色划分:直接对文件对象进行操作的是节点流,包裹在文本流之上对文件对象进行操作的是处理流。下图为各个流分类之间的关系





下面表格将介绍一些比较关键常用的IO流:


缓冲流、转换流、对象流等都属于处理流


问:在知道IO流的分类和基本的IO流之后,我们又如何来通过类对象来实现程序与文件之间的交互呢?


一、File类:外部文件在程序中的代言人

IO流可以帮助我们对外部文件进行读取、修改和输出。但是,在那之前我们首先要知道java.io包下的另一个类:File类(java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据),因为我们在创建输入流对象的构造参数就是File类的对象。

//file为File类对象FileInputStream fis = new FileInputStream(file);

关于File类,我们可以简单理解为:File类的对象在程序中就代表着我们要操作的外部文件。File类本身给提供了一些方法,让我们能够直接对外部文件进行部分操作,例如:创建新文件,删除已存在的文件,对文件进行重命名等。但是,File类不能够对文件的内容进行操作,例如:读取txt文本文件的内容并输出到控制台,这需要借用IO流才能实现。那么,我们接下来看看File类都提供了哪些方法:



接下来,我们来看看如何创建一个File类对象以及如何通过File类对象对文件进行相关操作。

import java.io.File;import java.io.IOException;import org.junit.Test;public class TestFileBlog {@Testpublic void fileObject(){/* * 1.创建File类对象 * 通过File类的构造函数public File(String pathname)可以创建File类的对象, * 其中构造参数:pathname为目标文件的路径可以是相对路径也可以是绝对路径。 * 绝对路径:从盘符开始的路径,例如:E:\java\test.txt * 相对路径:相对于当前文件的路径,例如:\java\1.jpg 表示当前工程目录下java文件夹下的1.jpg图片 *        相对路径使用的特殊符号: *        --|"\" :代表根目录 *        --|".\" :代表目前所在的目录 *        --|"..\" :代表上一层目录 */File file = new File("E:\\IO\\test.txt");/* * 2.访问文件信息 * --|getName() 返回文件名称(有后缀名) * --|renameTo(File newname) 将文件重命名 */String fileName = file.getName();//file.renameTo(new File("E:\\IO\\test1.txt"));System.out.println("文件名称:" + fileName);/* * 3.文件检测 * --|exists() * --|canRead() * --|canWrite() */boolean exist = file.exists();boolean read = file.canRead();boolean write = file.canWrite();System.out.println("文件是否存在:" + exist);System.out.println("文件是否可读:" + read);System.out.println("文件是否可写:" + write);/* * 4.文件常规信息:length() */long length = file.length();System.out.println("文件长度为:" + length);/* * 5.文件操作: * --|createNewFile() * --|delete() */File file1 = new File("E:\\IO\\test2.txt");try {boolean create = file1.createNewFile();System.out.println("创建文件是否成功:" + create);} catch (IOException e) {e.printStackTrace();}boolean delete = file1.delete();System.out.println("删除文件是否成功:" + delete);}}

上面的代码简单的介绍了,File类对象的创建以及一些常用方法的使用。在这里,我们应该记住File类对象是如何创建的,因为创建IO流对象的构造参数便是File对象。


二、IO流的真正使用(从流的角色出发)

1、节点流( 字节流:FileInputStream  FileOutputStream       字符流:FileReader  FileWriter)

1.1、FileInputStream和FileOutputStream

@Testpublic void test_In_OutputStream(){/* * (文件复制) * 读取E盘IO文件夹下test.txt文件,并将文件的内容输出到同文件夹下test1.txt文件中 *///1.创建File类对象File file = new File("E:\\IO\\test.txt");File file1 = new File("E:\\IO\\test1.txt");//2.创建输入输出流对象FileInputStream fis = null;FileOutputStream fos = null;try{fis = new FileInputStream(file);fos = new FileOutputStream(file1);//3.定义字节数组b接收输入流读取的内容,len为输入流对象读取内容的长度byte[] b = new byte[20];int len;//4.通过循环:fis遍历读取目标文件的内容,fos将内容复制到另一个文件中while((len = fis.read(b)) != -1){fos.write(b, 0, len);}}catch(Exception e){e.printStackTrace();}finally{//5.关闭输入输出流if(fos != null){try {fos.close();} catch (IOException e) {e.printStackTrace();}}if(fis != null){try {fis.close();} catch (IOException e) {e.printStackTrace();}}}}


注:

FileInputStream常用方法:

--|public FileInputStream(File file)  throws FileNotFoundException

参数:目标文件对象

异常:如果该文件不存在,或者它是一个目录,而不是一个常规文件,抑或因为其他某些原因而无法打开进行读取

返回值:无

说明:通过之前已经创建的目标文件File对象file来创建一个FileInputStream对象

--|public FileInputStream(String pathname) throws FileNotFoundException

参数:目标文件的路径名

异常:如果该文件不存在,或者它是一个目录,而不是一个常规文件,抑或因为其他某些原因而无法打开进行读取

说明:通过系统中真实存在的文件的路径名来创建FileInputStream对象

--|public int read() throws IOException

参数:无

异常:如果发生IO错误

返回值:下一个数据字节;如果已到达文件末尾,则返回 -1

说明:从输入流中读取一个字节,如果已至文件末尾,则方法阻塞

--|public int read(byte[] b) throws IOException

参数:预先定义好的字节数组,用来存储从输入流中读取的内容

异常:如果发生IO错误

返回值:长度值length,该长度值为从输入流中读取文件内容的长度;如果已至文件末尾,则返回-1

说明:从输入流中将最多 b.length 个字节的数据读入到一个 byte 数组中。在没有输入可用之时,此方法将阻塞。 

--|public int  read(byte[] b,int off,int len)  throws  IOException

参数:b:存储读取内容的字节数组

           off:目标数组b中的起始偏移量(也就是从字节数b的第几个位置开始写入内容,一般off为0)

           len:读取的最大字节数

异常:如果发生IO错误

返回值:返回读取的内容长度;如果已至文件末尾,则返回-1

说明:从此输入流中将最多 len个字节的数据读入一个 byte 数组中。如果len 不为 0,则在输入可用之前,该方法将阻塞;否则,不读取任何字节并返回0

--|public void close() throws IOException

参数:无

异常:如果发生IO错误

返回值:无

说明:关闭输入流,释放系统资源


FileOutputStream常用方法:

--|public FileOutputStream(String pathname)  throws FileNotFoundException

参数:输出目标文件的系统路径名称

异常:如果文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它

返回值:无

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

--|public FileOutputStream(File file)  throws FileNotFoundException

参数:为了进行写入而打开的文件

异常:如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开

返回值:无

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

--|public void write(int b) throws IOException

参数:要写入的字节

异常:

返回值:

说明:将指定字节写入此文件输出流

--|public void write(byte[] b) throws IOException

参数:数据

异常:

返回值:

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

--|public write(byte[] b,int off,int len) throws IOException

参数:b:数据

           off:数据中的起始偏移量

           len:要写入的字节数

异常:

返回值:

说明:将指定 byte 数组中从偏移量 off 开始的 len个字节写入此文件输出流

--|public void close() throws IOException

参数:无

异常:如果发生IO错误

返回值:无

说明:关闭输出流流,释放系统资源


1.2、FileReader和FileWriter

@Testpublic void test_Reader_Writer(){/* * (文件复制) * 读取E盘IO文件夹下test.txt文件,并将文件的内容输出到同文件夹下test1.txt文件中 *///1.创建File类对象File file = new File("E:\\IO\\test.txt");File file1 = new File("E:\\IO\\test3.txt");//2.创建输入输出流对象FileReader fr = null;FileWriter fw = null;try{fr = new FileReader(file);fw = new FileWriter(file1);//3.创建存储数据的字符数组c以及长度lenchar[] c = new char[20];int len;//4.循环遍历数组并输出复制while((len = fr.read(c)) != -1){fw.write(c,0,len);}}catch(Exception e){e.printStackTrace();}finally{//5.关闭输入输出流if(fw != null){try {fw.close();} catch (IOException e) {e.printStackTrace();}}if(fr != null){try {fr.close();} catch (IOException e) {e.printStackTrace();}}}}



2、处理流

2.1、缓冲流(BufferedInputStream  BufferedOutPutStream   BufferedReader  BufferedWriter)

2.1.1BufferedInputStream和BufferedOutputStream

@Testpublic void test_Buffered_In_OutputStream(){/* * (文件复制) * 读取E盘IO文件夹下test.txt文件,并将文件的内容输出到同文件夹下test1.txt文件中 *///1.创建File对象File file = new File("E:\\IO\\test.txt");File file1 = new File("E:\\IO\\test4.txt");//2.创建相应的节点流:FileInputStream、FileOutputStream//3.创建相应的缓冲流BufferedInputStream bis = null;BufferedOutputStream bos = null;try {FileInputStream fis = new FileInputStream(file);FileOutputStream fos = new FileOutputStream(file1);bis = new BufferedInputStream(fis);bos = new BufferedOutputStream(fos);//4.具体文件的复制byte[] b = new byte[20];int len;while((len = bis.read(b)) !=-1){bos.write(b, 0, len);}} catch (IOException e) {e.printStackTrace();}finally{//5.关闭缓冲流if(bos != null){try {bos.close();} catch (IOException e) {e.printStackTrace();}}if(bis != null){try {bis.close();} catch (IOException e) {e.printStackTrace();}}}}

2.1.2BufferedReader和BufferedWriter

@Testpublic void test_Buffered_Reader_Writer(){/* * (文件复制) * 读取E盘IO文件夹下test.txt文件,并将文件的内容输出到同文件夹下test1.txt文件中 *///1.创建File对象File file = new File("E:\\IO\\test.txt");File file1 = new File("E:\\IO\\test6.txt");//2.创建相关流对象:字符输入输出流  缓冲流BufferedReader br = null;BufferedWriter bw = null;try {FileReader fr = new FileReader(file);FileWriter fw = new FileWriter(file1);br = new BufferedReader(fr);bw = new BufferedWriter(fw);String str;//readLine() 读取并返回文本中的一行 ;如果已至文件末尾则返回nullwhile((str = br.readLine()) != null){bw.write(str);//newLine() 创建新的一行bw.newLine();//flush() 清空缓冲流中的内容bw.flush();}}catch (IOException e) {e.printStackTrace();}finally{if(bw != null){try {bw.close();} catch (IOException e) {e.printStackTrace();}}if(br != null){try {br.close();} catch (IOException e) {e.printStackTrace();}}}}


2.2 转换流(InputStreamReader和OutputStreamWriter)


@Testpublic void test_InputStreamReader(){/* * 转换流:InputStreamReader和OutputStreamWriter * 解码(InputStreamReader):字节流--->字符流 * 编码(OutputStreamWriter):字符流--->字节流 * * (文件复制) * 读取E盘IO文件夹下test.txt文件,并将文件的内容输出到同文件夹下test1.txt文件中 */BufferedReader br = null;BufferedWriter bw = null;try {//解码File file = new File("E:\\IO\\test.txt");FileInputStream fis = new FileInputStream(file);InputStreamReader isr = new InputStreamReader(fis,"GBK");br = new BufferedReader(isr);//编码File file1 = new File("E:\\IO\\test7.txt");FileOutputStream fos = new FileOutputStream(file1);OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");bw = new BufferedWriter(osw);String str;while((str = br.readLine()) != null){bw.write(str);bw.newLine();bw.flush();}}catch (IOException e) {e.printStackTrace();}finally{if(bw != null){try {bw.close();} catch (IOException e) {e.printStackTrace();}}if(br != null){try {br.close();} catch (IOException e) {e.printStackTrace();}}}}

2.3标准流(system.in和system.out)

@Testpublic void test_system_In_Out(){/* * 标准流: * 输入流:system.in * 输出流: systme.out *  * 题目:输入一串小写字符,将小写字符转换成大写输出,当遇到“e”或者“exist” * 时,退出。 */BufferedReader br = null;try {InputStream is = System.in;InputStreamReader isr = new InputStreamReader(is);br = new BufferedReader(isr);String str;while(true){System.out.println("请输入字符:");str = br.readLine();if(str.equalsIgnoreCase("e") || str.equalsIgnoreCase("exsit")){break;}String str1 = str.toUpperCase();System.out.println(str1);}} catch (IOException e) {e.printStackTrace();}finally{if(br != null){try {br.close();} catch (IOException e) {e.printStackTrace();}}}}

2.4打印流(字节流:PrintStream  字符流:PrintWriter)

@Testpublic void test_PrintStream(){/* * 打印流:就是将程序中的内容输出到指定文件中 */FileOutputStream fos = null;try {fos = new FileOutputStream("print.txt");} catch (FileNotFoundException e) {e.printStackTrace();}//创建打印输出流,设置为自动刷新模式(写入换行符或字节“\n”时都会刷新缓冲区)PrintStream ps = new PrintStream(fos,true);//把标准输出流(控制台输出)改成文件输出if(ps != null){System.setOut(ps);}for(int i = 0; i < 255;i++){System.out.print((char)i);if((i + 1) % 5 == 0){System.out.println();}}}

2.5对象流(ObjectInputStream和ObjectOutputStream)

用于存储和读取对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。

序列化(Serialize):用ObjectOutputStream类将一个Java对象写入IO流中

反序列化(Deserialize):用ObjectInputStream类从IO流中恢复该Java对象

:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量

对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原。如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:Serializable,Externalizable;

:如果某个类的字段不是基本数据类型或 String  类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的 Field 的类也不能序列化

import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import org.junit.Test;public class TestObjectStream {//对象反序列化@Testpublic void test_ObjectInputStream(){ObjectInputStream ois = null;try {FileInputStream fis = new FileInputStream("Student.txt");ois = new ObjectInputStream(fis);Student s = (Student)ois.readObject();System.out.println(s);Student s1 = (Student)ois.readObject();System.out.println(s1);} catch (Exception e) {e.printStackTrace();}finally{if(ois != null){try {ois.close();} catch (IOException e) {e.printStackTrace();}}}}//对象序列化@Testpublic void test_ObjectOutputStream(){Student s = new Student(1000, new Person("Bob", 18,'a'));Student s1 = new Student(1001, new Person("Tom",25, 'a'));ObjectOutputStream oos = null;try {FileOutputStream fos = new FileOutputStream("Student.txt");oos = new ObjectOutputStream(fos);oos.writeObject(s);oos.flush();oos.writeObject(s1);oos.flush();}catch(Exception e){e.printStackTrace();}finally{if(oos != null){try {oos.close();} catch (IOException e) {e.printStackTrace();}}}}}/* * 可序列化的对象类的特征: * 1.该类应该实现Serializable接口 * 2.该类中的属性也应该是可序列化的 */class Student implements Serializable{/* * 1.serialVersionUID用来表明类的不同版本间的兼容性 * 2.如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。 *   若类的源代码作了修改,serialVersionUID 可能发生变化。故建议,显示声明 * 3.显示定义serialVersionUID的用途 * --|希望类的不同版本对序列化兼容,因此需确保类的不同版本具有相同的serialVersionUID * --|不希望类的不同版本对序列化兼容,因此需确保类的不同版本具有不同的serialVersionUID */private static final long serialVersionUID = 1234567890;int number;Person p;public Student(int number,Person p){this.number = number;this.p = p;}@Overridepublic String toString() {return "Student [number=" + number + ", p=" + p + "]";}}class Person implements Serializable{private static final long serialVersionUID = 109854321;String name;int age;char sex;public Person(String name,int age,char sex){this.name = name;this.age = age;this.sex = sex;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";}}


0 0