IO流(学习笔记)

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

IO流主要的分类方式有以下3种:

  • 按数据流的方向:输入流、输出流
  • 按处理数据单位:字节流、字符流
  • 按功能:节点流、处理流

在这里插入图片描述
字节流字符流操作数据不同
字节流操作的单元是数据单元是8位的字节,字符流操作的是数据单元为16位的字符。

为什么用字符流?

  • Java中字符是采用Unicode标准,Unicode 编码中,一个英文字母或一个中文汉字为两个字节。
  • 而在UTF-8编码中,一个中文字符是3个字节。例如下面图中,“云深不知处”5个中文对应的是15个字节:-28-70-111-26-73-79-28-72-115-25-97-91-27-92-124
  • 那么问题来了,如果使用字节流处理中文,如果一次读写一个字符对应的字节数就不会有问题,一旦将一个字符对应的字节分裂开来,就会出现乱码了。为了更方便地处理中文这些字符,Java就推出了字符流。

字节流和字符流的其他区别:
1.字节流:一般用来处理图像、视频、音频、PPT、Word等类型的文件。字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。
2.字符流:一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了。
3.字节流可以处理一切文件,而字符流只能处理纯文本文件。字符流 = 字节流 + 编码表

一、File

构造方法
File(String pathname):根据一个路径得到File对象
File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
File(File parent, String child):根据一个父File对象和子文件/目录得到File对象
常用功能:
public boolean creatNewFile():创建一个新文件,若存在,则不重复创建
public boolean mkdir():创建一个目录,若存在,则不创建,只能创建单层目录
public boolean mkdirs():创建一个目录,若存在,则不创建,用于创建单层或多层目录
删除功能:
public boolean delete():删除文件或者文件夹
注意:只能删除空文件夹
重命名功能:
public boolean renameTo(File file):把文件重命名为指定路径
判断功能
public boolean isDirectory(): 判断是否是目录
public boolean isFile(): 判断是否是文件
public boolean exists(): 判断是否存在
public boolean canRead(): 判断是否可读
public boolean canWrite(): 判断是否可写
public boolean isHidden(): 判断是否隐藏
获取功能:
public String getAbsolutePath(): 获取绝对路径
public String getPath(): 获取相对路径
public String getParent() 获取上一级路径,返回字符串,没有返回null
public File getParentFile() 获取上一级路径,返回File类型,没有返回null
public long getTotalSpace() 返回总容量 单位字节
public long getFreeSpace() 返回剩余容量 单位字节
public String getName(): 获取名称
public long length(): 获取长度。字节数
public long lastModified(): 获取最后一次的修改时间,毫秒值
public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组
具体请跳转

二、InputStream

FileInputStream

构造方法有三个,常用的有以下两个:
1、FileInputStream(File file),参数传入一个File类型的对象。
2、FileInputStream(String name),参数传入文件的路径。
常用方法:
1、int read()方法
从文件的第一个字节开始,read方法每执行一次,就会将一个字节读取,并返回该字节ASCII码,如果读出的数据是空的,即读取的地方是没有数据,则返回-1。
2.int read(byte b[])
该方法与int read()方法不一样,该方法将字节一个一个地往byte数组中存放,直到数组满或读完,然后返回读到的字节的数量,如果**一个字节都没有读到,则返回-1
引用

