前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java基础之IO流(三)

Java基础之IO流(三)

作者头像
Remember_Ray
发布2020-08-05 11:32:43
3790
发布2020-08-05 11:32:43
举报
文章被收录于专栏:Ray学习笔记Ray学习笔记

Java I/O体系从原理到应用,这一篇全说清楚了

转换流

顾名思义,就是可以把字符与字节的流相互转换

OutputStreamWriter类

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节。它的作用的就是,将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去

/**
 * 字符转字节,并指定编码
 */
public static void test1() throws IOException {
    // 创建与文件关联的字节输出流对象
    FileOutputStream fos = new FileOutputStream("e:\\e.txt");
    // 创建可以把字符转成字节的转换流对象,并指定编码
    OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
    // 调用转换流,把文字写进去,其实是写到转换流的缓冲区中
    // 写入缓冲区
    osw.write("OutputStreamWriter 是字符流通向字节流的桥梁");
    // 关闭资源
    osw.close();
}

其实在OutputStreamWriter流中维护自己的缓冲区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到OutputStreamWriter缓冲区中。然后再调用刷新功能,或者关闭流,或者缓冲区存满后会把缓冲区中的字节数据使用字节流写到指定的文件中

InputStreamReader类

它使用指定的字符编码表读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集

/**
 * 字节转字符,并指定编码
 */
public static void test2() throws IOException {
    // 创建读取文件的字节流对象
    InputStream in = new FileInputStream("e:\\e.txt");
    // 创建转换流对象
    //InputStreamReader isr = new InputStreamReader(in);这样创建对象,会用本地默认码表读取,将会发生错误解码的错误
    InputStreamReader isr = new InputStreamReader(in, "utf-8");
    // 使用转换流去读字节流中的字节
    int ch = 0;
    while ((ch = isr.read()) != -1) {
        System.out.println((char)ch);
    }
    // 关闭资源
    isr.close();
}

注意:在读取指定的编码的文件时,一定要指定编码格式,否则就会发生解码错误,而发生乱码现象

缓冲流

读取数据量大的文件时,读取的速度会很慢,很影响我们程序的效率,那么,我想提高速度,怎么办? Java中提高了一套缓冲流,它的存在,可提高IO流的读写速度, 缓冲流,根据流的分类分类字节缓冲流与字符缓冲流

字节缓冲流

它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了IO流的读写速度

字节缓冲流根据流的方向,共有2个

  • 写入数据到流中,字节缓冲输出流 BufferedOutputStream
  • 读取流中的数据,字节缓冲输入流 BufferedInputStream

字节缓冲输出流 BufferedOutputStream

通过字节缓冲流,进行文件的读写操作 写数据到文件的操作

构造方法

public BufferedOutputStream(OutputStream out)创建一个新的缓冲输出流,以将数据写入指定的底层输出流
/**
 * 写数据到文件的方法(缓冲流)
 */
public static void test3() throws IOException {
    // 创建基本的字节输出流
    FileOutputStream fileOut = new FileOutputStream("e:\\abc.txt");
    // 使用高效的缓冲流,把基本的流进行封装,实现速度的提升
    BufferedOutputStream out = new BufferedOutputStream(fileOut);
    // 写数据
    out.write("字节缓冲输出流 BufferedOutputStream".getBytes());
    // 关闭流
    out.close();
}

字节缓冲输入流BufferedInputStream

构造方法

public BufferedInputStream(InputStream in)
/**
 * 从文件中读取数据(缓冲流)
 */
public static void test4() throws IOException {
    // 1. 创建缓冲流对象
    FileInputStream fileIn = new FileInputStream("e:\\abc.txt");
    // 使用高效的缓冲流,把基本的流进行封装,实现速度的提升
    BufferedInputStream in = new BufferedInputStream(fileIn);
    // 2. 读数据
    int ch = -1;
    while ((ch = in.read()) != -1) {
        System.out.println((char)ch);
    }
    // 3. 关闭资源
    in.close();
}

使用基本的流与高效的流完成复制文件

  • 方式1: 采用基本的流,一次一个字节的方式复制 共耗时 224613毫秒
  • 方式2: 采用基本的流,一个多个字节的方式赋值 共耗时 327毫秒
  • 方式3: 采用高效的流,一次一个字节的方式复制 共耗时 2047毫秒
  • 方式4: 采用高效的流,一个多个字节的方式赋值 共耗时 96毫秒
