黑马程序员 IO流-->字符流

------- android培训java培训、期待与您交流! ----------
  IO流的简单介绍

1、IO流用来处理设备之间的数据传输;

2、Java对数据的操作是通过流的方式;

3、流按流向分为:输入流和输出流,按操作数据分为:字节流和字符流;

4、IO流的四个抽象基类:字节流 InputStream OutputStream 字符流 Reader Writer

什么是输入流和输出流?

输入流和输出流均是相对于程序而言的,可以理解为从磁盘等往程序中读入数据则是输入流,从程序中往磁

盘文件中写入数据则是输出流。

什么是字节流和字符流?

字节流操作数据是以字节为单位,可以处理一些媒体数据,而一个中文最少占两个字节,如果用字节流操作

中文读入写出的是中文的一半,将会出现不可识别的乱码,所以针对一些文字数据,jdk中提供了可供操作文

字数据的字符流,字符流对象中融合了当前系统默认的码表,操作字符的时候会在码表中找到对应的数据。

字符流

数据的最常见体现形式就是文件,我们可以使用Reader和Writer下的FileReader和FileWriter来操作数据。

怎么从一个文件中往程序中读入数据:

1、创建文件输入流对象,并和指定名称的文件相关联;

2、使用对象的read等方法读入数据;

3、关闭流对象。

示例:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderDemo {

	public static void main(String[] args) {
		FileReader reader = null;
		// 由于IO流在操作数据时会抛出异常,我们应该捕获并进行相应的操作
		try {
			// 创建一个文件读取流对象,并和指定名称的文件相关联,如果文件不存在系統会抛出
			// FileNotFoundException异常
			reader = new FileReader("demo.txt");
			
			/*
			int ch = -1;
			// read()一次读一个字符,当数据读完时会返回-1
			while ((ch = reader.read()) != -1) {
			    // 每读入一个字符就在控制台打印一个字符
				System.out.println("ch=" + (char) ch);
			}
			*/
			
			// 定义一个字符数组,用于存储读到字符
			char[] chArr = new char[1024];
			// 用于存储读入char数组中字符的个数
			int len = -1;
			while ((len = reader.read(chArr)) != -1) {
				// 打印读入数组中的所有字符组成的字符串
				System.out.println(new String(chArr, 0, len));
			}
			// 在关闭流资源前可以先刷新一下,把流中的数据刷入目的地
			// 仅使用此方法时并不关闭流资源
			// reader.flush();
		} catch (FileNotFoundException e) {
			System.out.println("文件读取失败");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				// 关闭流资源
				reader.close();
			} catch (IOException e) {
				System.out.println("关闭流资源失败");
			}
		}
	}
}

怎么从程序往一个文件中写入数据:

1、创建文件输出流对象;

2、使用对象的write等方法写入数据;

3、关闭流对象。

示例:

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterDemo {

	public static void main(String[] args) {
		FileWriter writer = null;
		try {
			// 创建一个输出流对象,会在指定目录下创建此文件
			// 如果该目录下有同名文件,将会被覆盖。
			writer = new FileWriter("demo.txt");
			// 如果存在此文件,想要在内容后面续写,传入FileWriter构造方法的第二个参数为true即可
			// writer = new FileWriter("demo.txt",true);

			// 可以直接写入字符串
			writer.write("afdhdj");
			// 刷新流对象中的缓冲的数据,流仍然存在
			// writer.flush();

		} catch (IOException e) {
			System.out.println("写入资源失败");
		} finally {
			try {
				if (writer != null) {
					// 关闭流资源
					writer.close();
				}
			} catch (IOException e) {
				System.out.println("关闭流资源失败");
			}
		}
	}
}

练习:将C盘一个文本文件复制到D盘。

原理:复制文件其实就是将指定的源文件读入内存中再写入到目标文件

