JAVA学习————Day32

IO流

1. IO流
1.1 IO概述

IO参照物是当前程序使用内存
I
input 从硬盘读取数据到内存!!!read 读
O
output 从内存写入数据到硬盘!!! write 写

直播为例:
OBS推流软件 --> 浏览器 OBS输出数据到浏览器
磊哥的键盘,屏幕,声音 --> OBS 对于OBS而言这是输入
浏览器 --> 屏幕,耳机 对于浏览器而言,输出

对于Java而言:
按照处理单位来看
字节流
所有的数据按照字节方式进行传输!!!
字符流
数据按照当前系统采用的编码集方式进行字符操作,该操作局限性很大!!!
所能操作并且不会出现错误的文件,有且只有记事本打开无乱码的文本文件

组合
字节输入流
字节输出流
字符输入流
字符输出流

1.2 缓存概念

缓存缓冲有什么好处???
一般的网站,第二次打开总要比第一次打开速度要快!!!
第一次加载网站打开的过程中,会对当前网页一些固定资源进行保存,
提高用户在访问页面的速度,优化体验。

开发中使用缓冲缓存可以有效的提高文件操作效率!!!

1.3 IO流分类

class InputStream 字节输入流基类
–| class FileInputStream 文件操作字节输入流

class OutputStream 字节输出流基类
–| class FileOutputStream 文件操作字节输出流

class Reader 字符输入流基类
–| class FileReader 文件操作字符输入流

class Writer 字符输出流基类
–| class FileWriter 文件操作字符输出流

需要学习的方法:
read
write

缓冲流:
BufferedInputStream
字节输入缓冲流
BufferedOutputStream
字节输出缓冲流
BufferedReader
字符输入缓冲流
BufferedWriter
字符输出缓冲流

1.4 FileInputStream 文件操作字节输入流

Constructor构造方法
FileInputStream(String filePath);
根据用户指定的文件路径创建对应的FileInputStream,文件操作输入字节流,
如果文件不存在,抛出异常FileNotFoundException
FileInputStream(File file);
根据用户指定对应文件的File类对象,创建对应的FileInputStream,如果文件
不存在,抛出异常FileNotFoundException

Method成员方法
int read();
从文件中读取一个字节数据返回。如果读取到底末尾,返回-1 EOF End Of File
int read(byte[] buf); 【重点】
从文件中读取数据到缓冲数组buf中,返回值类型是从文件中读取到的字节个数,如
果读取到文件末尾,返回-1, EOF End Of File
读取数据的方法,在运行过程中出现了问题,抛出异常IOException

操作流程:
1. 明确对应文件的路径,可以选择直接给予对应的String类型路径,或者创建对应的File类对象,作为参数
2. 创建FileInputStream文件操作字节输入流,打开文件操作管道
3. 从FileInputStream对象中使用方法,读取数据
4. 关闭资源!!!FileInputStream类对象 ==> 水龙头!!!

代码演示
package com.qfedu.a_inputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * FileInputStream 演示
 */
public class Demo1 {
	public static void main(String[] args) throws IOException {
		// 1. 明确操作文件
		File file = new File("D:/aaa/1.txt");
		
		// 2. 创建文件操作输入字节流对象
		FileInputStream fis = new FileInputStream(file);
		
		/*
		 * 3. 读取数据
		 * int read();
		 * 		从文件中读取一个字节数据返回,返回值类型是int类型,但是
		 * int类型数据中,有且只有低8位是有效数据
		 */
		int content = fis.read();
		System.out.println((char) content);
		content = fis.read();
		System.out.println((char) content);
		
		// content = fis.read() content内容和-1比较,不等于-1继续
		while ((content = fis.read()) != -1) {
			System.out.println((char) content);
		}
		
		// 4. 关闭资源
		fis.close();
	}
}
package com.qfedu.a_inputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/*
 * FileInputStream 演示 int read(byte[] buf);
 */
