JavaSE进阶——Day11 字节流、打印流
该篇主要讲解Java中字节流、打印流
符输出流
字节流读中文出现码的原码
- 因为字节流一次读一个字节,而不管GBK还是UTF-8一个中文都是多个字节,用字节流每次只能读其中的一部分,所以就会出现乱码问题
字符流输出介绍
Writer类
FileWriter的成员
构造方法 :
- public FileWriter(File file) : 往指定的File路径中写入数据
- public FileWriter(String fileName) : 往指定的String路径中写入数据
成员方法 :
| void write(int c) | 写一个字符 |
| :———————————————————-: | :—————————: |
| void write(char[] cbuf) | 写入一个字符数组 |
| void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
| void write(String str) | 写一个字符串 |
| void write(String str, int off, int len) | 写一个字符串的一部分 || flush() | 刷新流,还可以继续写数据 |
| :——-: | :—————————————————————————————: |
| close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
FileWriter写数据的步骤
创建字符输出流对象
- 注意事项: 如果文件不存在,就创建。但是要保证父级路径存在。 如果文件存在就清空
写数据
- 注意事项: 写出int类型的整数,实际写出的是整数在码表上对应的字母。 写出字符串数据,是把字符串本身原样写出。
释放资源
- 注意事项: 每次使用完流必须要释放资源。
```
package com.itheima.writer_demo;import java.io.FileWriter;
import java.io.IOException;/*
Writer类 : 写入字符流的最顶层的类 , 是一个抽象类 ,不能实例化 需要使用其子类FileWriter类 FileWriter类 : 用来写入字符文件的便捷类 构造方法 : public FileWriter(File file) : 往指定的File路径中写入数据 public FileWriter(String fileName) : 往指定的String路径中写入数据 成员方法 void write•(int c) 写一个字符 void write•(char[] cbuf) 写入一个字符数组 void write•(char[] cbuf, int off, int len) 写入字符数组的一部分 void write•(String str) 写一个字符串 void write•(String str, int off, int len) 写一个字符串的一部分 flush() 刷新流,还可以继续写数据 close() 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
*/
public class WriterDemo1 {public static void main(String[] args) throws IOException { // 创建字符输出流对象 // 如果文件不存在会创建一个空的文件 // 如果文件存在 , 会把文件中的内容清空 FileWriter fw = new FileWriter("day12_demo\\charstream2.txt"); // 写数据 fw.write('a'); fw.write('b'); // 刷新流 , 把流中的数据刷到硬盘中 , 刷新之后可以继续写数据 // fw.flush(); // 释放资源 // 关闭流 , 但是会先刷新流 fw.close(); // 一旦关闭流无法写数据 // fw.write('c'); }
}
1
package com.itheima.writer_demo;
import java.io.FileWriter;
import java.io.IOException;/*
Writer类 : 写入字符流的最顶层的类 , 是一个抽象类 ,不能实例化 需要使用其子类FileWriter类 FileWriter类 : 用来写入字符文件的便捷类 构造方法 : public FileWriter(File file) : 往指定的File路径中写入数据 public FileWriter(String fileName) : 往指定的String路径中写入数据 成员方法 void write•(int c) 写一个字符 void write•(char[] cbuf) 写入一个字符数组 void write•(char[] cbuf, int off, int len) 写入字符数组的一部分 void write•(String str) 写一个字符串 void write•(String str, int off, int len) 写一个字符串的一部分 flush() 刷新流,还可以继续写数据 close() 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
*/
public class WriterDemo2 {public static void main(String[] args) throws IOException { // 创建字符输出流对象 FileWriter fw = new FileWriter("day12_demo\\charstream2.txt"); // 写数据
// void write•(int c) 写一个字符
// fw.write(‘a’);
// fw.write(‘b’);
// fw.write(‘c’);// void write•(char[] cbuf) 写入一个字符数组
char[] chs = {'a', 'b', 'c', 'd', 'e'};
// fw.write(chs);
// void write•(char[] cbuf, int off, int len) 写入字符数组的一部分
// fw.write(chs , 2 , 3);// void write•(String str) 写一个字符串
// fw.write(“abcadaasda”);// void write•(String str, int off, int len) 写一个字符串的一部分
// fw.write(“abnacna”, 3, 2);// 释放资源 fw.close(); }
}
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
### 字符输出流练习
- ```
package com.itheima.writer_demo;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
/*
需求 : 将用户键盘录入的用户名和密码保存到本地实现永久化存储。
要求 : 用户名和密码在文件中各占一行
步骤:
1 用户键盘录入用户名
2 创建字符输出流对象
3 将用户名和密码写到本地文件中
*/
public class WriterTest {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
// 创建字符输出流对象
FileWriter fw = new FileWriter("day12_demo\\user.txt");
// 往文件中写入用户名和密码
fw.write(username);
// 换行
fw.write("\r\n");
fw.write(password);
// 刷新
fw.flush();
// 释放资源
fw.close();
}
}
字符输入流
字节输入流介绍
- Reader类 :
- 读取字符流的最顶层的类 , 是一个抽象类 ,不能实例化
- 需要使用其子类FileReader类
- FileReader类 :
- 用来读取字符文件的便捷类
FileReader的成员
构造方法 :
- public FileReader(File file) : 从指定的File路径中读取数据
- public FileReader(String fileName) : 从指定的String路径中读取数据
成员方法 :
- | int read() | 一次读一个字符数据 |
| :—————————-: | :——————————: |
| int read(char[] cbuf) | 一次读一个字符数组数据 |
- | int read() | 一次读一个字符数据 |
```
package com.itheima.reader_demo;import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;/*
Reader类 : 读取字符流的最顶层的类 , 是一个抽象类 ,不能实例化 需要使用其子类FileReader类 FileReader类 : 用来读取字符文件的便捷类 构造方法 : public FileReader(File file) : 从指定的File路径中读取数据 public FileReader(String fileName) : 从指定的String路径中读取数据 成员方法 : int read•() : 一次读一个字符数据 int read•(char[] cbuf) : 一次读一个字符数组数据
*/
public class ReaderDemo1 {public static void main(String[] args) throws IOException { // 创建字符输入流对象 FileReader fr = new FileReader("day12_demo\\charstream.txt"); // 一次读一个字符数据 int ch; while ((ch = fr.read()) != -1) { System.out.print((char) ch); } // 释放资源 fr.close(); }
}
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
- ```
package com.itheima.reader_demo;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
Reader类 : 读取字符流的最顶层的类 , 是一个抽象类 ,不能实例化
需要使用其子类FileReader类
FileReader类 : 用来读取字符文件的便捷类
构造方法 :
public FileReader(File file) : 从指定的File路径中读取数据
public FileReader(String fileName) : 从指定的String路径中读取数据
成员方法 :
int read•() 一次读一个字符数据
int read•(char[] cbuf) 一次读一个字符数组数据
*/
public class ReaderDemo2 {
public static void main(String[] args) throws IOException {
// 创建字符输入流对象
FileReader fr = new FileReader("day12_demo\\charstream.txt");
// 一次读一个字符数组数据
char[] chs = new char[1024];
int len;
while ((len = fr.read(chs)) != -1) {
System.out.println(new String(chs, 0, len));
}
// 释放资源
fr.close();
}
}
字符缓冲流
字符缓冲流
- BufferedWriter:可以将数据高效的写出
- BufferedReader:可以将数据高效的读入到内存
- 注意 : 字符缓冲流不具备读写功能 , 只提供缓冲区 , 真正读写还是需要依赖于构造接收的基本的字符流
- 构造方法:
- public BufferedWriter(Writer out) : 构造方法中需要接收一个基本的字符输出流
- public BufferedReader(Reader in) : 构造方法中需要接收一个基本的字符输入流
1 | package com.itheima.bufferedstream_demo; |
字符缓冲流特有的功能
BufferedWriter类
- void newLine():写一个行分隔符,会根据操作系统的不同,写入不同的行分隔符
BufferedReader类
- public String readLine() :读取文件一行数据, 不包含换行符号 , 读到文件的末尾返回null
```
package com.itheima.bufferedstream_demo;import java.io.*;
/*
1 字符缓冲流: BufferedWriter:可以将数据高效的写出 BufferedReader:可以将数据高效的读入到内存 2 字符缓冲流特有功能 BufferedWriter类 void newLine•():写一个行分隔符,会根据操作系统的不同,写入不同的行分隔符 BufferedReader类 public String readLine•() :读取文件一行数据, 不包含换行符号 , 读到文件的末尾返回null 远桥之下泛莲舟 岱岩石上松溪流 万仞翠山梨亭在 莫闻空谷声悠悠
*/
public class BufferedStreamDemo2 {public static void main(String[] args) throws IOException { // 创建高效的字符输出流对象 BufferedWriter bw = new BufferedWriter(new FileWriter("day12_demo\\abc.txt")); // void newLine•():写一个行分隔符,会根据操作系统的不同,写入不同的行分隔符 bw.write("远桥之下泛莲舟"); bw.newLine(); bw.write("岱岩石上松溪流"); bw.newLine(); bw.write("万仞翠山梨亭在"); bw.newLine(); bw.write("莫闻空谷声悠悠"); bw.flush(); // 创建高效的字符输入流对象 BufferedReader br = new BufferedReader(new FileReader("day12_demo\\abc.txt")); // public String readLine•() :读取文件一行数据, 不包含换行符号 , 读到文件的末尾返回null
// String s = br.readLine();
// System.out.println(s);
// s = br.readLine();
// System.out.println(s);
// s = br.readLine();
// System.out.println(s);
// s = br.readLine();
// System.out.println(s);
// System.out.println(“============”);
// s = br.readLine();
// System.out.println(s);
// s = br.readLine();
// System.out.println(s);// 循环改进 String line; while((line = br.readLine()) != null){ System.out.println(line); } // 释放资源 br.close(); bw.close(); }
}
1
2
3
### 字符缓冲流练习package com.itheima.bufferedstream_demo;
import java.io.*;
import java.util.Arrays;
/*
需求:读取文件中的数据 : 33 22 11 55 44
排序后 : 11 22 33 44 55 再次写到本地文件
步骤 :
1 创建高效的字符输入流对象
2 读取文件中的一行数据
3 将数据按照空格切割
4 把字符串数组转成int类型数组
5 对int类型的数组进行排序
6 创建高效的字符输出流对象
7 遍历数组,把数组中的数据写入到文件中
8 释放资源
*/
public class BufferedStreamDemo3 {
public static void main(String[] args) throws IOException {
// 1 创建高效的字符输入流对象
BufferedReader br = new BufferedReader(new FileReader(“day12_demo\sort.txt”));
// 2 读取文件中的一行数据
String line = br.readLine();
// 3 将数据按照空格切割
String[] strs = line.split(“ “);
// 4 把字符串数组转成int类型数组
int[] arr = new int[strs.length];
for (int i = 0; i < strs.length; i++) {
arr[i] = Integer.parseInt(strs[i]);
}
// 5 对int类型的数组进行排序
Arrays.sort(arr);
// 6 创建高效的字符输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter(“day12_demo\sort.txt”));
// 7 遍历数组,把数组写入到文件中
for (int i = 0; i < arr.length; i++) {
bw.write(arr[i] + “ “);
bw.flush();
}
// 8 释放资源
br.close();
bw.close();
}
}
1 |
|
package com.itheima.conversion_demo;
import java.io.*;
/*
转换流就是来进行字节流和字符流之间转换的桥梁
InputStreamReader是从字节流到字符流的桥梁
public InputStreamReader(InputStream in) : 创建一个使用默认编码的 InputStreamReader。
public InputStreamReader(InputStream in , String charsetName) : 创建使用指定编码的 InputStreamReader。
OutputStreamWriter是从字符流到字节流的桥梁
public OutputStreamWriter(OutputStream out) : 创建使用默认字符编码的 OutputStreamWriter
public OutputStreamWriter(OutputStream out, String charsetName) : 创建使用指定编码的 OutputStreamWriter。
需求1 : 使用转换流 , 把以下数据按照GBK的编码写入文件 , 在使用GBK的编码读取数据
数据如下 :
远桥之下泛莲舟
岱岩石上松溪流
万仞翠山梨亭在
莫闻空谷声悠悠
*/
public class ConversionDemo2 {
public static void main(String[] args) throws IOException {
// 创建转换输出流
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“day12_demo\conversion.txt”), “GBK”);
osw.write(“远桥之下泛莲舟”);
osw.write(“\r\n”);
osw.write(“岱岩石上松溪流”);
osw.write(“\r\n”);
osw.write(“万仞翠山梨亭在”);
osw.write(“\r\n”);
osw.write(“莫闻空谷声悠悠”);
osw.write(“\r\n”);
osw.close();
// 创建转换输入流
InputStreamReader isr = new InputStreamReader(new FileInputStream("day12_demo\\conversion.txt"), "GBK");
int ch;
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
}
isr.close();
}
}
1 |
package com.itheima.conversion_demo;
import java.io.*;
/*
转换流就是来进行字节流和字符流之间转换的桥梁
InputStreamReader是从字节流到字符流的桥梁
public InputStreamReader(InputStream in) : 创建一个使用默认编码的 InputStreamReader。
public InputStreamReader(InputStream in , String charsetName) : 创建使用指定编码的 InputStreamReader。
OutputStreamWriter是从字符流到字节流的桥梁
public OutputStreamWriter(OutputStream out) : 创建使用默认字符编码的 OutputStreamWriter
public OutputStreamWriter(OutputStream out, String charsetName) : 创建使用指定编码的 OutputStreamWriter。
需求2 : 将模块根目录中GBK编码的文本文件 , 转换为UTF-8编码的文本文件
*/
public class ConversionDemo2 {
public static void main(String[] args) throws IOException {
// 创建转换输入流
InputStreamReader isr = new InputStreamReader(new FileInputStream("day12_demo\\GBK编码的文件.txt"), "GBK");
// 创建转换输出流
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day12_demo\\UTF编码的文件.txt"), "UTF-8");
int ch;
while ((ch = isr.read()) != -1) {// 以GBK编码进去读取
osw.write(ch);// 以UTF-8编码进行写入
}
// 释放资源
isr.close();
osw.close();
}
}
1 |
|
对象操作流的练习
打印流
学习目标
- 了解打印流的使用
内容讲解
【1】API
PrintStream类 : 打印流
作用 : 就是为了方便记录数据(日志)
1)构造方法
1 | public PrintStream(String filePath) : 构建一个打印流对象,传入接收数据的文件路径 |
2)方法
1 | public void println(数据) 打印后换行 |
【2】代码实践
创建打印流对象,记录一些数据到指定文件
1 | package com.itheima.printstream_demo; |
System.out 对象类型,其实就是PrintStream类型。
可以改变系统输出的流向:System.setOut(打印流)
1 | package com.itheima.printstream_demo; |
内容小结
- 打印流使用很简单,print/println方法
- 作用:就是为了方便记录数据(日志)
装饰设计模式(自己绘制关系图)
- 设计模式 : 一套良好的编码风格 , 经过众多的开发人员不断的测试总结而来
【1】概述
装饰模式指的是在不改变原类, 不使用继承的基础上,动态地扩展一个对象的功能。
不使用继承技术扩展功能, 可以降低耦合
使用原则:
- 装饰类和被装饰类需要有共同的父类型。
- 在之前学习过的 BufferedWriter 和 FileWriter 就是装饰设计模式
- BufferedWriter的父类为Writer
- FileWriter的父类也是Writer
- 我们把FileWriter的对象传递到BufferedWriter的构造中 , 那么可以理解为BufferedWriter是装饰类 , FileWriter是被装饰类
- BufferedWriter对FileWriter的功能做了增强
- 装饰类的构造要接收被装饰类的对象
- FileWriter fw = new FileWriter(“路径”);
- BufferedWriter bw = new BufferedWriter(fw);
- 在装饰类中把要增强扩展的功能进行扩展
- BufferedWriter和FileWriter的功能一样, 都具备Writer中写数据的功能
- 但是BufferedWriter提供了缓冲区 , 相当于对FileWriter功能做了扩展
- 对于不要增强的功能直接调用
- 不需要增强的功能直接继承父类的即可
- 装饰类和被装饰类需要有共同的父类型。
【2】代码实践
已知有接口Star和其子类型LiuDeHua。
1 | public interface Star { |
需求 :在不改变LiuDeHua类,及不使用继承的技术前提下,动态的扩展LiuDeHua的sing功能。
LiuDeHua就是一个被装饰类 , 需要对唱歌的功能进行扩展
思路 :
定义一个装饰类,去装饰增强 LiuDehua类。
步骤:
- 创建LiuDeHua类并实现接口Star【被装饰类】
- 定义一个装饰类LiuDeHuaWrapper实现Star 【装饰类】
- 在装饰类里面定义一个成员变量类型是LiuDeHua,可以使用构造方法进行传入被装饰类对象。
- 在装饰类中对sing方法进行功能扩展
- 对dance不做改动
- 测试类分别创建装饰类的对象和被装饰类的对象。将被装饰类对象刘德华对象设置给装饰类对象
1 | package com.itheima.design_demo; |
内容小结
- 装饰类和被装饰类需要有共同的父类型。
- 装饰类要传入被装饰类的对象
- 在装饰类中把要增强扩展的功能进行扩展
- 对于不要增强的功能直接调用
commons-io工具包(对文件的拷贝做优化)
【1】三方库的导入
下载commons-io相关jar包;http://commons.apache.org/proper/commons-io/
把commons-io-2.6.jar包复制到指定的Module的lib目录中
将commons-io-2.6.jar加入到项目中
右键jar包:
【2】API
1)org.apache.commons.io.IOUtils类
1 | public static int copy(InputStream in, OutputStream out): |
2)org.apache.commons.io.FileUtils
1 | public static void copyFileToDirectory(final File srcFile, final File destFile): |
代码实践:
1 | package com.itheima.commons_io; |
内容小结
commons-io可以简化IO复制文件的操作。