/*
 * 需求:将d:\\test.avi文件进行复制
 * 		采用4种方式复制
 * 	
 * 
 * 数据源: d:\\test.avi
 * 目的地1: d:\\copy1.avi
 * 目的地2: d:\\copy2.avi
 * 目的地3: d:\\copy3.avi
 * 目的地4: d:\\copy4.avi
 * 
 * 实现的步骤:
 * 	1,指定数据源
 * 	2,指定目的地
 * 	3,读数据
 * 	4,写数据
 * 	5,关闭流
 * 
 */
public class CopyAVI {
	public static void main(String[] args) throws IOException {
		//开始计时
		long start = System.currentTimeMillis();
		//方式1: 采用基本的流,一次一个字节的方式复制
		//method1("d:\\test.avi", "d:\\copy1.avi");
		//方式2: 采用基本的流,一个多个字节的方式赋值
		//method2("d:\\test.avi", "d:\\copy2.avi");
		//方式3: 采用高效的流,一次一个字节的方式复制
		//method3("d:\\test.avi", "d:\\copy3.avi");
		//方式4: 采用高效的流,一个多个字节的方式赋值
		method4("d:\\test.avi", "d:\\copy4.avi");
		
		//结束计时
		long end = System.currentTimeMillis();
		//打印耗时多少毫秒
		System.out.println("共耗时 " +(end - start)+ "毫秒");
	}
	
	//方式4: 采用高效的流,一个多个字节的方式赋值
	private static void method4(String src, String dest) throws IOException {
		//1,指定数据源
		BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
		 //2,指定目的地
		BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
		 //3,读数据
		byte[] buffer = new byte[1024];
		int len = -1;
		while ( (len = in.read(buffer)) != -1) {
			//4,写数据
			out.write(buffer, 0, len);
		}
		 //5,关闭流
		in.close();
		out.close();
	}

	//方式3: 采用高效的流,一次一个字节的方式复制
	private static void method3(String src, String dest) throws IOException {
		//1,指定数据源
		BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
		 //2,指定目的地
		BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
		 //3,读数据
		int ch = -1;
		while ((ch=in.read()) != -1) {
			//4,写数据
			out.write(ch);	
		}		
		 //5,关闭流
		in.close();
		out.close();
	}

	//方式2: 采用基本的流,一个多个字节的方式赋值
	private static void method2(String src, String dest) throws IOException {
		//1,指定数据源
		FileInputStream in = new FileInputStream(src);
		//2,指定目的地
		FileOutputStream out = new FileOutputStream(dest);
		//3,读数据
		byte[] buffer = new byte[1024];
		int len = -1;
		while ( (len=in.read(buffer)) != -1) {
			//4,写数据
			out.write(buffer, 0, len);
		}
		//5,关闭流
		in.close();
		out.close();
	}

	//方式1: 采用基本的流,一次一个字节的方式复制
	private static void method1(String src, String dest) throws IOException {
		//1,指定数据源
		FileInputStream in = new FileInputStream(src);
		//2,指定目的地
		FileOutputStream out = new FileOutputStream(dest);
		//3,读数据
		int ch = -1;
		while (( ch=in.read()) != -1) {
			//4,写数据
			out.write(ch);
		}
		//5,关闭流
		in.close();
		out.close();
	}
}

字符缓冲流

  • 字符缓冲输入流 BufferedReader
  • 字符缓冲输出流 BufferedWriter

字符缓冲输出流BufferedWriter

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入

/**
 * BufferedWriter 字符缓冲输出流
 * 方法
 * 	public void newLine()写入一个行分隔符
 *
 * 需求: 通过缓冲输出流写入数据到文件
 * 分析:
 * 	1,创建流对象
 * 	2,写数据
 * 	3,关闭流
 *
 */
public static void test5() throws IOException {
    // 基本字符输出流
    FileWriter fileOut = new FileWriter("file.txt");
    // 把基本的流进行包装
    BufferedWriter out = new BufferedWriter(fileOut);
    // 写数据
    for (int i = 0; i < 5; i++) {
        out.write("hello");
        out.newLine();
    }
    // 关闭资源
    out.close();
}

字符缓冲输入流BufferedReader

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取

/**
 * BufferedReader 字符缓冲输入流
 *
 * 方法:
 * 	String readLine()
 *  需求:从文件中读取数据,并显示数据
 */
public static void test6() throws IOException {
    // 创建流
    BufferedReader in = new BufferedReader(new FileReader("file.txt"));
    // 读数据
    //一次读取文本中一行的字符串内容
    String line = null;
    while ((line = in.readLine()) != null) {
        System.out.println(line);
    }
    // 关闭资源
    in.close();
}

其实字符缓冲流 就是多了2个方法 一个是新起一行的 newLine(),还有一个是 readLine方法 读取一行的字符数据。(如果是字符流 其实返回的是字符要char()转换成String)