public class Demo2 {
	public static void main(String[] args) throws IOException {
		long start = System.currentTimeMillis();
		// 1. 明确操作文件
		File file = new File("D:/aaa/1.txt");

		// 2. 创建FileInputStream对象
		FileInputStream fis = new FileInputStream(file);

		/*
		 * int read(byte[] buf); 该方法参数需要一个byte类型数组,这是一个缓冲数组。自定义数组容量
		 * 但是一般情况,数组容量是1024的2的指数倍 1024 2048 4096 8192 返回值类型是缓冲数组中有效元素个数,读取到数据的字节个数,如果读取到
		 * 文件末尾,返回-1
		 */
		// 3. 读取文件 4KB缓冲字节数组
		byte[] buf = new byte[1024 * 4];
		int length = -1;

		while ((length = fis.read(buf)) != -1) {
			// 字节数组转换成字符串
			System.out.println(new String(buf, 0, length));
		}

		// 4. 关闭资源
		fis.close();
		

		long end = System.currentTimeMillis();
		
		System.out.println("结束:" + (end - start));
	}
}

时间效率
明显发现使用缓冲数组速度要远远高于单一字节读取操作
读取24.8MB文件
单一字节读取时间 47000 ms
数组缓冲读取数据 19 ms

1.5 FileOutputStream 文件操作字节输出流

Constructor构造方法
FileOutputStream(String filePath);
根据用户指定的路径,创建对应的FileOutputStream文件操作输出流对象。如果
路径不合法,抛出异常FileNotFoundException。
采用写入数据到文件的方式,是【删除写】!!!文件内容清空,在写入数据

FileOutputStream(File file);
	根据用户指定的File类对象,创建对应FileOutputStream文件操作输出流对
	象,如果路径不合法,抛出异常FileNotFoundException。
	采用写入数据到文件的方式,是【删除写】!!!文件内容清空,在写入数据

FileOutputStream(String filePath, boolean append);
	根据用户指定的路径,创建对应的FileOutputStream文件操作输出流对象。如果
	路径不合法,抛出异常FileNotFoundException。
	append参数是boolean类型,如果传入参数为true,表示【追加写】,在文件末
	尾写入数据	

FileOutputStream(File file, boolean append);
	根据用户指定的File类对象,创建对应FileOutputStream文件操作输出流对
	象,如果路径不合法,抛出异常FileNotFoundException。
	append参数是boolean类型,如果传入参数为true,表示【追加写】,在文件末
	尾写入数据	

Method成员方法
void write(int b);
写入一个字节数据写入到文件中
void write(byte[] buf);
写入一个字节数组到文件中
void write(byte[] buf, int off, int count);
写入一个字节数组到文件中,要求从off偏移位置开始,计数count

操作流程:
1. 明确对应文件的路径,可以选择直接给予对应的String类型路径,或者创建对应的File类对象,作为参数
2. 创建FileOutputStream文件操作输出字节流,打开文件操作管道
3. 使用FileOutputStream对象写入数据到文件中
4. 关闭资源!!!

【注意】
1. FileOutputStream拥有创建文件的能力,在路径合法,且对应目录有写入权限下可以创建文件
2. 区分删除写和追加写

代码演示
package com.qfedu.a_inputstream;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * FileOutputStream演示
 */
public class Demo3 {
	public static void main(String[] args) throws IOException {
		// 1. 明确操作文件
		File file = new File("D:/aaa/疯狂打脸.txt");
		
		// 2. 创建FileOutputStream对象,默认使用删除写方式
		FileOutputStream fos = new FileOutputStream(file, true);
		
		// 3. 写入数据到文件中
		fos.write(49);
		fos.write("今天骚磊同学,疯狂被打脸\n".getBytes());
		fos.write("1234567".getBytes(), 0, 3);
		// 4. 关闭资源
		fos.close();
	}
}
1.6 FileReader 文件操作字符输入流

Constructor构造方法
FileReader(String filePath);
根据指定路径的文件创建对应的文件字符输入流对象,如果文件不存在,抛出异常
FileNotFoundException
FileReader(File file);
根据指定路径的File类对象创建文件字符输入流对象,如果文件不存在,抛出异常
FileNotFoundException

Method成员方法
int read();
从文件中读取一个字符数据,返回值为int类型,int类型数据中有且只有低十六位
是有效数据,如果读取到文件末尾返回-1 EOF End Of File
int read(char[] buf);
从文件中读取数据到char类型缓冲数组buf,返回值是读取到字符个数。如果读取
到文件末尾返回-1 EOF End Of File

