Java进阶—字节流、字符流

一、IO流

I:input 输入(读取),即把硬盘中的数据,【读取】到内存(临时存储)中使用
    
O:output 输出(写入),即把内存中的数据,【写入】到硬盘(永久存储)中保存
    
流:数据(字符,字节),1个字符=2个字节,1个字节=8bit(8个二进制位)

IO流的最顶层的父类:

字节流:
    字节输入流:InputStream
    字节输出流:OutputStream
    
字符流:
    字符输入流:Reader
    字符输出流:Writer

二、字节输出流

1.一切皆为字节

一切文件数据(文本、图片、视频等)在存储时,都是以【二进制】数字的形式保存,都是一个一个的字节,那么传输时一样如此。

所以字节流可以传输任意文件数据。在操作流的时候,要时刻明确,无论使用什么样的流对象,【底层传输的始终为二进制数据】。

2.java.io.OutputStream:字节输出流

此【抽象类】是表示输出字节流的所有类的超类,定义了一些子类共性的成员方法:

-public void close():关闭此输出流并释放与此流相关联的任何系统资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序的效率)
-public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。
-public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流
-public void write(byte[] b, int off, int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
-public abstract void write(int b):将指定的字节输出流

3.java.io.FileOutputStream extends OutputStream

FileOutputStream:文件字节输出流
作用:把内存中的数据写入到硬盘的文件中

构造方法:

FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流。

FileOutputStream(File file):创建一个向指定File对象表示的文件中写入数据的文件输出流。

参数:写入数据的目的地
    String name:目的地是一个文件的路径
    File file:目的地是一个文件
    
构造方法的作用:
    1.创建一个FileOutputStream对象
    2.会根据构造方法中传递的文件/文件路径,创建一个空的文件
    3.会把FileOutputStream对象指向创建好的文件

写入数据的原理(内存-->硬盘)
    java程序-->JVM(Java虚拟机)-->OS(操作系统)-->OS调用写数据的方法-->把数据写入到文件中

4.字节输出流的使用步骤(重点)

1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的地

2.调用FileOutputStream对象中的方法write,把数据写入到文件中

3.释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序的效率)

5.一次写多个字节的方法

5.1 public void write(byte[] b)

public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流

一次写多个字节:

    如果写的第一个字节是正数(0-127),那么显示的时候会查询ASCII表
    
    如果写的第一个字节是负数,那么第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认码表(GBK)

5.2 public void write(byte[] b, int off, int len)

public void write(byte[] b, int off, int len):把字节数组的一部分写入到文件中

从指定的字节数组写入len字节,从偏移量off开始输出到此输出流

int off:数组的开始索引
int len:写几个字节

5.3 写入字符串的方法

可以使用String类中的方法把字符串,转换为字节数组

byte[] getBytes():把字符串转换为字节数组

6.追加写/续写

追加写/续写:使用两个参数的构造方法

    FileOutputStream(String name, boolean append) 创建一个向具有指定name的文件中写入数据的输出文件流
    
    FileOutputStream(File file, boolean append) 创建一个向指定File对象表示的文件中写入数据的文件输出流
    
    参数:
    
        String name, File file:写入数据的目的地
        
        boolean append:追加写开关
            true:创建对象不会覆盖原文件,继续在文件末尾追加写数据
            false:创建一个新文件,覆盖源文件

写换行:写换行符号

    Windows:\r\n
    Linux:/n
    mac:/r

三、字节输入流

1.java.io.InputStream:字节输入流

此抽象类是表示字节输入流的所有类的超类/父类,定义了所有子类共性的方法:

int read() 从输入流中读取数据的下一个字节,【一次读取一个字节】

int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中

void close() 关闭此输入流并释放与该流关联的所有系统资源

2.java.io.FileInputStream extends InputStream

FileInputStream:文件字节输入流
作用:把硬盘文件中的数据,读取到内存中使用

构造方法:

FileInputStream(String name)

FileInputStream(File file)

参数:读取文件的数据源
    String name:文件的路径
    File file:文件
    
构造方法的作用;
    1.会创建一个FileInputStream对象
    2.会把FileInputStream对象指定构造方法中要读取的文件

读取数据的原理(硬盘 --> 内存)
    java程序 --> JVM --> OS --> OS读取数据的方法 --> 读取文件

3.字节输入流的使用步骤

1.创建FileInputStream对象,构造方法中绑定要读取的数据源

2.使用FileInputStream对象中的方法read,读取文件

3.释放资源

注意事项:
    使用While循环的时候,必须使用一个变量来接收读取到的字节

4.布尔表达式(len = fis.read()) != -1