使用字符缓冲流完成文件的复制

/**
 * 采用高效的字符缓冲流,完成文本文件的赋值
 *
 * 数据源: file.txt
 * 目的地: copyFile.txt
 *
 * 分析:
 * 	1,指定数据源, 是数据源中读数据,采用输入流
 * 	2,指定目的地,是把数据写入目的地,采用输出流
 * 	3,读数据
 * 	4,写数据
 * 	5,关闭流
 */
public static void test7() throws IOException {
    // 1. 指定数据源,读取数据采用输入流
    BufferedReader in = new BufferedReader(new FileReader("file.txt"));

    // 2. 指定目的地,写入数据采用输出流
    BufferedWriter out = new BufferedWriter(new FileWriter("copyFile.txt"));

    // 3. 开始读取数据
    String line = null;
    while ((line = in.readLine()) != null) {
        // 4. 写数据
        out.write(line);
        // 写入换行符号
        out.newLine();
    }

IO流使用规律总结

明确一: 要操作的数据是数据源还是数据目的

先根据需求明确要读还是要写

  • 源 : InputStreamReader
  • 目的 : OutputStreamWriter

明确二: 要操作的数据是字节还是文本

已经明确到了具体的体系上

  • 字节 : InputStream
  • 文本 : Reader

目的

  • 字节 : OutputStream
  • 文本 : Writer

明确三: 明确数据所在的具体设备

完全可以明确具体要使用哪个流对象

源设备:

  • 硬盘: 文件 File开头
  • 内存: 数组、字符串
  • 键盘: System.in
  • 网络: Socket

目的设备

  • 硬盘 : 文件 File开头
  • 内存 :数组,字符串
  • 屏幕 : System.out
  • 网络 :Socket

明确四: 是否需要额外功能呢?

  • 转换吗? 转换流. InputStreamReader OutputStreamWriter
  • 高效吗? 缓冲区对象。Buffered…

Java IO 总结

字节流

字节输入流 InputStream

  • FileInputStream 操作文件的字节输入流
  • BufferedInputStream 高效的字节输入流

字节输出流 OutputStream

  • FileOutputStream 操作文件的字节输出流
  • BufferedOutputStream 高效的字节输出流

字符流

字符输入流 Reader

  • FileReader 操作文件的字符输入流
  • BufferedReader 高效的字符输入流
  • InputStreamReader 输入操作的转换流(把字节流封装成字符流)

字符输出流 Writer

  • FileWriter 操作文件的字符输出流
  • ufferedWriter 高效的字符输出流
  • OutputStreamWriter 输出操作的转换流(把字节流封装成字符流)

方法

读数据方法

read() 一次读一个字节或字符的方法 read(byte[] char[]) 一次读一个数组数据的方法 readLine() 一次读一行字符串的方法(BufferedReader类特有方法) readObject() 从流中读取对象(ObjectInputStream特有方法)

写数据方法

write(int) 一次写一个字节或字符到文件中 write(byte[] char[]) 一次写一个数组数据到文件中 write(String) 一次写一个字符串内容到文件中 writeObject(Object ) 写对象到流中(ObjectOutputStream类特有方法) newLine() 写一个换行符号(BufferedWriter类特有方法)

过程

向文件中写入数据的过程

  1. 创建输出流对象
  2. 写数据到文件
  3. 关闭输出流

从文件中读数据的过程

  1. 创建输入流对象
  2. 从文件中读数据
  3. 关闭输入流

文件复制的过程

  1. 创建输入流(数据源)
  2. 创建输出流(目的地)
  3. 从输入流中读数据
  4. 通过输出流,把数据写入目的地
  5. 关闭流
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-02-07|,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 转换流
    • OutputStreamWriter类
      • InputStreamReader类
      • 缓冲流
        • 字节缓冲流
          • 字节缓冲输出流 BufferedOutputStream
          • 字节缓冲输入流BufferedInputStream
          • 使用基本的流与高效的流完成复制文件
        • 字符缓冲流
          • 字符缓冲输出流BufferedWriter
          • 字符缓冲输入流BufferedReader
          • 使用字符缓冲流完成文件的复制
      • IO流使用规律总结
      • Java IO 总结
        • 字节流
          • 字节输入流 InputStream
          • 字节输出流 OutputStream
        • 字符流
          • 字符输入流 Reader
          • 字符输出流 Writer
        • 方法
          • 读数据方法
          • 写数据方法
        • 过程
          • 向文件中写入数据的过程
          • 从文件中读数据的过程
          • 文件复制的过程
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档