黑马程序员——IO流篇

------- android培训java培训、期待与您交流! ----------

IO流概述

1.什么是流

    ①.流是一种抽象的概念,可以理解为输入/输出的途径。

    ②.一个读取字节序列的对象被称为输入流,一个写入字节序列的对象称为输出流。输入流和输出流是相对于程序本身而言的。

2.流的分类

    ①.按照流向对流进行分类,分输入流和输出流。

    ②,按照处理的不同数据类型对流进行分类,分为字节流(Byte)和字符流(Character)。

3.字节流和字符流的区别

    ①.字节流读取的时候,读到一个字节就返回一个字节。字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8码表中是3个字节)时。先去查指定的编码表,将查到的字符返回。

    ②.字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流

    ③.简单说:字节流+编码表。

IO流主要结构

    

字节流

1.字节流概述

    Java的IO系统提供了InputStream和OutputStream两个抽象类实现字节数据(8位)的输入和输出。

2.InputStream类

    (1)定义

        InputStream类是个抽象类,作为字节输入流的直接或间接的父类,它定义了许多有用的方法,包括读取、移动指针、标记、复位、关闭等方法。

    (2)常用方法

        ①.int available()回此输入流方法的下一个调用方可以不受阻塞地从此输入流读取(或跳过)的字节数

        ②.void close()  关闭此输入流并释放与该流关联的所有系统资源。

        ③.abstract  int read()  从输入流读取下一个数据字节。 如果到达流的末尾,则返回 -1。

        ④.int read(byte[] b)从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中。 如果到达流的末尾,则返回 -1。

        ⑤.int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入字节数组。 如果到达流的末尾,则返回 -1。

        ⑥.long skip(long n) 跳过和放弃此输入流中的 n 个数据字节。 

    (3)FileInputStream类

        ①.FileInputStream类是InputStream的一个子类, 用于读取诸如图像数据之类的原始字节流。

        ②.它代表从文件中读取数据,其构造函数参数可以是一个文件对象或字符串(文件的路径)。

// 方式一,一次读一个字节
int by = 0;
// 读取,赋值,判断
while ((by = fis.read()) != -1) {
	System.out.print((char) by);
}
// 方式二,一次读一个字节数组
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
	System.out.print(new String(bys, 0, len));
}

3.OutputStream类

    (1)定义

        OutputStream类也是个抽象类,作为字节输出流的直接或间接的父类,它定义了许多有用的方法,包括读取、移动指针、标记、复位、关闭等方法。

    (2)常用方法

        ①.void close()  关闭此输出流并释放与此流有关的所有系统资源。

        ②.void flush() 刷新此输出流并强制写出所有缓冲的输出字节。

        ③.void  write(byte[] b)   将 b.length 个字节从指定的字节数组写入此输出流。

        ④.void  write(byte[] b, int off, int len)  将指定字节数组中从偏移量 off 开始的 len 个字节写入此输出流。

        ⑤.abstract  void  write(int b)  将指定的字节写入此输出流。

    (3)FileOutputStream

        ①.FileOutputStream类是OutputStream的一个子类,是用于将数据写入File或FileDescriptor的输出流。

        ②.通过该输出流把数据写入文件,构造函数的参数可以是文件对象或者字符串(文件的路径)

//一次写一个字节
int by = 0;
while ((by = fis.read()) != -1) {
	fos.write(by);
}
//一次写一个字节数组
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
	fos.write(bys, 0, len);
}

字符流

1.字符流概述

    字符流主要是用于支持Unicode的文字内容,其中输入流Reader抽象类用来读取,输出流Writer抽象类用来写入。

2.Reader类

    (1)定义

        Reader类是读取字符流的父类,它是抽象类,所有继承自该类的子类都必须实现抽象方法reader()和close()。

    (2)常用方法

        ①.abstract  void close()   关闭该流。

        ②.void mark(int readAheadLimit)  标记流中的当前位置。 

        ③.boolean markSupported()   判断此流是否支持mark()操作。

        ④.int read()   读取单个字符。如果已到达流的末尾,则返回-1 

        ⑤.int read(char[] cbuf)  将字符读入数组。如果已到达流的末尾,则返回-1

        .abstract int read(char[] cbuf, int off, int len)    将字符读入数组的某一部分。 如果已到达流的末尾,则返回-1

        .int read(CharBuffer target)   试图将字符读入指定的字符缓冲区。 如果已到达流的末尾,则返回-1。 

        .boolean ready()   判断是否准备读取此流。

        .void reset()    重置该流。

        ⑨+.long skip(long n) 跳过字符

    (3)FileReader类

        ①.FileReader类继承自InputStreamReader,读取字符流。

        ②.该类的构造函数默认采用了合适的字符编码和字节缓冲区大小

        ③.该类通过指定一个File对象或一个文件名的条件下创建一个新的FileReader对象。

3.Writer类

 (1)定义

        Writer类是字符流输出类的父类,它是抽象类,所有继承自该类的子类都必须实现抽象方法writer()。

    (2)常用方法

        ①.Writer append(char c)   将指定字符追加到此writer。

        ②.Writer append(CharSequence csq)   将指定字符序列追加到此writer。  

        ③.Writer append(CharSequence csq, int start, int end)    将指定字符序列的子序列追加到此 writer.Appendable。

        ④.abstract  void close()   关闭此流,但要先刷新它。

        ⑤.abstract  void flush()   刷新此流。

        .void write(char[] cbuf)     写入字符数组。

        .abstract  void write(char[] cbuf, int off, int len)    写入字符数组的某一部分。 

        .void write(int c)   写入单个字符。

        .void write(String str)    写入字符串。

        ⑨+.void write(String str, int off, int len)     写入字符串的某一部分。 

    (3)FileWriter类

        ①.FileWriter类继承自OutputStreamWriter,写入字符流。

        ②.该类把字符写入文件,文件位置在构造函数中指定。

        ③.该类的构造函数接受默认的字符编码和默认的字节缓冲区大小。

//一次读写一个字符	
public static void main(String[] args) throws IOException {
	FileReader fr = new FileReader("d:\\a.txt");
	FileWriter fw = new FileWriter("d:\\b.txt");
	
	int ch = 0;
	while ((ch = fr.read()) != -1) {
		fw.write(ch);
	}
	
	fr.close();
	fw.close();
}

转换流

1.转换流概述

    ①.字节流操作中文数据不是特别的方便,所以就出现了转换流。 转换流的作用就是把字节流转换字符流来使用。

    ②.转换流其实是一个字符流,字符流 = 字节流 + 编码表

2.编码表

    ①由字符和对应的数值组成的一张表

3.常见的编码表

    ①.ASCII

    ②.ISO-8859-1

    ③.GB2312

    ④.GBK

    ⑤.GB18030

    ⑥.UTF-8

4.字符串中的编码问题

    ①.编码:String -- byte[]

    ②.解码:byte[] -- String  

5.IO流中的编码问题

    ①.OutputStreamWriter

        OutputStreamWriter(OutputStream os):默认编码,GBK

        OutputStreamWriter(OutputStream os,String charsetName):指定编码

    ②.InputStreamReader

        InputStreamReader(InputStream is):默认编码,GBK

        InputStreamReader(InputStream is,String charsetName):指定编码

    ③.编码问题其实很简单

        编码只要一致即可。

高效流

1.什么是高效流

    ①.高效流又称为带缓冲区的流,可以把数据先放入缓冲区,防止每次读、写数据时进行实际的操作,减少了数据实际访问的时间开销。

    ②.高效流分为:高效的字节流BufferedInputStream、BufferedOutputStream和高效的字符流BufferedReader、BufferedWriter。

2.BufferedInputStream类

    ①.本类间接继承自InputStream类,并实现了abstract  int read()方法。此类没有特殊方法需要学习。

3.BufferedOutputStream类

    ①.本类间接继承自OutputStream类,并实现了abstract  void write(int b)方法。此类也没有特殊方法需要学习。

// 高效字节流一次读写一个字节:
public static void method3(String srcString, String destString)
		throws IOException {
	BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
			srcString));
	BufferedOutputStream bos = new BufferedOutputStream(
			new FileOutputStream(destString));

	int by = 0;
	while ((by = bis.read()) != -1) {
		bos.write(by);

	}

	bos.close();
	bis.close();
}

// 高效字节流一次读写一个字节数组:
public static void method4(String srcString, String destString)
		throws IOException {
	BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
			srcString));
	BufferedOutputStream bos = new BufferedOutputStream(
			new FileOutputStream(destString));

	byte[] bys = new byte[1024];
	int len = 0;
	while ((len = bis.read(bys)) != -1) {
		bos.write(bys, 0, len);
	}

	bos.close();
	bis.close();
}

4.BufferedReader类

    ①.此类间接继承自Reader类,并实现了abstract  void close()方法和abstract int read(char[] cbuf, int off, int len)方法

    ②.此类有一个新方法

        String readLine()  读取一个文本行。 如果已到达流末尾,则返回 null 

5.BufferedWriter类

    ①.本类间接继承自Writer类,并实现了abstract void close()方法、abstract void flush()方法abstract void flush()方法。此类也没有特殊方法需要学习。

    ②.此类有一个新方法

        void newLine()  写入一个行分隔符。

// 一次读写一个字符数组
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

	char[] chs = new char[1024];
	int len = 0;
	while ((len = br.read(chs)) != -1) {
		bw.write(chs, 0, len);
		bw.flush();
	}

	// 释放资源
	bw.close();
	br.close();
// 一次读一行
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

	// 读写数据
	String line = null;
	while ((line = br.readLine()) != null) {
		bw.write(line);
		bw.newLine();
		bw.flush();
	}

	// 释放资源
	bw.close();
	br.close();

IO小结

其他流

1.打印流

    (1).分类

        ①.PrintStream——字节打印流

        ②.PrintWriter——字符打印流

    (2).特点

        ①.只操作目的地,不操作数据源

        ②.可以操作任意类型的数据

        ③.如果启动了自动刷新,在调用println()方法时,能够自动换行并刷新

        ④.打印流自动包装高效

2.标准输入输出流

    (1).System类下面有这样两个字段

        ①.in标准输入流

        ②.out标准输出流

    (2).键盘录入数据的三种方式

        ①.main方法的args接受参数

        ②.System.in通过BufferedReader进行包装

        ③.Scanner类

3.随机访问流

    RandomAccessFile——随机访问流,该流可以按照文件指针的位置写数据和读数据。

4.合并流

    SequenceInputStream——合并流,该流可以把多个输入流的数据写到一个输出流中。该流只提供了读的方法。

5.序列化流

    ObjectOutputStream——序列化流,该流可以把对象写入文本文件或者在网络中传输。

    (1).如何实现序列化呢?

        ①.让被序列化的对象所属类实现序列化接口。

        ②.该接口是一个标记接口,没有方法,没有功能需要实现。

    (2).注意问题

        ①.把数据写到文件后,再去修改类会产生一个问题。

        ②.该如何解决这个问题呢?在类文件中,给出一个固定的序列化id值,serisversion UID= ;,这样也可以解决黄色警告线的问题。

        ③.transient用来声明不需要序列化成员变量。

    (3).反序列化

        ObjectInputStream被称为反序列化。

        ①. 对象 转换成 流数据 称为序列化,

        ②.流数据 转换成 对象 称为反序列化。

/*
 * 序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象 -- 流数据(ObjectOutputStream)
 * 反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 -- 对象(ObjectInputStream)
 */
public class ObjectStreamDemo {
	public static void main(String[] args) throws IOException,
			ClassNotFoundException {
		// 由于我们要对对象进行序列化,所以我们先自定义一个类
		// 序列化数据其实就是把对象写到文本文件
		// write();

		read();
	}

	private static void read() throws IOException, ClassNotFoundException {
		// 创建反序列化对象
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
				"oos.txt"));

		// 还原对象
		Object obj = ois.readObject();

		// 释放资源
		ois.close();

		// 输出对象
		System.out.println(obj);
	}

	private static void write() throws IOException {
		// 创建序列化流对象
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
				"oos.txt"));

		// 创建对象
		Person p = new Person("林青霞", 27);

		// public final void writeObject(Object obj)
		oos.writeObject(p);

		// 释放资源
		oos.close();
	}
}

6.Properties

    Properties是一个集合,Hashtable(Map)的子类。它的属性是集合,但是能和IO流相结合。

    (1).特有功能

        ①.String getProperty(String key)   用指定的键在此属性列表中搜索属性。 

        ②.String getProperty(String key, String defaultValue)   用指定的键在属性列表中搜索属性。

        ③.Set<String> stringPropertyNames() 获取所有键的集合。

    (2).和IO结合的方法

        ①.把键值对形式的文本文件内容加载到集合中

            void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。 

        ②.把集合的数据存储到文本文件中

            void store(OutputStream out, String comments)    以适合使用 load 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值