2015-04-23
一、转换流(IO流续)
1、编码表概述
由字符及其对应的数值组成的一张表
编码
把看得懂的变成看不懂的
解码
把看不懂的变成看得懂的
常见的编码表
ASCII:用7位来表示一个数据
ISO-8859-1:在西欧使用,用8位来表示一个数据
GB2312:简体中文,使用2字节来表示一个汉字
GBK:简体中文
GB18030:简体中文,替代GBK
BIG5:繁体中文,台湾,香港使用
Unicode:国际码,统一码,用2字节表示一个数据,在Java中使用的码就是Unicode
utf-8:国际码,统一码,表示一个数据,所使用的字节数是变化的,使用1~4位字节表 示一个数据,表示一个汉字时,用3个字节。
字符串中的编码问题
编码:把看懂的数据转换成 看不懂的数据
解码:把看不懂的数据 转换成看懂的数据
解码:
public String(byte[] bytes)用系统平台默认的字符集进行解码指定的 byte 数组
public String(byte[] bytes,String charsetName) 通过指定的编码表,进行解码指定的byte数组
编码:
public byte[] getBytes() 使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
public byte[]getBytes(String charsetName) 使用指定的字符集将此String 编码为 byte序列,并将结果存储到一个新的 byte 数组中。
注:数据的编码操作要字符编码表统一
2、OutputStreamWriter 字符输出流
它是Writer的子类,Writer是字符流
publicOutputStreamWriter(OutputStream out)
publicOutputStreamWriter(OutputStream out,String charsetName)
OutputStreamWriter: 转换流
它是Writer的子类,Writer是字符流
作用: 可以将 字节流中的数据,按照指定的编码表进行数据的编码,生产的结果成为了字符流
字节流 --> 字符流
OutputStreamWriter: 字符输出流
构造方法:
public OutputStreamWriter(OutputStream out)
创建使用默认字符编码(gbk)的 OutputStreamWriter。
public OutputStreamWriter(OutputStream out,StringcharsetName)
创建使用指定字符集的 OutputStreamWriter。
3、InputStreamReader 字符输入流
publicInputStreamReader(InputStream in)
publicInputStreamReader(InputStream in,String charsetName)
4、OutputStreamWriter写数据方法
public voidwrite(int c) 写入一个字符
public voidwrite(char[] cbuf) 写入一个字符数组
public voidwrite(char[] cbuf,int startIndex,int len) 写入字符数组的一部分
public voidwrite(String str) 写入一个字符串
public voidwrite(String str,int startIndex,int len) 写入字符串的一部分
5、字符流操作要注意的问题
flush()的作用
flush()和close()的区别
flush(): 将数据缓冲区中的内容刷新到目的地文件中
close(): 在关闭之前,执行一次刷洗操作,然后关闭流,释放流所占用的资源
flush()和close()的区别?
flush()后,流没有关闭,可以继续读写数据
close()后,流关闭了,不能够继续读写数据
6、OutputStreamWriter读数据方法
public int read()
public int read(char[]cbuf)
案例:字符流复制文本文件(copyText.java)
7、便捷读写类
发现上一个版本,使用转换流太麻烦, 有没有简化的方式,应该有
大多数情况下,我们都是使用平台的默认字节集进行的编解码操作,没有必要使用转 换流,可以使用更简化的流
FileReader:用来读取字符文件的便捷类
FileWriter:用来写入字符文件的便捷类
Reader
|- InputStreamReader
|- FileReader
Writer
|- OutputStreamWriter
|- FileWriter
举例:便捷类的读写
//数据源
FileReader fr =new FileReader("面试题.txt");
//目的地
FileWriter fw =new FileWriter("copyText.txt");
//读数据
int ch = -1;
while ((ch =fr.read()) != -1) {
//写数据
fw.write(ch);
}
//关闭流
fr.close();
fw.close();
二、BufferedWriter字符缓冲输出流BufferedReader字符缓冲输入流
1、构造方法
publicBufferedWriter(Writer out)
public BufferedWriter(Writerout, int size)
2、特殊功能
BufferedWriter 字符缓冲输出流
publicvoid newLine() 根据当前的系统,写一个换行符
BufferedReader
publicString readLine():读取一行字符串, 读取到回车换行结束
当没有获取到有效数据的时候,返回null
读数据,用readLine()时,如果遍历到空时,返回null。
代码实现:
//读
public static voidreader() throws IOException {
//创建流对象
BufferedReader br= new BufferedReader(new FileReader("bw.txt"));
//读数据
String line =null;
//获取数据,赋值, 判断
while ((line =br.readLine()) != null) {
System.out.println(line);
}
// String line =br.readLine();
// System.out.println(line);
//
// line =br.readLine();
// System.out.println(line);
//
// line =br.readLine();
// System.out.println(line);
//关闭
br.close();
}
//写
public static voidwriter() throws IOException {
//创建流对象
BufferedWriter bw= new BufferedWriter(new FileWriter("bw.txt"));
//写数据
for (int i = 1; i<= 10; i++) {
bw.write("HelloWorld"+i);
bw.newLine();//写一个换行符
bw.flush();//刷新数据到目的地
}
//关闭
bw.close();
}
3、总结:字节与字符流的转换
注意:字符流只能复制文本文件,不能复制图片、视频等文件,而应该用字节流复制这些文件。
举例:
复制图片,用字节流,正确:
public static voidmethod1() throws IOException {
BufferedInputStream bis =new BufferedInputStream(new
FileInputStream("E:\\resource\\IMG_1693.jpg"));
BufferedOutputStream bos =new
BufferedOutputStream(newFileOutputStream("1693.jpg"));
//读
byte[] buffer = newbyte[1024];
int len = -1;
while ((len =bis.read(buffer)) != -1) {
//写
bos.write(buffer,0, len);
}
//关闭流
bis.close();
bos.close();
}
复制图片,用字节流,错误:
public static void method2() throws IOException {
BufferedReader br = new
BufferedReader(newFileReader("E:\\resource\\IMG_1693.jpg"));
BufferedWriter bw = newBufferedWriter(new FileWriter("1693.jpg"));
//读
String line = null;
while ((line =br.readLine()) != null) {
//写
bw.write(line);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
}
}
三、案例
1、把文本数据复制到ArrayList中
练习:把文本文件中的数据 存储到Arraylist集合中
分析:
1:创建字符输入流BufferedReader,用来读取数据
2:创建ArrayList集合,用来存储数据
3:读取File中的数据
4:把数据添加到集合
5:遍历集合中的数据
6:关闭流
代码实现:
//1:创建字符输入流BufferedReader, 用来读取数据
BufferedReader br= new BufferedReader(new FileReader("arraylist.txt"));
//2:创建ArrayList集合,用来存储数据
ArrayList<String>list = new ArrayList<String>();
//3:读取File中的数据
String line =null;
while ((line =br.readLine()) != null) {
//4:把数据添加到集合
list.add(line);
}
//5:遍历集合中的数据
for (String s :list) {
System.out.println(s);
}
//6:关闭流
br.close();
2、复制单层文件
数据源:E:\resource无子目录
目的地:NoDir
分析:
1: 封装数据源 (文件夹)
2: 封装目的地(文件夹)
3: 获取到数据源所对应的目录中,每一个File对象
4: 文件的复制
代码实现:
public class CopyDir {
public static voidmain(String[] args) throws IOException {
//1: 封装数据源 (文件夹)
File srcPath =new File("E:\\resource无子目录");
//2: 封装目的地(文件夹)
File destPath =new File("NoDir");
//创建目的地文件夹
destPath.mkdir();
//获取数据源中所有的File对象,得到每个File对象
File[] files =srcPath.listFiles();
//3: 获取到数据源所对应的目录中,每一个File对象
for (File file :files) {
//file-- E:\resource无子目录\ 小苹果.flv
//dest-- NoDir\ 小苹果.flv
Stringname = file.getName();
//4: 文件的复制
Filedest = new File(destPath, name);
copyFile(file,dest);
}
}
//文件的复制
public static voidcopyFile(File src, File dest) throws IOException {
//数据源
BufferedInputStreambis = new BufferedInputStream(new FileInputStream(src));
//目的地
BufferedOutputStreambos =new BufferedOutputStream(new FileOutputStream(dest));
//读
byte[] buffer =new byte[1024];
int len = -1;
while ((len =bis.read(buffer)) != -1) {
//写
bos.write(buffer,0, len);
}
//关闭流
bis.close();
bos.close();
}
}
3、复制多层文件夹
数据源:E:\resource
目的地:YesDir
YesDir
|- Demo.java
|- error.wav
|- 各种专治
|- [www-itcast-cn]专治各种疼痛01.mp4
分析:
1)封装数据源
2):封装目的地
3)创建目的地文件夹
4)获取到数据源中所有的File对象
5)遍历,获取到每一个File对象
6) 判断当前File对象 是否为 文件夹
是:
文件夹
递归,封装好目的地,回到步骤3
否:
文件
文件的复制
得到新文件的名称[File对象]
开始复制文件
4、学生成绩的有序存储
// 1: 创建学生集合对象, TreeSet<Student>
TreeSet<Student>ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
publicint compare(Student s1, Student s2) {
//总分
intnum = (int) (s2.sum() - s1.sum());
//语文,数学,英语
intnum2 = (int) ((num == 0) ? (s2.getChineseScore() - s1
.getChineseScore()): num);
//姓名
returnnum2;
}
});
// 2:键盘输入数据
for (int i = 0; i< 3; i++) {
Stringname = new Scanner(System.in).nextLine();
doublechineseScore = new Scanner(System.in).nextDouble();
doublemathScore = new Scanner(System.in).nextDouble();
doubleenglishScore = new Scanner(System.in).nextDouble();
// 3:创建学生对象,把键盘输入数据 复制给学生对象
Students = new Student(name, chineseScore, mathScore, englishScore);
// 4: 把学生对象元素添加到集合
ts.add(s);
}
// 6:创建一个字符输出流对象 BufferedWriter
BufferedWriter bw= new BufferedWriter(new FileWriter("score.txt"));
// 5: 遍历,得到每一个元素
for (Student s :ts) {
Stringdata = s.getName() + "\t" + s.getChineseScore() + "\t"
+s.getMathScore() + "\t" + s.getEnglishScore() + "\t"
+s.sum();
bw.write(data);
bw.newLine();
bw.flush();
}
//关闭流
bw.close();
四、行号
1、设置行号,获得行号的方法
LineNumberReader 带有行号的字符输入流
public int getLineNumber()获得当前行号。
public voidsetLineNumber(int lineNumber)设置当前行号。
代码实现:
//创建流对象
LineNumberReaderlnr = new LineNumberReader(new FileReader("面试题.txt"));
lnr.setLineNumber(100);
//读数据
String line =null;
while ((line =lnr.readLine()) != null) {
intlineNumber = lnr.getLineNumber();
System.out.println(lineNumber+": "+ line);
}
//关闭流
lnr.close();