BufferedInputStream

  • 当创建BufferedInputStream时,将创建一个内部缓冲区数组
  • BufferedInputStream 的父类是FilterInputStream
  • 使用BufferedInputStream读资源比FileInputStream读取资源的效率高(BufferedInputStream的read方法会读取尽可能多的字节,执行read时先从缓冲区读取,当缓冲区数据读完时再把缓冲区填满。
  • BufferedInputStream大部分是从缓冲区读入

构造方法
1.BufferedInputStream(InputStream in)
创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用。
2.BufferedInputStream(InputStream in, int size)
创建 BufferedInputStream具有指定缓冲区大小,可以指定缓冲区的大小。

例如:
BufferedInputStream  buffer2  = new BufferedInputStream(new FileInputStream("D:\\www\\abc.txt"));

read方法的使用与FileInputStream类中读的方法是一致的

read()        //一次读取一个字节
read(byte[] ch)    //一次读取一个字节数组
read(byte[] ch , int off,int length)   //一次读取一个字节数组,设置偏移量,以及读取字节的长度

ObjectInputStream和ObjectInputStream

  • ObjectInputStream是将对象的原始数据序列化,ObjectOutputStream将序列化的数据反序列化。一定要注意ObjectOutputStream与ObjectInputStream必须配合使用,且按同样的顺序。
  • ObjectInputStream 用于恢复先前序列化的对象,其它的用途包括主机之间使用socket流传递对象、远程系统调用
  • 只有对象支持java.io.Serializable或java.io.Externalizable接口的才能够被从流中读取

注意:
Java对象的存取条件
1.对象所属的类需要序列化
2.对象中的属性的类也都需要序列化
3.对象所属的类需要提供全局常量serialVersionUID序列化版本号

序列化、反序列化方法
writeObject(对象)
Object o = ois.readObject();
引用

三、OutputStream

FileOutputStream

构造方法:
FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file,boolean append) 意思同上,但是可以追加数据,不覆盖原有数据
FileOutputStream(String path) 创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String path,boolean append)创建一个向具有指定 name 的文件中写入数据的输出文件流。
注:
它与输入流的构造方法有一些不同点
①多了一个boolean类型的参数表可追加
②若文件路径不存在会自动创建,而输入流会报错
常用方法:

//java提供个三种写入数据的形式,分别是字节数组,指定字节数组,字节
write(byte[] b)    将 b.length 个字节从指定 byte 数组写入此文件输出流中。
write(byte[] b, int off, int len)    将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
write(int b)    将指定字节写入此文件输出流

BufferOutputStream

和bufferInputStream原理一样
在这里插入图片描述

 //刷新此缓冲的输出流,保证数据全部都能写出
bos.flush();

四、Reader

FileReader

Java提供了FileWriter和FileReader简化字符流的读写,new FileWriter等同于new OutputStreamWriter(new FileOutputStream(file, true))
构造方法:

  • FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。
  • FileReader(FileDescriptor fd) 在给定从中读取数据的 FileDescriptor 的情况下创建一个新
    FileReader。
  • FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader

常用方法:

  • public int read() throws IOException 读取单个字符。 读取的字符,如果已到达流的末尾,则返回 -1
  • public int read(char[] cbuf) throws IOException 读取一个字符数组
    读取的字符,如果已到达流的末尾,则返回 -1
  • public void close() throws IOException 关闭该流并释放与之关联的所有资源。

示例:

public static void main(String[] args) throws Exception {
    //读取当前项目下的StringDemo.java文件
    FileReader fr = new FileReader("StringDemo.java")
    //一次读取一个字符数组
    char[] chs = new char[1024] ;
    int len = 0 ;
    while((len=fr.read(chs))!=-1) {
        System.out.println(new String(chs,0,len));
    }
        
    //释放资源
    fr.close();

}

BufferedReader

构造方法:

BufferedReader(Reader inputStream) 
BufferedReader(Reader inputStream, int bufSize) 

常用方法:

void     close()
void     mark(int markLimit)
boolean  markSupported()
int      read()
int      read(char[] buffer, int offset, int length)
String   readLine()
boolean  ready()
void     reset()
long     skip(long charCount)

注意:

StringBuffer类的readLine()从每次读取的一行内容,直至读取的为null为止。然后进行输出。

StringBuffer类的read()方法读取到的每一个数字转化后的字符,然后进行输出。

InputStreamReader

InputStreamReader类是从字节流到字符流的桥接器:它使用指定的字符集读取字节并将它们解码为字符。 它使用的字符集可以通过名称指定,也可以明确指定,或者可以接受平台的默认字符集。每次调用一个InputStreamReader的read()方法都可能导致从底层字节输入流中读取一个或多个字节。 为了实现字节到字符的有效转换,可以从基础流中提取比满足当前读取操作所需的更多字节。为了获得最高效率,请考虑在BufferedReader中包装InputStreamReader
InputStreamReader类与FileReader类的关系
1、FileReader类仅仅是InputStreamReader的简单衍生并未扩展任何功能
2、FileReader类读取数据实质是InputStreamReader类在读取,而InputStreamReader读取数据实际是StreamDecoder类读取
在这里插入图片描述代码演示:

		//初级版
		//inputstream:将字节流转换为字符流的桥梁
		InputStreamReader isr = new InputStreamReader(new FileInputStream("utf-8.txt"), "utf-8");//使用指定码表
		//outputstream:将字符流转换为字节流的桥梁
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
		
		int c;
		while((c = isr.read()) != -1) {
			osw.write(c);
		}
		isr.close();
		osw.close();
		-----------------------------------------------------------------------
		//升级版
		BufferedReader br = 									//高效的用指定的编码表读
				new BufferedReader(new InputStreamReader(new FileInputStream("utf-8.txt"), "UTF-8"));
		BufferedWriter bw = 									//高效的用指定的编码表写
				new BufferedWriter(new OutputStreamWriter(new FileOutputStream("gbk.txt"), "GBK"));
		int ch;
		while((ch = br.read()) != -1) {
			bw.write(ch);
		}
		
		br.close();
		bw.close();

五、Writer

FileWriter

构造方法:

  • FileWriter(File file) 根据给定的 File 对象构造一个 FileWriter 对象。
  • FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter
    对象。
  • FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。
  • FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的
    boolean 值来构造 FileWriter 对象。

常用方法:

	write(int c):写入数字,利用 ASCII 码表 或者 Unicode 表转化
    write(String str):写入字符串
    write(char[] cbuf):写入字符数组
    write(String str, int off, int len):写入字符串的一部分
    write(char[] cbuf,int off,int len):写入字符数组的一部分

举例:

public static void testOverload() throws IOException {
        FileWriter fileWriter = new FileWriter("file03.txt");
        // 重载方法一:写入数字,利用 ASCII 码表 或者 Unicode 表转化
        // ASCII 码表中常用的:48 - 0,65 - A,97 - a
        fileWriter.write(65);
        fileWriter.write("\r\n");

        // 定义字符串
        String str = "我很骄傲我是中国人!";
        // 重载方法二:写入字符串
        fileWriter.write(str);
        fileWriter.write("\r\n");
        // 重载方法三:写入字符数组
        char[] javaArray = {'J','a','v','a'};
        fileWriter.write(javaArray);
        fileWriter.write("\r\n");
        // 重载方法四:写入字符串的一部分(结果:我是中国人)
        fileWriter.write(str, 4, 5);
        fileWriter.write("\r\n");
        // 重载方法五:写入字符数组的一部分(结果:v)
        fileWriter.write(javaArray, 2, 1);

        fileWriter.close();
    }

BufferedWriter

BufferedWriter类是Writer的子类,它为了提高效率,加入了缓冲技术,将字符读取对象作为参数。
BufferedWriter类将一个常量值作为默认缓冲区的大小,它同时也可以通过构造函数来指定大小。
提供了newLine()方法,它使用自己的行分隔符概念,它是由系统自带的属性line.separator定义,并非使用换行符来终止行.

writer会立即将其输出发送到基础字符或字节流,所以在使用BufferedWriter来包装writer的子类可以提高输出的效率

BufferedWriter类中的方法都返回void,write()方法,写入字符串的某一部分,flush()方法刷新该流的缓存。
举例:

import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
//缓冲区的出现是为了提高流的操作效率而出现的
//所以在创建缓冲区之前,必须先要有流对象
public class BufferedWriterDemo{
	public static void main(String[] args) throws IOException{
	//在这里抛一个IO异常,才能运行
	FileWriter fr =new FileWriter(E:/buf1.txt”);//创建一个读取流对象和文件相关联
	bufferedWriter bufw = new buffereWriter(fw);//创建buffereWriter类对象
	For(int x=1;x<9;x++){
	  Bufw.write(“abcd”+x);
	  Bufw.newLine();
	  Bufw.flush();
	}
	Bufw.flush();//刷新
	Bufw.clase();//关闭缓冲区
}
}

OutputStreamWriter

原理同InputStreamWriter


换行:

	Windows 操作系统下:\r\n
    
    Linux 操作系统下:\n
    
    Mac 操作系统下:早期使用的是 \r,现在使用的是 \n

字节与字符:

ASCII 码中,一个英文字母(不分大小写)为一个字节,一个中文汉字为两个字节。
UTF-8 编码中,一个英文字为一个字节,一个中文为三个字节。
Unicode 编码中,一个英文为一个字节,一个中文为两个字节。
符号:英文标点为一个字节,中文标点为两个字节。例如:英文句号 .1个字节的大小,中文句号 。占2个字节的大小。
UTF-16 编码中,一个英文字母字符或一个汉字字符存储都需要 2 个字节(Unicode 扩展区的一些汉字存储需要 4 个字节)。
UTF-32 编码中,世界上任何字符的存储都需要 4 个字节。

本篇仅是个人学习笔记,原文请移步大佬

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值