操作流程:
1. 明确需要读取数据的文件
2. 创建FileReader对象,打开文件操作管道
3. 使用FileReader类对象方法,读取文件数据
4. 关闭资源

代码演示

package com.qfedu.a_inputstream;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

/*

  • FileReade演示
    */
    public class Demo4 {
    public static void main(String[] args) throws IOException {
    // 1. 明确操作文件
    File file = new File(“D:/aaa/疯狂打脸.txt”);

     // 2. 创建FileReader对象,打开文件管道
     FileReader fr = new FileReader(file);
     
     // 3. 读取数据
     // int content = fr.read();
     // System.out.println((char) content);
     char[] buf = new char[1024];
     int count = -1;
     
     while ((count = fr.read(buf)) != -1) {
     	System.out.println(new String(buf, 0, count));
     } 
     
     // 4. 关闭资源
     fr.close();
    

    }
    }

1.7 FileWriter文件操作字符输出流

Constructor构造方法
FileWriter( String filePath);
根据用户指定的路径,创建对应的FileWriter文件操作字符输出流对象。如果
路径不合法,抛出异常FileNotFoundException。
采用写入数据到文件的方式,是【删除写】!!!文件内容清空,在写入数据

FileWriter(File file);
	根据用户指定的File类对象,创建对应FileWriter文件操作字符输出流对
	象,如果路径不合法,抛出异常FileNotFoundException。
	采用写入数据到文件的方式,是【删除写】!!!文件内容清空,在写入数据

FileWriter(String filePath, boolean append);
	根据用户指定的路径,创建对应的FileWriter文件操作字符输出流对象。如果
	路径不合法,抛出异常FileNotFoundException。
	append参数是boolean类型,如果传入参数为true,表示【追加写】,在文件末
	尾写入数据	

FileWriter(File file, boolean append);
	根据用户指定的File类对象,创建对应FileWriter文件操作字符输出流对
	象,如果路径不合法,抛出异常FileNotFoundException。
	append参数是boolean类型,如果传入参数为true,表示【追加写】,在文件末
	尾写入数据	

Method成员方法
void write(int ch);
写入一个字符数据写入到文件中
void write(char[] buf);
写入一个字符数组到文件中
void write(char[] buf, int off, int count);
写入一个字符数组到文件中,要求从off偏移位置开始,计数count
void write(String str);
写入一个字符串到文件中
void write(String str, int offset, int count);
写入一个字符串到文件中,要求从offset偏移位置开始,计数count

【注意】
1. FileWriter拥有创建文件的能力,在路径合法,且对应目录有写入权限下可以创建文件
2. 区分删除写和追加写

代码演示
package com.qfedu.a_inputstream;

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

/*
 * FileWriter
 */
