黑马程序员—Java基础—IO流—字符流

时间:2023-02-16 13:07:34

-----------android培训java培训、java学习型技术博客、期待与您交流!------------ 

字符流


转换流:

转换流出现的原因及思想

由于字节流操作中文不是特别方便,所以,java就提供了转换流。

字符流=字节流+编码表。

编码表概述和常见的编码表

ASCII:美国标准信息交换码。

用一个字节的7位可以表示。

ISO8859-1:拉丁码表。欧洲码表

用一个字节的8位表示。

GB2312:中国的中文编码表。

GBK:中国的中文编码表升级,融合了更多的中文文字符号。

GB18030:GBK的取代版本

BIG-5码 :通行于*、香港地区的一个繁体字编码方案,俗称“大五码”。

Unicode:国际标准码,融合了多种文字。

所有文字都用两个字节来表示,Java语言使用的就是unicode

UTF-8:最多用三个字节来表示一个字符。

字符串中的编码问题

编码

// String --byte[]  把看得懂的变成看不懂的

解码

// byte[] –String  把看不懂的变成看得懂的

编码解码的格式要保持一致

编、解码问题 24行 JavaRaw
  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.UnsupportedEncodingException;import java.util.Arrays;
/* * String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组 * byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组 */public class StringDemo {public static void main(String[] args) throws UnsupportedEncodingException {String s = "陈奕迅";
// String -- byte[]byte[] bys = s.getBytes(); // [-60, -29, -70, -61]// byte[] bys = s.getBytes("GBK");// [-60, -29, -70, -61]// byte[] bys = s.getBytes("UTF-8");// [-28, -67, -96, -27, -91, -67]System.out.println(Arrays.toString(bys));
// byte[] -- StringString ss = new String(bys); // 陈奕迅// String ss = new String(bys, "GBK"); //陈奕迅// String ss = new String(bys, "UTF-8"); // ???System.out.println(ss);}}

转换流概述

OutputStreamWriter字符输出流

publicOutputStreamWriter(OutputStream out)  根据默认编码把字节流的数据转换为字符流

publicOutputStreamWriter(OutputStream out,String charsetName)  根据指定编码把字节流数据转换为字符流

InputStreamReader字符输入流

publicInputStreamReader(InputStream in)  用默认的编码读取数据

publicInputStreamReader(InputStream in,String charsetName)  用指定的编码读取数据


 转换输出流 21行 JavaRaw
  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;

public class OutputStreamWriterDemo {public static void main(String[] args) throws IOException {// 创建对象// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(// "osw.txt")); // 默认GBK// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(// "osw.txt"), "GBK"); // 指定GBKOutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "UTF-8"); // 指定UTF-8// 写数据osw.write("陈奕迅");
// 释放资源osw.close();}}
 转换输入流 28行 JavaRaw
  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;

public class InputStreamReaderDemo {public static void main(String[] args) throws IOException {// 创建对象// InputStreamReader isr = new InputStreamReader(new FileInputStream(// "osw.txt"));
// InputStreamReader isr = new InputStreamReader(new FileInputStream(// "osw.txt"), "GBK");
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "UTF-8");
// 读取数据// 一次读取一个字符int ch = 0;while ((ch = isr.read()) != -1) {System.out.print((char) ch);}
// 释放资源isr.close();}}

转换流的简化写法

转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类。

FileWriter

FileReader
转换流的简写 29行 JavaRaw
  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyFileDemo2 {public static void main(String[] args) throws IOException {// 封装数据源FileReader fr = new FileReader("a.txt");// 封装目的地FileWriter fw = new FileWriter("b.txt");
// 一次一个字符// int ch = 0;// while ((ch = fr.read()) != -1) {// fw.write(ch);// }
// 一次一个字符数组char[] chs = new char[1024];int len = 0;while ((len = fr.read(chs)) != -1) {fw.write(chs, 0, len);fw.flush();}
// 释放资源fw.close();fr.close();}}

字符缓冲流

字符流的缓冲区——BufferedReader和BufferedWriter

缓冲区的出现:提高了流的读写效率,所以在缓冲区创建前,要先创建流对象。即先将流对象初始化到构造函数中。 

缓冲技术原理:此对象中封装了数组,将数据存入,再一次性取出。

写入流缓冲区BufferedWriter的步骤:

        1、创建一个字符写入流对象。

        FileWriterfw=newFileWriter("buf.txt");

        2、为了提高字符写入流效率。加入缓冲技术。只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。

        BufferedWriterbufw =new BufferedWriter(fw);

         3、调用write方法写入数据到指定文件

        bf.write("adfg");

         记住,只要用到缓冲区,就要记得刷新。(关闭流同样会刷新,但为了排除意外事故,保证数据存在,建议写入一次就刷新一次)

       bf.flush();

        4、其实关闭缓冲区,就是在关闭缓冲区中的流对象。

小知识:BufferedWriter缓冲区中提供了一个跨平台的换行符:newLine();可以在不同操作系统上调用,用作数据换行。bf.newLine();

读取流缓冲区BufferedReader

        该缓冲区提供了一个一次读一行的方法readLine,方便于堆文本数据的获取,当返回null时表示读到文件末尾。readLine方法返回的时候,只返回回车符之前的数据内容。并不返回回车符。

readLine方法原理:

        无论是读一行。或者读取多个字符。其实最终都是在在硬盘上一个一个读取。所以最终使用的还是read方法一次读一个的方法。

步骤:

       1、创建一个读取流对象和文件相关联

        FileReader fr=newFileReader("buf.txt");

       2、为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲区对象的构造函数。

         BufferedReader bufr=new BufferedReader(fr);

       3、调用该缓冲区提供的readLine方法一行一行读取,如果到达文件末尾,则返回null

        如: String s=bufr.readLine();

       4、关闭流资源

 字符缓冲区的特殊方法 49行 JavaRaw
  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.io.IOException;
/* * 字符缓冲流的特殊方法: * BufferedWriter: * public void newLine():根据系统来决定换行符 * BufferedReader: * public String readLine():一次读取一行数据 * 包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null */public class BufferedDemo {public static void main(String[] args) throws IOException {// write();read();}
private static void read() throws IOException {// 创建字符缓冲输入流对象BufferedReader br = new BufferedReader(new FileReader("bw2.txt"));
// public String readLine():一次读取一行数据// String line = br.readLine();// System.out.println(line);// line = br.readLine();// System.out.println(line);
String line = null;while ((line = br.readLine()) != null) {System.out.println(line);}//释放资源br.close();}
private static void write() throws IOException {// 创建字符缓冲输出流对象BufferedWriter bw = new BufferedWriter(new FileWriter("bw2.txt"));for (int x = 0; x < 10; x++) {bw.write("hello" + x);// bw.write("\r\n");bw.newLine();bw.flush();}bw.close();}
}
IO练习:

复制单极文件夹中指定文件并修改文件名称

 复制多级文件并修改.java文件为.txt文件 69行 JavaRaw
  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;/* * 复制单极文件夹中指定文件并修改文件名称 */public class Test1 {public static void main(String[] args) throws IOException{//源文件File src = new File("E:\\za");//目标文件File des = new File("D:\\");//判断目标文件是否存在,不存在创建if (des.exists()) {des.mkdirs();}//调用方法复制文件夹copyFolder(src, des);}//定义用来复制文件夹的方法public static void copyFolder(File src,File des)throws IOException{//判断源文件是不是文件if(src.isFile()){//是的话获取名称String name=src.getName();//判断名称是不是符合指定文件格式if(name.endsWith(".java")){//如果是改名name=name.replace(".java", ".txt");}//重新命名新目标文件File newDes=new File(des,name);//调用复制文件的方法copy(src,newDes);}else {//不是的话获取名称String name=src.getName();//创建新的目标文件夹File newDes=new File(des,name);newDes.mkdirs();//获取源文件下的文件数组File[] files=src.listFiles();for(File file:files){//递归调用copyFolder(file,newDes);}}}//定义方法用来复制文件public static void copy(File src,File des)throws IOException{//高效字节输入流,指向源文件BufferedInputStream bis=new BufferedInputStream(new FileInputStream(src));//高效字节输出流,指向目标文件BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(des));//一次读取一个数组byte[] by=new byte[1024];int len=0;while((len=bis.read(by))!=-1){//一次写出一个数组的一部分bos.write(by,0,len);}//释放资源bis.close();bos.close();}}

流的操作规律:

1,明确源和目的。

       数据源:就是需要读取,可以使用两个体系:InputStreamReader

       数据汇:就是需要写入,可以使用两个体系:OutputStreamWriter

2,操作的数据是否是纯文本数据?

       如果是:数据源:Reader

                数据汇:Writer

       如果不是:数据源:InputStream

                   数据汇:OutputStream

3,虽然确定了一个体系,但是该体系中有太多的对象,到底用哪个呢?

       明确操作的数据设备。

       数据源对应的设备:硬盘(File),内存(数组),键盘(System.in)

       数据汇对应的设备:硬盘(File),内存(数组),控制台(System.out)

4,需要在基本操作上附加其他功能吗?比如缓冲。

       如果需要就进行装饰。以提高效率!

IO体系

黑马程序员—Java基础—IO流—字符流

-----------android培训java培训、java学习型技术博客、期待与您交流!------------