装饰者模式
思想: 将原有的功能进行提升
例:
File类 ---> 提升为具有写文件的功能
将File类对象传入输出流中(相当于提升了File对象的功能)
File file = new file("/UserS/lna/Desktop/test.txt");
FileOutputStream fos = new FileOutputStream(file);
FileOutputStream ---> 提升为具有高效性功能
将FileOutputStream传入BufferedOutputStream
BufferedOutputStream bos = new BufferedOutputStream(fos);
装饰者模式步骤:
1.将被装饰者 定义为类中的一个成员变量
2.在构造方法中 进行成员变量的赋值
赋值后 就相当于 可以拿到这个对象
有这个对象 就能调用该对象的方法
3.对原有的方法进行升级
例: 对学生功能进行升级
// 创建一个学生类
class Student {
public void study() {
System.out.println("学习c语言");
System.out.println("学习c++");
System.out.println("学习c#");
}
}
// 装饰学生类
class LSyudent {
private Student student;
public LSyudent() {
super();
// TODO Auto-generated constructor stub
}
public LSyudent(Student student) {
super();
this.student = student;
}
public void lstudy() {
student.study();
System.out.println("学习java");
System.out.println("学习PHP");
}
}
// 调用测试
public class D1 {
public static void main(String[] args) {
Student student = new Student();
LSyudent lSyudent = new LSyudent(student);
lSyudent.lstudy();
}
}
// 打印结果
学习c语言
学习c++
学习c#
学习java
学习PHP
LineNumberReader 带行号的缓冲字符输入流
继承于BufferedReader
测试LineNumberReader
File file = new File("/Users/lna/c/xiaofeng.txt");
FileReader fr = new FileReader(file);
LineNumberReader lnr = new LineNumberReader(fr);
// 设置行号
lnr.setLineNumber(100);
while ((string = lnr.readLine()) != null) {
// 打印行号 和 内容
System.out.println(lnr.getLineNumber() + ":" + string);
}
lnr.close();
利用装饰者模式 模拟LineNumberReader类
class MyLineNumberReader {
// 具有读文件 和 读取行号的功能
// 将被包装的对象 定义为实例变量
private Reader reader; // Reader的子类都可以传入
private int lineNum;
public MyLineNumberReader() {
super();
// TODO Auto-generated constructor stub
}
public MyLineNumberReader(Reader reader) {
super();
this.reader = reader;
}
public int getLineNum() {
return lineNum;
}
public void setLineNum(int lineNum) {
this.lineNum = lineNum;
}
// 读取方法 每次读一行 获取读的内容
public String LineReader() throws IOException {
// 每读一行 行号+1
lineNum++;
// 每次读取一行 需要拼接字符串
StringBuffer sb = new StringBuffer();
int len = 0;
// 循环读取 直到到达流的末尾
while ((len = reader.read()) != -1) {
// 判断是否读完一行
if (len != '\n') {
sb.append((char)len);
} else {
return sb.toString(); // 转成字符型
}
}
// 判断文件读完 返回空
if (sb.length() == 0) {
return null;
}
return sb.toString();
}
// 关闭流的方法
public void closeMyLine() throws IOException {
reader.close();
}
}
打印流
打印流不会抛出IO异常
操作输出目的: 写文件 用控制台打印
PrintStream (字节流)
构造方法: 文件 字节输出流 或 路径
PrintWriter (字符流)
构造方法: 文件 字节输出流 路径 字符输出流
核心功能: 原样输出到目的端
System.in 是 BufferedInputStream对象 缓冲字节输入流
System.out 是 PrintStream对象(打印流)
打印字节流PrintStream写文件
// 打印字节流PrintStream写文件
public class D3fun1 {
public static void main(String[] args) throws IOException {
File file = new File("/Users/lanou/Desktop/lna/binbin.txt");
FileOutputStream fos = new FileOutputStream(file);
PrintStream ps = new PrintStream(fos);
// 写入
ps.println("haha");
ps.print(100);
ps.print(true);
ps.close();
}
}
打印字符流PrintWriter写文件
public class D3fun2 {
// 打印字符流PrintWriter写文件
public static void main(String[] args) throws IOException {
File file = new File("/Users/lanou/Desktop/lna/binbin.txt");
FileWriter fw = new FileWriter(file);
// 可使用自动刷新的构造方法 只对流有效
PrintWriter pw = new PrintWriter(fw,true);
pw.println("大海吧");
pw.print(true);
pw.print(666);
pw.close();
}
}
利用System.in 从控制台接收
利用System.out 输出到控制台
输入quit停止输入
打印到控制台(不用Scanner)
创建流对象 不会卡住程序
从控制台读取的时候才会卡住
public static void main(String[] args) throws IOException {
System.out.println("请输入:");
// 从打印控制台接收输入的信息
InputStream in = System.in;
// 拼接字符串
StringBuffer sb = new StringBuffer();
int len = 0; // 接受读取的ascii码
while (true) {
// 判断是否停止
if (sb.toString().equals("quit")) {
break;
}
// 读取输入的信息(程序卡住,输入信息)
len = in.read();
if (len != '\n') {
// 是否换行
sb.append((char)len); // 拼接字符
} else {
// 换行则打印
System.out.println(sb.toString());
// 清空字符串 再继续下一行
sb.delete(0, sb.length());
}
}
in.close();
}
合并流(输入流)
SequenceInputStream
作用: 可以把多个文件 读成一个文件(合并成一个文件)
文件不局限为文本文件(照片之类也可以)
例: 将三个文件的内容 写入一个文件中
File file1 = new File("/Users/rename/lna/1.txt");
File file2 = new File("/Users/rename/lna/2.txt");
File file3 = new File("/Users/rename/lna/c/3.txt");
// 创建集合
Vector<FileInputStream> vector = new Vector<>();
// 添加文件输入流
vector.add(new FileInputStream(file1));
vector.add(new FileInputStream(file2));
vector.add(new FileInputStream(file3));
// 获取迭代器
Enumeration<FileInputStream> elements = vector.elements();
// 创建合并流
SequenceInputStream sis = new SequenceInputStream(elements);
// 写入的文件
FileOutputStream fos = new FileOutputStream("/Users/lna/a/test.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos); // 转换流
BufferedWriter bw = new BufferedWriter(osw); //使用bw的换行方法
int len = 0;
while ((len = sis.read()) != -1) {
bw.write(len);
bw.newLine();
bw.flush();
}
sis.close();
bw.close();
例: 将一张图片 分割成多个文件
每个文件按1M分割 1024*1024
分割完后
再将分割的多个文件合并成一个图片
public static void main(String[] args) throws IOException {
// 读
FileInputStream fis = new FileInputStream(new File("/Users/lanou/Desktop/dp.png"));
int len = 0;
byte[] b = new byte[1024*1024];
int num = 1;
while ((len = fis.read(b)) != -1) {
// 写入
File file = new File("/Users/lanou/Desktop/rename/" + num + ".png");
FileOutputStream fos = new FileOutputStream(file);
fos.write(b, 0, len);
num++;
fos.close();
}
}
public static void fun() throws IOException {
// 合并
// 创建集合
Vector<FileInputStream> vector = new Vector<>();
int num = 1;
while (true) {
File file = new File("/Users/lanou/Desktop/rename/" + num + ".png");
try {
num++;
FileInputStream fis = new FileInputStream(file);
vector.add(fis);
} catch (FileNotFoundException e) {
break;
}
}
Enumeration<FileInputStream> elements = vector.elements();
SequenceInputStream sis = new SequenceInputStream(elements);
FileOutputStream fos = new FileOutputStream(new File("/Users/lanou/Desktop/rename/图片.png"));
// 读写
int len = 0;
byte[] b = new byte[1024*1024];
while ((len = sis.read(b)) != -1) {
fos.write(b, 0, len);
fos.flush();
}
sis.close();
fos.close();
}