示例:

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyDemo {

	public static void main(String[] args) {
		FileWriter writer = null;
		FileReader reader = null;
		try {
			// 创建输出流对象,并指定目标文件
			writer = new FileWriter("d:\\demo.txt");
			// 创建输入流对象,并与要操作的文件相关联
			reader = new FileReader("c:\\demo.txt");
			/* 方法1
			int ch = -1;
			// 每从源文件中读取到一个字符就写入到目标文件中
			while ((ch = reader.read()) != -1) {
				writer.write(ch);
			}
			*/
			
			// 方法2
			char[] buf = new char[1024];
			// 读入buf中的字符个数
			int len = -1;
			while((len = reader.read(buf))!=-1){
				writer.write(buf, 0, len);
			}
		} catch (IOException e) {
			System.out.println("文件读写失败");
		} finally {
			// 关闭流资源
			if (writer != null) {
				try {
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

第一种方法读取一个字符就写入目标文件一个字符,而第二种方法是先把读取的字符存入一个缓冲区,存满

后一次性写入到目标文件中,这样可以避免对文件系统的多次读写,从而提高效率,所以建议使用第二种方法。

字符流的缓冲区

简单介绍:

字符流的缓冲区就是对字符流的一种处理流BufferedReader和BufferedWriter,处理流对象中封装了数组,

将数据存入,再一次性取出。其实处理流就是运用了设计模式中的装饰模式,对已有对象的功能进行增强,

所以处理流必须要有要增强功能的流对象,即构造方法中需要传入相应的输入或输出流对象。

缓冲区的出现提高了流的读写效率

练习:使用处理流来拷贝文件,提高效率。

示例:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyByBuffer {

	public static void main(String[] args) {
		// 声明输入输出流对象
		FileWriter writer = null;
		FileReader reader = null;
		// 声明处理流对象
		BufferedWriter bufWriter = null;
		BufferedReader bufReader = null;
		try {
			// 创建输出流对象,并指定目标文件
			writer = new FileWriter("d:\\demo.txt");
			// 创建输入流对象,并与要操作的文件相关联
			reader = new FileReader("c:\\demo.txt");

			// 创建处理流对象,并把要增强功能的输出流对象传入
			bufWriter = new BufferedWriter(writer);
			bufReader = new BufferedReader(reader);
			// 读入内存中的数据
			String line = null;
			// 每次从流中读一行到line中
			while ((line = bufReader.readLine()) != null) {
				// 将内存中的数据写入流中
				bufWriter.write(line);
				// 换行
				bufWriter.newLine();
				// 将流中的数据刷新到指定文件中
				bufWriter.flush();
			}

		} catch (IOException e) {
			System.out.println("文件读写失败");
		} finally {
			// 关闭流资源
			if (bufWriter != null) {
				try {
					bufWriter.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (bufReader != null) {
				try {
					bufReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
注意:

1>缓冲流要结合流才可以使用,它只是在流的基础上对流的功能进行了增强;

2>缓冲流提供了一个跨平台的行分隔符:newLine();

3>BufferedReader提供了一个一次读取一行的方法readLine();方便于对文本数据的读取;

4>readLine读取的数据不包含任何行终止符,当返回null时,表示读到文件末尾;

5>关闭缓冲流对象即是关闭了它处理的流对象资源,因为缓冲流其实就是在内存中创建一个缓冲的区域,

先把数据存入缓冲区,再进行多个字符的读写以提高文本数据的读写效率,当使用close的时候,实际上

在方法的内部关闭的是构造方法时传入的流对象,而readLine()方法实现的最终原理也是从硬盘一个一个

的读入缓冲流对象封装的字符数组,当读到行终止符时以字符串的形式返回读到的数据。

下面就readLine的原理自定义一个类MyBufferedReader,包含与readLine相同功能的方法。

示例:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

/**
 * 自定义一个功能与BufferedReader相似的类,继承Reader 对象中包含一个输入流对象
 */
class MyBufferedReader extends Reader {
	private Reader r;

	// 构造方法,需要传入一个输入流对象
	// 这里用到了多态,父类引用指向子类对象
	public MyBufferedReader(Reader r) {
		this.r = r;
	}

	@Override
	public int read(char[] cbuf, int off, int len) throws IOException {
		// 直接调用的是输入流对象的方法
		return r.read(cbuf, off, len);
	}

	@Override
	public void close() throws IOException {
		// 从这也可以看出,当调用缓冲区的close的方法时,直接关闭的是传入的输入流的资源
		r.close();
	}

	// 重写一个方法来实现readLine方法的功能,并抛出异常由调用者去处理
	public String myReadLine() throws IOException {
		// 定义一个缓冲区,readLine是用数组来实现的
		StringBuilder builder = new StringBuilder();

		int ch = -1;
		while ((ch = r.read()) != -1) {
			// 如果读到\r字符,则继续读下个字符,并不存入缓冲区
			if (ch == '\r') {
				continue;
			}
			if (ch == '\n') {
				// 当读到换行符时,将缓冲区中的数据以字符串形式返回
				return builder.toString();
			} else {
				// 将读取的字符存入缓冲区
				builder.append((char) ch);
			}
			// 如果最后一行并没有行终止符,那么将缓冲区的数据返回
			if (builder != null) {
				return builder.toString();
			}
		}
		// 读到结尾,返回null
		return null;
	}
}


// 测试类
public class MyBufferedDemo {

	public static void main(String[] args) {

		MyBufferedReader bufferedReader = null;

		try {
			// 创建一个自定义的缓冲流
			bufferedReader = new MyBufferedReader(new FileReader("demo.txt"));

			String line = null;
			// 使用自己创建的方法来读取一行的数据
			while ((line = bufferedReader.myReadLine()) != null) {
				System.out.println(line);
			}
		} catch (FileNotFoundException e) {
			System.out.println("文件读取失败");
		} catch (IOException e) {
			System.out.println("文件读取失败");
		} finally {
			// 关闭流资源
			try {
				bufferedReader.close();
			} catch (IOException e) {
				System.out.println("关闭流资源失败");
			}
		}
	}
}

最后:流一般都是以一对的形式存在的,有输入流就有输出流,例如:FileInputStream和FileOutputStream,

DataInputStream和DataOutputStream等。













  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值