IO流基础 输入流、输出流、深层理解编码 解码 编码表 & 乱码原因

IO流

本质:就是用来传输数据的

  • 作用: 读写
  • 数据的持久化,利用的就是写的功能

1.IO流的特点

  • 数据的传输必须经过内存

  • 外界到内存叫做输入流

  • 内存到外界叫做输出流

  • 流编程关心三要素

    •    数据源: 从哪里到内存
      
    •    目的地: 从内存到哪里去
      
    •    交通工具: 选择对应的流相关的类
      

2.字节流

字节流是万能流,读写纯二进制文件必须用字节流 【视频 音频 图片】

  •    文本文件 【java txt html css js xml...】
    
  •    InputStream
    
    •    	FileInputStream
      
      •   		BufferedInputStream
        
  •    OutputStream
    
    •    	FileOutputStream
      
      •   	BufferedOutputStream
        

2.1输出流

输出流的特点: 如果输出流对应的路径没有真实的文件,会自动创建

常用方法

说明
void close()关闭此输出流并释放与此流有关的所有系统资源。
void flush()刷新此输出流并强制写出所有缓冲的输出字节。 缓冲区【字节数组 字符数组 容器】刷新到外界
void write(byte[] b)将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len)将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b)将指定的字节写入此输出流。

2.2输入流

  • 单字节
说明
abstract int read()从输入流中读取数据的下一个字节。

特点

  1. 每次读取一个字节,读取完之后,文件指针向后移动一个字节单位,准备读取下一个字节
  2. 际读取的内容,如果读取到文件末尾返回-1
  3. 方法返回的是读取内容

缺点

  1. 效率太低
  2. 如果有中文可能乱码
  • 数组
说明
int read(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b, int off, int len)将输入流中最多 len 个数据字节读入 byte 数组。

特点

  1. 一次性读取一个字节数组,放入到形参中

  2. 每读取一个字节数组,并且将文件指针指向下一个字节数组后的位置

  3. 方法返回的结果是实际读取的长度,读取到文件末尾返回-1

2.2.1读取原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EBtlelf9-1574675065111)(E:\尚学堂\TYPORA_NOTES\16.3 IO流.assets\读取原理.png)]

2.3高效字节缓冲流

BufferedInputStream BufferedOutputStream

用法

BufferedInputStream is = new BufferedInputStream(InputStream in);
//根据多态
InputStream inputStream = new FileInputStream();

//简化
BufferedInputStream is = new BufferedInputStream(new FileInputStream());

2.4注意事项

  1. 数据写入完成后记得调用**close()**方法关闭流对象

  2. 数据追加写入要使用如下构造方法
    FileOutputStream(File file, boolean append)

    // 追加写入方式
    		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("fos.txt", true));
    		for (int i = 1; i <= 10; i++) {
    			bos.write(("HelloWorld" + i).getBytes());
    			bos.write("\r\n".getBytes());
    		}		
    		bos.close();
    
  3. 不同的系统针对不同的换行符号识别是不一样的
    例如:windows识别的换行符是\r\n,Linux识别的换行符是\n等等。
    常见的一些高级记事本,是可以识别任意换行符号的。

  4. 数据写入中存在两个异常需要处理FileNotFoundExceptionIOException
    FileNotFoundException extends IOException

  5. 多的"-1"问题

    		InputStream is = new FileInputStream("IODemo03.java");
    		int b = 0;
    		//问题代码:
    		//原因,多循环了	
    		while(b != -1) {
                b = is.read();//当b显示的是最后后一个字符,while的条件是ture
                //进入循环后没有字符可以读取,返回-1并输出
    			System.out.print((char)b);
            }
    		//正确代码
    		while((b = is.read()) != -1) {
    			System.out.print((char)b);
            }
    

2.5字节流缺点:

  1. 如果人为的转换可能出现乱码 【字符的编码表有很多】

  2. 处理一些特殊字符【换行符】不方便

  3. 如果我想要读取文本文件中的某一行不方便【不能读行】

3.字符流

字符流是为了更好读写文本文件而引出的 (用记事本打开你能够读懂就是用字符流)

  • Reader
    • InputStreamReader

      •   	FileReader
        
    • BufferedReader

  • Writer
    • OutputStreamWriter

      • FileWriter
    • BufferedWriter

3.1字符输出流(Writer)

Writer说明
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.2字符输入流 ( Reader )

Reader说明
int read()读取单个字符
int read(char[] cbuf)将字符读入数组
abstract int read(char[] cbuf, int off, int len)将字符读入数组的某一部分

3.3转换流

InputStreamReader && OutputStreamWriter

  1. 本质是一个字符流

  2. 能够处理编码

  3. 能够将字节流转换成字符流

		InputStreamReader isr = new InputStreamReader(new FileInputStream("charset.txt"), "utf-8");
		char[] chs = new char[7];
		int len = isr.read(chs);
		System.out.println(new String(chs, 0, len));
		
		osw.close();
		isr.close();
		Reader r = new InputStreamReader(new FileInputStream("IODemo03.java"));

3.4高效缓冲字符流

  • BufferedReader
    • readLine可以读取一行
    • 提高字符流的效率
  • BufferedWriter
    • newLine能够适配不同操作系统的换行符
    • 提高字符流的效率
private static void copy(String srcFileName, String descFileName) {
		try (BufferedReader br = new BufferedReader(new FileReader(srcFileName));
				BufferedWriter bw = new BufferedWriter(new FileWriter(descFileName))){
			String line = null;
			while((line = br.readLine()) != null) {
				bw.write(line);
				bw.newLine();
				bw.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

4.close() & flash() 的区别

  • 字节流是纯粹的二进制,所以可以不用flush,但是字符流需要将某些字节按照某种编码转换成字符,先读取到缓冲区,这个时候必须要flush

  • close方法来自于 AutoCloseable接口输入流和输出流都需要关闭
    如果是输入流,直接释放流资源
    如果是输出流,将所有的缓冲区中字节刷新到外界,再释放资源

  • flush来自于Flushable接口 【输出流】
    输入流不需要flush
    输出流表示将每次读取的内容从内存刷新到外界

5.异常类型

  • java.io.IOException: Stream Closed 流关闭之后不可以再进行读写

  • java.io.FileNotFoundException 文件不存在

6.编码、解码、编码表

编码: 将字符、字符串、流转换成 二进制 [ “c” --> “97” --> 1100001 ]

解码: 将二进制转换成对应的字符、字符串、流 [ 1100001 --> “97” --> “c” ]

编码表: 就是数字和字符对应的一张表

  • 编码表有很多,常见的编码表:
    •    ASCII  美国标准信息交换码
      
    •    Unicode 国际标准码
      
    •    UTF-8 最多用三个字节来表示一个字符。
      
    •    ISO-8859-1 拉丁码表。欧洲码表。【文件服务器或者Tomcat7默认编码就是这个】
      
    •    GB2312/GBK/GB18030 中文编码表。
      
    •    Java平台中**默认采用的编码方式是GBK**。
      

6.1乱码原因

  1. 在文件读写的时候人为的转换

  2. 系统文件编码不一致

  3. 读取和写入的编码表不一致

  4. url编码出现问题

6.2显示问题

视频:

  • 字节流缺失字节,播放不了
  • 字符流缺失可以播放

图片:

  • 字节流图片缺失字节可能可以播放
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值