流的概念
1.Java中几种类型的流?
- 按照流向分:输入流(inputStream);输出流(outputStream)。
- 按照处理数据的单位分:字节流(8位的字节);字符流(16位的字节)。
- 按功能分为:节点流(低级流);处理流(高级流/过滤流)
2.什么是输入输出流?
- 输入就是将数据从各种输入设备(包括文件,键盘)中读取到内存中去。
- 输出就是将数据写入到各种输出设备中(比如文件,显示器,磁盘等)
字节流和字符流
Fiel类不支持文件内容处理,如果要处理文件内容,必须要通过流的操作模式来完成。
流分为三种:
- 字节流:数据流中最小的数据单位是字节,字节型二进制数据。
- 字符流:字符型文本数据。数据流中最小的数据单位只字符,java中的字符是Unicode编码,一个字符占两个字节。
- 转换流:(加工厂)字节流和字符流之间需要通过转换流来进行转换。
为什么要有字符缓冲流?
为了提高字符流读写的效率,引入了缓冲机制,进行字符批量的读写,提高了单个字符读写的效率。 BufferedReader 用于加快读取字符的速度, BufferedWriter 用于加快写入的速度。
字符流:
//文件字符流读取
@Test
public void t2() throws IOException{
FileReader reader = new FileReader("E:\\workspcae\\javaweb\\IO-study\\data\\测试名字");
//读取字符数,对应要使用字符数组
char [] chars = new char[1024];
int len ;//读取长度也就是当前bytes的元素个数
while ((len = reader.read(chars)) != -1){
//不等于-1意味着,chars数组还有空间
String s = new String(chars,0,len);//bytes数组转String,通过String的构造方法来转
System.out.println(s);
}
}
字节流:
@Test
//二进制文件流读取操作,字节读取
public void t1() throws IOException {
InputStream fis = null;
try {
//第一种方式:使用FileInputStream绝对路径
fis = new FileInputStream("E:\\workspcae\\javaweb\\IO-study\\data\\测试名字");
//方法二:使用ClassLoader+相对路径 推荐!
// fis = this.getClass().getClassLoader().getResourceAsStream("测试名字");
//abcdefg,进行读取操作时,在read(),new String()中
// 第二个参数为:从当前位置偏移多少位
//第三个参数为:读取多长
//读取字节数
byte [] bytes = new byte[1024];
int len ;//读取长度也就是当前bytes的元素个数
while ((len = fis.read(bytes)) != -1){
//不等于-1意味着,bytes数组还有空间
String s = new String(bytes,0,len);//bytes数组转String,通过String的构造方法来转
System.out.println(s);
}
//流使用完之后,都需要进行释放流的操作
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fis !=null){
//不等于null就关闭流
fis.close();
}
}
}
为什么需要有字节缓冲流?
答:当我们用read()读取文件时,每读一个字节,访问一次硬盘,效率很低。当文件过大时,操作 起来也不是很方便。因此我们需要用到buffer缓存流,当创建buffer对象时,会创建一个缓冲区 数组。当我们读一个文件时,先从硬盘中读到缓冲区,然后直接从缓冲区输出即可,效率会更高。
转换流:
字节流到字符流转换,转换流+缓冲流,这个方法的效率比较高,工作中常用
//字节流到字符流转换,转换流+缓冲流
//这个方法的效率比较高,工作中常用
@Test
public void t3() throws IOException {
FileInputStream fis= new FileInputStream("E:\\workspcae\\javaweb\\IO-study\\data\\测试名字");
//此处得到文件输入流,他是属于字节流的,需要转换为字符流的话,则需要使用转换流InputStreamReader
//转换流还提供了编码格式的选择,要选择文件的编码方式。
//字节字符转换流,指定编码格式,如果java编码目标文件的编码格式不一致,就会出现乱码
InputStreamReader isr= new InputStreamReader(fis);
//使用缓冲的字符流再将InputStreamReader转换流包装
BufferedReader br = new BufferedReader(isr);
String line;//文本型数据按行读取
while ((line = br.readLine()) != null){
System.out.println(line);
}
}
缓冲输入字节流的方式得到文本信息:
//缓冲输入字节流的方式得到文本信息
@Test
public void t4() throws IOException {
FileInputStream fis= new FileInputStream("E:\\workspcae\\javaweb\\IO-study\\data\\测试名字");
//此处得到文件输入流,他是属于字节流的,需要转换为字符流的话,则需要使用转换流InputStreamReader
//转换流还提供了编码格式的选择,要选择文件的编码方式。
BufferedInputStream bis = new BufferedInputStream(fis);//缓冲输入字节流
//读取字节数
byte [] bytes = new byte[1024];
int len ;//读取长度也就是当前bytes的元素个数
while ((len = bis.read(bytes)) != -1){
//不等于-1意味着,bytes数组还有空间
String s = new String(bytes,0,len);//bytes数组转String,通过String的构造方法来转
System.out.println(s);
}
}
字节流与字符流对比(面试题):
- 字节流操作的基本单位是1个字节;字符流操作的基本单位为2个字节的Unicode字符,分别为操作字符,字符数组或字符串。所以字符流是由java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以他对多国语言支持性比较好。
- 字节流在操作时本身不会用到缓存区,是与文件本身直接操作的;而字符流在操作的时候使用到缓冲区的。字符流使用字节流读到一个或多个字节时,会先去查指定的编码表,再将查到的字符返回。
- 所有文件的存储都是字节存储的,在磁盘上保存的是字节。
- 字节流可以处理所有类型的数据:如图片,MP3,AVI,视频等,而字符流只能处理字符型数据。所以只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都是字节流。
- 在使用字节流操作中,即使没有关闭资源(close方法),也能输出;而字符流不使用close方法的话,就不会输出任何内容。
字符字节转换流:
有时我们会需要字节流和字符流之间的转换,因为这是两种不同的流,所以在转换时需要用到OutputStreamWriter和InputStreamRread。
InputStreamRread是Reader的子类,将输入的字节流转换成字符流。
OutputStreamWriter是Writer的子类,将输出的字符流转换成字节流。
字节流如何转换为字符流?(面试题)
补充:Class和Classload:
- 项目通过相对路径获取资源文件时,主要使用ClassLoader方法获取,不使用File和Class
@Test
public void t1(){
//通过class获取资源或者IO流,是以当前class编译类的路径作为相对位置
InputStream is= this.getClass().getResourceAsStream("../测试名字2");
System.out.println(is);
//通过ClassLoader获取资源或者IO流,是以整个项目编译的根路径作为相对位置
//项目通过相对路径获取资源文件时,主要使用ClassLoader方法获取,不使用File和Class
InputStream is2= this.getClass().getClassLoader().getResourceAsStream("测试名字22");
System.out.println(is2);
}
IDEA编译代码的路径: