-----------android培训、java培训、期待与您交流! ------------
1.IO流概述
*IO流用来处理设备之间的数据传输
*Java对数据的操作时通过流的方式
*Java用于操作流的对象都在IO包里
*流按照操作数据分为两种:字节流和字符流
*流按照流向分为:输入流,输出流
2.FileWriter的使用
在硬盘上创建一个文件并写入一些文字数据
- import java.io.*;
- class FileWriterDemo {
- public static void main(String[] args) throws IOException {
- /*
- *创建一个FileWriter对象,创建了一个流,该对象一被初始化就必须要明确被操作的文件
- *如果目标目录下已经有同名文件,将被覆盖
- */
- FileWriter fw = new FileWriter("F:\\test1\\aa.java"); //反斜杠要两个\\
- /*
- *调用write方法将字符串写入流中
- *调用flush方法刷新流的缓冲区,将数据写入目标文件中去
- */
- fw.write("abc");
- fw.flush();
- //关闭流资源,关闭之前会刷新一次流
- fw.close();
- }
- }
3.IO异常处理方式
- import java.io.*;
- class IOExceptionDemo {
- public static void main(String[] args) {
- FileWriter fw = null; //如果声明在try代码块中,fw.close()将会报错
- try {
- fw = new FileWriter("demo.txt");
- fw.write("abcde");
- } catch(IOException e) {
- System.out.println(e.toString());
- }
- finally{ //finally中存放的是一定要执行的操作,一般是关闭资源
- try {
- if(fw!=null) //防止空指针异常
- fw.close();
- } catch (IOException e) {
- System.out.println(e.toString());
- }
- }
- }
- }
意义:因为new FileWriter()会将同名文件覆盖,为了防止数据丢失,应使用续写
- import java.io.*;
- class FileWrite {
- public static void main(String[] args) {
- //传递一个true参数,代表不覆盖已有的文件,并在已经有的文件末尾处进行数据续写
- FileWriter fw = null;
- //一定要做好异常的处理
- try {
- fw = new FileWriter("demo.txt",true);
- fw.write("abcde\r\n"); //\r\n才表示换行,只有\n在记事本中是一个小黑块
- } catch(IOException e) {
- System.out.println(e.toString());
- }
- finally{
- try {
- if(fw!=null)
- fw.close();
- } catch (IOException e) {
- System.out.println(e.toString());
- }
- }
- }
- }
5.文件文本读取方式
- import java.io.*;
- class FileReaderDemo {
- public static void main(String[] args) {
- /*
- *创建一个文件读取流对象,和指定名称的文件相关联
- *要保证该文件是已经存在的,如果不存在,会发生异常
- */
- FileReader fr = null;
- int ch = 0;
- try {
- fr = new FileReader("demo.txt");
- while(ch=fr.read()!=-1){ //注意是返回的int型数据,一次只读一个字符,而且会自动往下读
- System.out.println("ch="+(char)ch);
- }
- } catch(IOException e){
- System.out.println(e.toString());
- }
- finally{
- try {
- if(fr!=null)
- fr.close();
- } catch(IOException e) {
- System.out.println(e.toString());
- }
- }
- }
- }
- //文本读取的第二种方式:将字符读入数组
- import java.io.*;
- class FileReadDemo {
- public static void main(String[] args) {
- FileReader fr = null;
- char[] buf = new char[1024];
- int len = 0;
- /*
- *定义一个字符数组,用于存储读到的字符
- *该read(char[] buf)返回的是读到的字符个数
- */
- try{
- fr = new FileReader("F:\\test1\\aa.java");
- while((len = fr.read(buf))!=-1){ //返回-1表示没有数据
- System.out.println(new String(buf,0,len)); //读到几个打印几个
- }
- } catch(IOException e){
- System.out.println(e.toString());
- }
- finally{
- try {
- if(fr!=null)
- fr.close();
- } catch(IOException e) {
- System.out.println(e.toString());
- }
- }
- }
6.拷贝文本文件
复制原理:
1.在目标目录下创建一个文件,用于存储被复制文件的数据
2.定义读取流和原文件的关联
3.通过不断的读写完成数据存储
4.关闭资源
- import java.io.*;
- class Test {
- public static void main(String[] args) {
- String directory1 = "F:\\java\\kk.java";
- String directory2 = "F:\\test1\\test.txt";
- copy(directory1,directory2);
- }
- public static void copy (String str, String str1) {
- FileReader fr = null;
- FileWriter fw = null;
- char[] buf = new char[1024];
- int len = 0;
- try {
- fr = new FileReader(str);
- fw = new FileWriter(str1,true);
- while ((len = fr.read(buf))!=-1) {
- fw.write(buf,0,len);
- //fw.flush(); 因为finally代码块中fw.close()刷新了流
- }
- } catch (IOException e) {
- System.out.println(e.toString());
- }
- finally {
- // 2个异常一定要分别try catch处理
- try {
- if(fr!=null) {
- fr.close();
- }
- } catch (IOException e) {
- System.out.println(e.toString());
- }
- try {
- if(fr!=null) {
- fw.close();
- }
- } catch (IOException e) {
- System.out.println(e.toString());
- }
- }
- }
- }
7.BufferedWriter
缓冲区的出现时为了提高流的操作效率而出现的
创建缓冲区之前,必须要有流对象
- import java.io.*;
- class Demo {
- public static void main(String[] args) throws IOException{
- //创建一个字符写入流对象
- FileWriter fw = new FileWriter("F:\\test1\\xx.java");
- //为了提高字符写入流效率,加入了缓冲技术
- //只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可
- BufferedWriter bufw = new BufferedWriter(fw);
- bufw.write("ddddf");
- //换行
- bufw.newLine();
- //只要用到缓冲区,就要记得刷新
- bufw.flush();
- //关闭缓冲区,就是在关闭缓冲区中的流对象,因此无需fw.close()
- bufw.close();
- }
- }
8.BufferedReader
- //创建一个读取流对象
- FileReader fr = new FileReader("demo.txt");
- //将读取流对象传递给缓冲区的构造函数
- BufferedReader bufr = new BufferedReader();
- //一行一行读取是高效的,bufr.readLine()
- String line = null;
- while ((line = bufr.readLine())!=null) {
- System.out.println(line);
- }
- //关闭缓冲区
- bufr.close();
9.通过缓冲区复制一个文件
- import java.io.*;
- class Test {
- public static void main(String[] args) {
- String directory1 = "F:\\java\\kk.java";
- String directory2 = "F:\\test1\\xx.java";
- copy(directory1,directory2);
- }
- public static void copy (String str, String str1) {
- FileReader fr = null;
- FileWriter fw = null;
- try {
- fr = new FileReader(str);
- fw = new FileWriter(str1,true);
- BufferedWriter bufw = new BufferedWriter(fw);
- BufferedReader bufr = new BufferedReader(fr);
- String line = null;
- while ((line = bufr.readLine())!=null) {//不读取换行符
- bufw.write(line);
- bufw.newLine(); //注意要换行
- bufw.flush();
- }
- } catch (IOException e) {
- System.out.println(e.toString());
- }
- finally {
- // 2个异常一定要分别try catch处理
- try {
- if(fr!=null) {
- bufr.close();
- }
- } catch (IOException e) {
- System.out.println(e.toString());
- }
- try {
- if(fr!=null) {
- bufw.close();
- }
- } catch (IOException e) {
- System.out.println(e.toString());
- }
- }
- }
- }
10.装饰设计模式
什么情况下使用装饰设计模式
当我们需要对一个类的功能进行改进、增强的时候
装饰模式的基本格式。
含有被装饰类的引用
通过构造函数传入被装饰类对象
被装饰类含有同样的方法,其中调用被装饰类的方法,对其进行改进、增强
和被装饰类继承同一个类或实现同一个接口,可以当做被装饰类来使用
装饰和继承的区别:
装饰模式比继承要灵活,避免了继承体系的臃肿
而且降低了类与类之间的关系
装饰类因为增强已有对象,具备的功能和已有的时相同的,只不过提供了更强的功能
所以装饰类和被装饰类通常是都属于一个体系中的
实例:
- //把一次读一个字符的方法装饰成一次读一行的方法
- public String myReadLine() throws IOException {
- StringBuilder sb = new StringBuilder();
- int ch = 0;
- while ((ch = rean())!= -1) {
- if(ch == '\r')
- continue;
- if(ch == '\n')
- return sb.toString();
- }
- if(sb.length() != 0)
- return sb.toString();
- return null;
- }
11.LineNumberReader
跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。
例:
- package cn.itcast;
- import java.io.FileReader;
- import java.io.IOException;
- import java.io.LineNumberReader;
- class Test {
- public static void main(String[] args) throws IOException {
- FileReader fr = new FileReader("PersonDemo.java");
- LineNumberReader lnr = new LineNumberReader(fr);
- String line = null;
- while ((line = lnr.readLine()) != null) {
- System.out.println(line);
- }
- lnr.close();
- }
- }
12.字节流File读写操作
字节流主要是操作byte的类型数据
字节流与字符流不同:
a.字节流可以操作任意类型数据,而字符流只能操作文本文件
b.字节流的使用比字符流更加广泛,但是操作中文的文本文件时,字符流比字节流好用
字符流操作:主要操作文本文件
FileReader
FileWriter
BufferedReader
BufferedWriter
字节流操作
InputStream
方法:
void close() 关闭此输入流并释放与该流关联的所有系统资源。
int read(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
int read(byte[] b, int off, int len)将输入流中最多 len 个数据字节读入 byte 数组。
OutputStream
方法:
void close()关闭此输出流并释放与此流有关的所有系统资源。
void flush()刷新此输出流并强制写出所有缓冲的输出字节。
void write(byte[] b)将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len)将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
实例:拷贝图片
- package cn.itcast;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- class Test {
- public static void main(String[] args) {
- FileOutputStream fos = null;
- FileInputStream fis = null;
- try {
- fos = new FileOutputStream("C:\\2.bmp");
- fis = new FileInputStream("C:\\1.bmp");
- byte[] buf = new byte[1024];
- int len = 0;
- while ((len = fis.read(buf)) != -1) {
- fos.write(buf, 0, len);
- }
- } catch (IOException e) {
- throw new RuntimeException("复制文件失败");
- } finally {
- try {
- if (fis != null)
- fis.close();
- } catch (IOException e) {
- throw new RuntimeException("读取关闭失败");
- }
- try {
- if (fos != null)
- fos.close();
- } catch (IOException e) {
- throw new RuntimeException("写入关闭失败");
- }
- }
- }
- }
13.字节流的缓冲区
BufferedInputStream
BufferedOutputStream
实例:复制mp3文件
- package cn.itcast;
- import java.io.BufferedInputStream;
- import java.io.BufferedOutputStream;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- class Test{
- public static void main(String[] args)throws IOException {
- copy();
- }
- public static void copy() throws IOException {
- BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("C:\\1.mp3"));
- BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("D:\\2.mp3"));
- int by = 0;
- while ((by=bufis.read()) != -1) {
- bufos.write(by);
- }
- bufos.close();
- bufis.close();
- }
- }
System.out:对应的是标准输出设备,控制台
System.in:对应的是标准输入设备:键盘
例:
- import java.io.*;
- class Test{
- public static void main(String[] args) throws IOException {
- InputStream in = System.in;
- int by = in.read(); //只能读一个字节
- System.out.println(by);
- }
- }
15.读写转换流
类InputStreamReader
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集
为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:
BufferedReader in
= new BufferedReader(new InputStreamReader(System.in));
构造方法
InputStreamReader(InputStream in)
类OutputStreamWriter
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。例如:
Writer out
= new BufferedWriter(new OutputStreamWriter(System.out));
构造方法
OutputStreamWriter(OutputStream out)
转换流实例:
- package cn.itcast;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- class Test{
- public static void main(String[] args) throws IOException {
- //获取键盘录入对象
- InputStream in = System.in;
- //将字节流对象转成字符流对象,使用转换流
- InputStreamReader isr = new InputStreamReader(in);
- //为了提高效率,将字符流进行缓冲区技术的高效操作
- BufferedReader bufr = new BufferedReader(isr);
- String line = null;
- while ((line=bufr.readLine())!=null) {
- System.out.println(line.toUpperCase());
- }
- bufr.close();
- }
- }
16.流操作规律
如何选取流对象
通过三个明确来完成
a.明确源和目的
源:输入流 InputStream Reader
目的:输出流 OutputStream Writer
b.操作的数据是否是纯文本
是:使用字符流
否:使用字节流
c.当体系明确之后,再明确要使用哪个具体的对象
通过设备来进行区分:
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
选取流操作实例:
需求1:将一个文本文件中数据存储到另一个文件中,复制文件
源:InputStream Reader
是否是文本文件?
是,这时就可以选择Reader
明确设备:硬盘上的文件
Reader体系中可以操作文件的对象是FileReader
是否需要提高效率?
是,使用BufferedReader
目的:OutputStream Writer
是否是纯文本?
是,选择writer
设备:硬盘
可以使用FileWriter
是否需要提高效率?
是,使用BufferedWriter
需求2:将键盘录入的数据保存到一个文件中
源:InputStream Reader
是否是纯文本?
是,选择Reader
设备:键盘,对应的对象System.in
由于System.in对应的是字节流
因此使用转换流InputStreamReader
需要提高效率?
使用BufferedReader
目的:OutputStream Writer
是否是文本文件?
是,Writer,但是如果涉及编码问题则选择字节流后转成字符流
设备:硬盘
使用FileWriter,如需要加入指定的编码表,则需要使用转换流OutputStreamWriter
OutputStreamWriter(OutputStream out, CharsetEncoder enc)
是否要提高效率?
是,使用BufferedWriter