一、字节缓冲区流的概述和使用
缓冲流的作用是什么?为了提高IO流的读写效率
缓冲流使用的是哪两个流对象?
BufferedInputStream : 输入
常见成员方法:
intread() : 一次读取一个字节
intread(byte[] bys) : 一次读取一个字节数组
BufferedOutputStream : 输出
常见成员方法:
write(inti) : 写出单个字节
write(byte[]bys) : 写出一个字节数组
write(byte[]bys, int off, int len) : 写出字节数组的一部分
真正与文件产生关联的是那个流对象?
FileInputStream, FileOutputStream
因为缓冲流仅仅是对普通字节流的一个包装.二、字节流四种方式复制AVI并测试效率
基本字节流一次读写一个字节 共耗时:50233毫秒缓冲字节流一次读写一个字节 共耗时:197毫秒
缓冲字节流一次读写一个字节数组 共耗时:30毫秒
基本字节流一次读写一个字节数组 共耗时:79毫秒
三、转换流出现的原因
为什么要有转换流?A. 可以根据指定的编码表去读写字符 ->解决中文乱码问题(他是字符流的一种)
B. 可以将字节流转换为字符流进行操作 ->可以对于纯文本文件的操作, 变得更加方便.
细节:
GBK: 一个中文占用2个字节
UTF-8: 一个中文占用3个字节
非中文字符 : 占用1个字节
注意: 一般来说, 中文的字符, 都是以负数的字节进行存储.
但是也有一种现象, 第一个字节是负数,第二个字节是正数.
无论是怎样的编码表怎样的排列方式, 第一个字节肯定是负数.
四、编码表概述和常见编码表
编码表:由字符及其对应的数据组成的一张表
ASCII:
‘a’ 97
‘A’ 65
‘0’ 48
常见的编码表:
ASCII: 美国标准信息交换码, 用一个字节的7位表示数据
ISO-8859-1: 欧洲码表, 用一个字节的8位表示数据, 兼容ASCII
GB2312: 中文码表, 兼容ASCII
-----------------------------------------------------------
GBK : 中文码表的升级版, 融合了更多的中文文字符号, 兼容ASCII
UTF-8: 是一种可变长度的字符编码, 用1-3个字节表示数据, 又称为万国码, 兼容ASCII
用在网页上可以统一页面中的中文简体繁体和其他语言的显示.
乱码问题的产生:
1. 使用字节流读取数据, 拼接的时候出现问题.
2. 使用不同的编码表进行读写数据
五、String类中的编码和解码问题
编码把看得懂的变成看不懂的
public byte[] getBytes(StringcharsetName) throws UnsupportedEncodingException
使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
getByte(): 根据平台默认字符集进行编码
Strings = " 你好";
//[-60, -29, -70, -61]
byte[]bys = s.getBytes()
getByte(StringchatsetName) : 根据传入的编码表, 进行编码
Stringss = " 你好";
byte[]byse = ss.getBytes("utf-8");
//[-28, -67, -96, -27, -91, -67]
解码
把看不懂的变成看得懂的
public String(byte[] bytes,String charsetName)
通过使用指定的 charset解码指定的 byte 数组,构造一个新的 String。
重点强调 : 编码和解码的方式需要一致
String类中编码和解码的方法
编码:
getBytes(); --> 按照平台默认码表编码
getBytes("UTF-8") --> 按照指定的编码表进行编码
解码:
newString(byte[] bys); 根据平台默认编码表, 进行解码
newString(byte[] bys, String charsetname); 根据传入的编码表, 进行解码
Stringss = new String(bys,"UTF-8") --> 根据传入的字节数组和字符集解码
六、转换流中的编码和解码问题
转换流的构造方法OutputStreamWriter 字符输出流
publicOutputStreamWriter(OutputStream out)
根据默认编码把字节流的数据转换为字符流
publicOutputStreamWriter(OutputStream out,String charsetName)
根据指定编码把字节流数据转换为字符流
InputStreamReader 字符输入流
publicInputStreamReader(InputStream in)
用默认的编码读数据
publicInputStreamReader(InputStream in,String charsetName)
需求: 以UTF-8编码的格式写出 “你好”到文件中, 并将数据正确的读取出来打印在控制台
分析:
第一步: 创建OutputStreamWriter关联文件, 并在构造方法中指定编码表
第二步: 调用writer方法写出字符串
第三步: 创建InputStreamReader关联文件, 并在构造方法中指定码表进行读取
第四部: 调用read方法读取数据, 打印在控制台
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo01_Buffer {
public static void main(String[] args) throws IOException {
method01();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy2.txt"));
int i = 0;
while((i = bis.read())!=-1){
bos.write(i);
}
bis.close();
bos.close();
}
private static void method01() throws FileNotFoundException, IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.txt"));
byte[] bytes = new byte[2048];
int len = 0;
while((len = bis.read(bytes)) != -1){
bos.write(bytes, 0, len);
}
bis.close();
bos.close();
}
}
七、OutputStreamWriter写数据的5种方式
public void write(int c):写一个字符public void write(char[] cbuf):写一个字符数组
public void write(char[] cbuf,intoff,int len):写一个字符数组的一部分
public void write(String str):写一个字符串
public void write(String str,int off,intlen):写一个字符串的一部分
八、InputStreamReader读数据的2种方式
public int read():一次读取一个字符public int read(char[] cbuf):一次读取一个字符数组
九、字符流的练习之复制Java文件
需求:把当前项目目录下的StringDemo.java内容复制到当前项目目录下的Copy.java中import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo02_FileRw {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
char[] c = new char[2048];
int len;
while ((len = fr.read(c)) != -1) {
fw.write(new String(c, 0, len));
}
fr.close();
fw.close();
}
}
十、字符流的练习之复制Java文件改进版
flush和close方法的区别总结:
flush: 用于将缓冲区中的数据刷出到文件中.
调用完毕后, 可以继续写出数据.
close: 用于关闭流释放资源的, 但是如果关闭的是字符流, 那么会将缓冲区中的数据刷出到文件, 然后再进行关闭.
colse 方法调用结束, 不能再次写出数据
字符输出流在写出数据的时候, 如果没有调用close方法或者是flush方法的话,那么数据将不会写出到目标文件中
十一、字符缓冲区流的概述和使用
字符缓冲流使用的是哪两个类?总结:
1. 输入: BufferedReader
2. 输出: BufferedWriter
十二、字符缓冲区流的特殊功能
readLine()方法的作用是?newLine()方法的作用是?
总结:
1. 一次读取一行字符串, 但是不会读取到回车换行符, 文件的末尾结束标记为null
2. 用于写出回车换行, 但是具有跨平台性
十三、字符缓冲区流的特殊功能复制Java文件
注意: readLine方法在读取的时候,不会读取到回车换行符
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo03_Line {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("c.txt"));
String line;
while((line = br.readLine()) != null){
bw.write(line);
bw.newLine();
}
br.close();
bw.close();
}
}
十四、字符流的练习之5种方式复制文本文件
基本字符流一次读写一个字符基本字符流一次读写一个字符数组
缓冲字符流一次读写一个字符
缓冲字符流一次读写一个字符数组
缓冲字符串一次读写一个字符串
十五、字符流的练习之把集合中的学生对象数据存储到文本文件
需求:把ArrayList集合中的学生数据存储到文本文件
每一个学生数据作为文件中的一行数据
定义一个学生类。
学生:
学号,姓名,年龄,所在城市
it001,张曼玉,35,北京
it002,王祖贤,33,上海
it003,林青霞,30,西安
分析:
A: 创建集合对象
B:创建学生对象
C:把学生对象添加到集合中
D:创建字符缓冲输出流对象
E:遍历集合,得到每一个学生对象,然后把该对象的数据拼接成一个指定格式的字符串写到文本文件
F:释放资源
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import bean.Student;
public class Demo01_ListToFile {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("Student.txt"));
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("张三","a001", 21, "北京"));
list.add(new Student("李四","a002", 22, "上海"));
list.add(new Student("王五","a003", 23, "广州"));
list.add(new Student("赵六","a004", 24, "深圳"));
for (Student stu : list) {
StringBuilder sb = new StringBuilder();
sb.append(stu.getName()).append(",").append(stu.getId()).append(",").
append(stu.getAge()).append(",").append(stu.getAddress());
bw.write(sb.toString());
bw.newLine();
}
bw.close();
}
}
十六、字符流的练习之把文本文件中的学生对象数据读取到集合
需求:从文本文件中读取学生数据到ArrayList集合中,并遍历集合
每一行数据作为一个学生元素
it001, 张曼玉,35,北京
这里我们要使用String类中的一个方法:split()
分析:
A:创建字符缓冲输入流对象
B:创建集合对象
C:读取数据,每一次读取一行数据,把该行数据想办法封装成学生对象,并把学生对象存储到集合中
D:释放资源
E:遍历集合
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import bean.Student;
public class Demo02_FileToList {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("Student.txt"));
ArrayList<Student> list = new ArrayList<>();
String line;
while((line = br.readLine()) != null){
String[] sArr = line.split(",");
list.add(new Student(sArr[0],sArr[1],Integer.parseInt(sArr[2]),sArr[3]));
}
for (Student student : list) {
System.out.println(student);
}
br.close();
}
}