布尔表达式(len = fis.read()) != -1 有三层含义:

    1.fis.read():读取一个字节,read方法读完一个字节后,会把指针指向下一个字节
    
    2.len = fis.read():把读取到的字节赋值给变量len
    
    3.(len = fis.read()) != -1:判断变量len是否不等于-1
    
注意事项:必须用一个变量来接收读到的字节

	while ((len = fis.read()) != -1){}	正确
	
	while (fis.read() != -1){}	错误

5.字节输入流一次读取多个字节的方法

int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。

明确两件事情:

1.方法的参数byte[]的作用?

	起到缓冲作用,存储每次读取到的多个字节
	
    数组的长度一般定义为1024(1kb)或1024的整数倍
    
2.方法的返回值int是什么?

    每次读取到的有效字节个数

String类的构造方法

String(byte[] bytes): 把字节数组转换为字符串

String(byte[] bytes, int offset, int length): 把字节数组的一部分转换为字符串, offset: 数组的开始索引, length: 转换的字节个数

一次读取多个字节的原理:

1.首先创建一个流对象,指向要读取的文件,即b.txt

2.java程序调用JVM,JVM在调用OS,OS在调用方法读取文件中的内容

3.创建了一个数组,长度是2,默认值为[0, 0],len表示读取的有效字节个数

4.读取文件过程

    第一次读取:read方法指针指向A,数组长度为2,所以读取AB,覆盖默认值00,输出AB,len有效字节个数为2
    
    第二次读取:read方法指针指向C,数组长度为2,所以读取CD,覆盖原来的AB,输出CD,len有效字节个数为2
    
    第三次读取:read方法指针指向E,数组长度为2,但后边是结束标记,所以E覆盖原来的C,输出ED,len有效字节个数为1
    
    第四次读取:read方法指针指向结束标记,没有读到数据,返回-1
    
5.数组的作用:缓冲作用,存储读取到的多个字节

6.文件复制

6.1文件复制的原理

原理即一读一写,所有的文件都是以字节形式保存在电脑中的,例如音频,图片,视频等,所以可以通过字节流进行相关操作。

6.2文件复制的步骤

1.创建一个字节输入流对象,构造方法中绑定要读取的数据源

2.创建一个字节输出流对象,构造方法中绑定要写入的目的地

3.使用字节输入流中的方法read读取文件

4.使用字节输出流中的方法write把读取到的字节写入到目的地文件中

5.释放资源

注意事项:
   先关闭写的流,后关闭读的流。因为如果写完了,肯定是读取完毕了

四、字符输入流

1.使用字节流读取中文文件

1个中文,采用不同编码格式,占用字节数量不一样:

   GBK:占用两个字节
   
   UTF-8:占用3个字节

2.java.io.Reader:字符输入流

是字符输入流的最顶层的父类,定义了一些共性的成员方法,是一个抽象类。

共性的成员方法:

int read() 读取单个字符并返回。

int read(char[] cbuf) 一次读取多个字符,将字符读入数组

void close()    关闭该流并释放与之关联的所有资源

3.java.io.FileReader extends InputStreamReader extends Reader

FileReader:文件字符输入流

作用:把硬盘文件中的数据以字符的方式读取到内存中

构造方法:

FileReader(String fileName)

FileReader(File file)

参数:读取文件的数据源
    String fileName:文件的路径
    File file:一个文件
    
FileReader构造方法的作用:
    1.创建一个FileReader对象
    2.会把FileReader对象指向要读取的文件

4.字符输入流的使用步骤

1.创建FileReader对象,构造方法中绑定要读取的数据源

2.使用FileReader中的方法read读取文件

3.释放资源

五、字符输出流

1.java.io.Writer:字符输出流

是所有字符输出流的最顶层的父类,是一个抽象类。

共性的成员方法:

void write(int c) 写入单个字符

void write(char[] cbuf) 写入字符数组

void write(char[] cbuf, int off, int len) 写入字符数组的一部分,off数组的开始索引,len写的字符个数

void write(String str) 写入字符串

void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数

void flush() 刷新该流的缓冲

void close() 关闭此流,但要先刷新它

2.java.io.FileWriter extends OutputStreamWriter extends Writer

FileWriter:文件字符输出流

作用:把内存中的字符数据写入到文件中

FileWriter的构造方法:

FileWriter(File file) 根据给定的File对象构造一个FileWriter对象

FileWriter(String fileName) 根据给定的文件名构造一个FileWriter对象

参数:写入数据的目的地

    File file:一个文件
    
    String fileName:一个路径
    
构造方法的作用:

    1.会创建一个FileWriter对象
    
    2.会根据构造方法中传递的文件/文件路径,创建一个文件
    
    3.会把FileWriter对象指向创建好的文件

3.字符输出流的使用步骤(重点)

1.创建FileWriter对象,构造方法中绑定要写入数据的目的地

2.使用FileWriter中的方法write,把数据写入到内存缓冲区中(有一个字符转换为字节的过程,因为计算机中存储的都是字节)

3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中

4.释放资源(会先把内存缓冲区中的数据刷新到文件中,所以第3步也可以不写)

4.字节输出流 VS. 字符输出流

字节输出流是直接将数据写入到文件中

字符输出流是将数据先写入到内存缓冲区中,在刷新到文件中

fw.close(); 

	对于字节输出流来说,没有该语句也可以将数据写入文件;
	
	但是对于字符输出流来说,没有该语句,就无法写入,因为数据在内存缓冲区中,而不是直接写入到文件

5.flush方法和close方法的区别

flush:刷新缓冲区,流对象可以继续使用

close:先刷新缓冲区,然后通知系统释放资源,流对象不可以再被使用了。close方法之后,流已经关闭了,已经从内存中消失了,流就不能再继续使用了

6.字符输出流写数据的其他方法

void write(char[] cbuf) 写入字符数组

void write(char[] cbuf, int off, int len) 写入字符数组的一部分,off数组的开始索引,len写的字符个数

void write(String str) 写入字符串

void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数

7.续写和换行

续写/追加写:使用两个参数的构造方法

FileWriter(String fileName, boolean append)

FileWriter(File file, boolean append)

参数:
    String fileName, File file:写入数据的目的地
    boolean append:续写开关 true:不会创建新的文件覆盖源文件,可以续写; false:创建新的文件覆盖源文件

换行:换行符号

Windows:\r\n
Linux:/n
Mac:/r

六、处理流中的异常

1.JDK1.7之前

使用try catch finally 处理流中的异常

格式:

try{
    可能会产生异常的代码
}catch(异常类变量 变量名){
    异常的处理逻辑
}finally{
    一定会执行的代码
    一般资源释放代码写在这里
}

2.JDK7的新特性

在try的后边可以增加一个括号(),括号中可以定义流对象

那么这个流对象的作用域就在try中有效

try中的代码执行完毕,会自动把流对象释放,不用写finally

格式:

try(定义流对象;定义流对象...){
    可能会产生异常的代码
}catch(异常类变量 变量名){
    异常处理逻辑
}

3.JDK9新特性

try的前边可以定义流对象

在try后边的()中可以直接引入流对象的名称(变量名)

在try代码执行完毕之后,流对象也可以释放掉,不用写finally

格式:

A a = new A();
B b = new B();
try(a; b){
    可能会出现异常的代码
}catch(异常类变量 变量名){
    异常处理逻辑
}

七、java.util.Properties集合

1.概述

java.util.Properties extends Hashtable<k, v> implements Map<k, v>

Properties 类表示了一个持久的属性集,Properties可保存在流中或从流中加载。

Properties集合是一个唯一和IO流相结合的集合:

可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
    
可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用

属性列表中每个键及其对应值都是一个字符串:

Properties集合是一个双列集合,key和value默认都是字符串,所以不需要再写泛型了

2.使用Properties集合存储数据,遍历取出Properties集合中的数据

Properties集合是一个双列集合,key和value默认都是字符串

Properties集合有一些操作字符串的特有方法:

Object setProperty(String key, String value) 调用Hashtable的方法put。

String getProperty(String key) 用指定的键在此属性列表中搜索属性,即通过key找到value,此方法相当于Map集合中的get(key)方法

Set<String> stringPropertyNames() 返回此属性列表中的键集;其中该键及其对应值是字符串,此方法相当于Map集合的keySet方法

3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储

void store(OutputStream out, String comments)

void store(Writer writer, String comments)

参数:

    OutputStream out:字节输出流,不可以写中文
    
    Writer writer:字符输出流,可以写中文
    
    String comments:注释,用来解释说明保存的文件是做什么用的
            		 注意,注释不能使用中文,会产生乱码,因为注释默认采用的是Unicode编码,而系统采用的是GBK编码
                     一般使用""空字符串

使用步骤:

1.创建Properties集合对象,添加数据

2.创建字节输出流或者字符输出流对象,构造方法中绑定要输出的目的地

3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储

4.释放资源

4.使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用

void load(InputStream inStream)
void load(Reader reader)
参数:
    InputStream inStream:字节输入流,不能读取含有中文的键值对
    Reader reader:字符输入流,可以读取含有中文的键值对

使用步骤:

1.创建Properties集合对象

2.使用Properties集合对象中的方法load读取保存键值对的文件

3.遍历Properties集合

注意事项:

	1.存储键值对的文件中,键与值默认的连接符号可以使用=,空格(其他符号)
	
	2.存储键值对的文件中,可以使用#进行注释。被注释的键值对不会再被读取
	
	3.存储键值对的文件中,键与值默认都是字符串,不用再加引号了
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值