public class Demo5 {
	public static void main(String[] args) throws IOException {
		// 1. 明确文件
		File file = new File("D:/aaa/今天被一发入魂了.txt");
		
		// 2. 创建FileWriter
		FileWriter fw = new FileWriter(file);
		
		// 3. 写入数据
		fw.write('1');
		fw.write("我一个重坦被一个轻坦一发弹药架。。。".toCharArray());
		fw.write("abcdefg".toCharArray(), 1, 3);
		
		fw.write('\n');
		fw.write("胜利就在远方");
		fw.write("0123456789", 5, 4);
		
		// 4. 关闭资源
		fw.close();
	}
1.8 关于字节流和字符流总结
  1. 套路是一样的!!!
    明确文件
    打开管道
    操作文件
    关闭资源
  2. 核心方法
    read 读取,输入
    write 写入,输出
  3. 输出流有创建文件的能力。
  4. 输出流需要注意是删除写还是追加写。
  5. 一定要注意关闭资源!!!resource
1.9 文件拷贝对比
1.9.1 字符流字节流对比
字节流拷贝
package com.qfedu.a_inputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 字节流拷贝文件
 */
public class Demo6 {
	public static void main(String[] args) throws IOException {
		// 南水北调 西气东输
		// 1. 明确数据源
		File srcFile = new File("D:/aaa/1.mp4");
		
		// 2. 明确目的地
		File destFile = new File("D:/aaa/byteStream.mp4");
		
		// 3. 创建FileInputStream输入流对象,读取源文件数据
		FileInputStream fis = new FileInputStream(srcFile);
		
		// 4. 创建FileOutputStream输出流对象,写入数据到目标文件
		FileOutputStream fos = new FileOutputStream(destFile);
		
		// 5. 完成数据拷贝过程,读取数据,写入数据
		byte[] buf = new byte[1024 * 16];
		int length = -1;
		
		while ((length = fis.read(buf)) != -1) {
			fos.write(buf, 0, length);
		}
		
		// 6. 关闭资源 先关后开
		fos.close();
		fis.close();	
	}
}
字符流拷贝
package com.qfedu.a_inputstream;

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

/*
 * 字符流拷贝
 * 无法拷贝非文本可视化文件
 */
public class Demo7 {
	public static void main(String[] args) throws IOException {
		// 南水北调 西气东输
		// 1. 明确数据源
		File srcFile = new File("D:/aaa/1.mp4");

		// 2. 明确目的地
		File destFile = new File("D:/aaa/charStream.mp4");
		
		// 3. 创建FileReader
		FileReader fr = new FileReader(srcFile);
		
		// 4. 创建FileWriter
		FileWriter fw = new FileWriter(destFile);
		
		// 5. 拷贝数据
		char[] buf = new char[1024 * 8];
		int length = -1;
		
		while ((length = fr.read(buf)) != -1) {
			fw.write(buf, 0, length);
		}

		// 6. 关闭资源
		fw.close();
		fr.close();
		
	}
}
1.9.2 字符流操作效率问题
单字节拷贝操作
package com.qfedu.a_inputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 单字节拷贝数据
 */
public class Demo8 {
	public static void main(String[] args) throws IOException {
		long start = System.currentTimeMillis();
		// 南水北调 西气东输
		// 1. 明确数据源
		File srcFile = new File("D:/aaa/1.mp4");

		// 2. 明确目的地
		File destFile = new File("D:/aaa/byteStream.mp4");

		// 3. 创建FileInputStream输入流对象,读取源文件数据
		FileInputStream fis = new FileInputStream(srcFile);

		// 4. 创建FileOutputStream输出流对象,写入数据到目标文件
		FileOutputStream fos = new FileOutputStream(destFile);
		
		int content = -1;
		while ((content = fis.read()) != -1) {
			fos.write(content);
		}
		
		fos.close();
		fis.close();
		
		long end = System.currentTimeMillis();
		
		System.out.println("Time : " + (end - start));
	}
}

缓冲数组形式操作

package com.qfedu.a_inputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*

  • 字节流拷贝文件
    */
    public class Demo9 {
    public static void main(String[] args) throws IOException {
    long start = System.currentTimeMillis();
    // 南水北调 西气东输
    // 1. 明确数据源
    File srcFile = new File(“D:/aaa/1.mp4”);

     // 2. 明确目的地
     File destFile = new File("D:/aaa/byteStream.mp4");
    
     // 3. 创建FileInputStream输入流对象,读取源文件数据
     FileInputStream fis = new FileInputStream(srcFile);
    
     // 4. 创建FileOutputStream输出流对象,写入数据到目标文件
     FileOutputStream fos = new FileOutputStream(destFile);
    
     // 5. 完成数据拷贝过程,读取数据,写入数据
     byte[] buf = new byte[1024 * 16];
     int length = -1;
    
     while ((length = fis.read(buf)) != -1) {
     	fos.write(buf, 0, length);
     }
    
     // 6. 关闭资源 先关后开
     fos.close();
     fis.close();
     
     long end = System.currentTimeMillis();
    
     System.out.println("Time : " + (end - start));
    

    }
    }

有缓冲和无缓冲对比
  1. 在没有使用缓冲的情况下,每一次需要向磁盘读取一个字节数据,然后写入一个字节数据,这样会导致代码中出现太多次数的打开和关闭磁盘的次数。极大的影响效率!!!

  2. 缓冲之后,我们降低了对于磁盘开启次数,并且符合CPU操作磁盘的模式,CPU从磁盘读取数据是每一次4KB

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值