一:字符流
Reader
Writer
1.1
IO流中的编码和解码问题
OutputStreamWriter:把字节输出流转换为字符输出流
InputStreamReader:把字节输入流转换为字符输入流
1.2 转换流
写入数据,把字节输出流转换为字符输出流(不指定码表)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"));
把字节输出流转换为字符输出流(指定码表)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "GBK");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "UTF-8");
package com.edu_01;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
*
字符流写数据的三部曲:
1.创建字符输出流对象指向文件
2.调用方法向文件中写数据
3.刷新缓冲区
4.关流
*
*/
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
//不指定码表创建字符输出转换流
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"));
//osw.write("hello");
//指定码表的方式创建一个字符输出转换流
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"), "gbk");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"), "utf-8");
osw.write("中国");
//字符流写数据的时候,每写一次。必须刷新缓冲区
osw.flush();
//关流,字符流在关闭之前,会自动刷新缓冲区
osw.close();
}
}
读取数据, 把字节输入流转换为字符输入流(不指定码表)
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"));
把字节输入流转换为字符输入流(指定码表)
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "GBK");
总结:我们一般创建字符输入或者输出流一般情况下使用系统默认的码表就可以,如果来来回回需要指定码表的话,就显得非常的麻烦了
package com.edu_01;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
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("a.txt"));
//创建一个字符输入转换流,并指定码表
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"gbk");
//一次读取一个字符
/*System.out.println((char)isr.read());
System.out.println((char)isr.read());
System.out.println((char)isr.read());
System.out.println((char)isr.read());
System.out.println((char)isr.read());
System.out.println(isr.read());
System.out.println(isr.read());*/
//使用循环改进
int ch;
while ((ch=isr.read())!=-1) {
System.out.println((char)ch);
}
//关流
isr.close();
}
}
1.3 (将以上创建方式继续简化)
如果采用上述方式,创建对象写起来比较复杂。
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));
为了简化这种操作,java就针对这两个转换的字符流提供其子类。
FileReader
FileWriter
它们的默认编码是采用系统编码。
构造学习:
FileWriter(File file)
FileWriter(String fileName)
FileReader(File file)
FileReader(String fileName)
flush()和close()的区别?
A:flush 刷新缓冲区,流对象可以继续
B:close 先刷新缓冲区,再关闭流对象。流对象不可以继续使用了。
练习:给字符输出流里面利用方法写数据
* 字符输出流操作步骤:
* A:创建字符输出流对象
* B:调用写数据方法
* C:释放资源
*
* 写数据方法:
* 一次写一个字符 write(int c)
* 一次写一个字符数组write(char[] cbuf)
* 一次写一个字符数组的一部分write(char[] cbuf, int off,int len)
* 一次写一个字符串write(String str)
* 一次写一个字符串的一部分write(String str,int off,int len)
package com.edu_02;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterDemo {
public static void main(String[] args) throws IOException {
/**
* 要给字符输出流中写数据步骤:
* 1.创建字符输出流对象,并指向一个文件
* 2.调用字符输出流写数据的方法给里面写数据
* 3.刷新缓冲区
* 4.关流
*/
// FileWriter(File file)
// FileWriter(String fileName)
//1.创建字符输出流对象
//FileWriter fw = new FileWriter(new File("c.txt"));
FileWriter fw = new FileWriter("c.txt");
//调用方法写数据
//一次写一个字符 write(int c)
//fw.write('a');
//一次写一个字符数组write(char[] cbuf)
//char[] chs = {'h','e','l','l','o'};
//fw.write(chs);
//一次写一个字符数组的一部分write(char[] cbuf, int off,int len)
//char[] chs = {'h','e','l','l','o'};
//fw.write(chs, 2, 3);
//一次写一个字符串write(String str)
//fw.write("helloworld");
//一次写一个字符串的一部分write(String str,int off,int len)
fw.write("helloworld", 5, 5);
//刷新缓冲区
fw.flush();
//关流
fw.close();
}
}
1.4 字符输入流
字符输入流操作步骤:
A:创建字符输入流对象
FileReader fr = new FileReader("a.txt");
B:读取数据并显示在控制台
a:一次读取一个字符
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
b:一次读取一个字符数组
char[] chs = new char[1024];
int len;
while ((len = fr.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
C:释放资源
fr.close();
package com.edu_03;
import java.io.FileNotFoundException;
import java.io.FileReader;
/**
* FileReader(File file)
FileReader(String fileName)
*
*/
public class FileReaderDemo {
public static void main(String[] args) throws Exception {
/**
* 使用字符输入流读取c.txt真的个文件的步骤:
* 1.创建字符输入流对象,指向c.txt这个文件
* 2.一次读取一个字符
* 3.关流
*/
//1.创建字符输入流对象,指向c.txt这个文件
FileReader fr = new FileReader("c.txt");
//2.一次读取一个字符
/*System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println(fr.read());*/
//使用循环改进
/* int ch;
while ((ch=fr.read())!=-1) {
System.out.println((char)ch);
}*/
//一次读取一个字符数组
/* char[] chs = new char[2];
System.out.println(fr.read(chs));//一次读取一个字符数组,返回的是读取到的实际的字符长度
System.out.println(fr.read(chs));
System.out.println(fr.read(chs));
System.out.println(fr.read(chs));
System.out.println(fr.read(chs));*/
//使用循环改进上面代码
//定义一个字符数组
char[] chs = new char[1024];
int len;
while ((len=fr.read(chs))!=-1) {
System.out.println(new String(chs, 0, len));
}
//3.关流
fr.close();
}
}
1.5练习
注意:字符流输入输出流复制的文件是有要求的,简单来说只要是记事本打开文件的内容你能够看得懂,就可以用字符流来进行复制,否则不行
具体原因:像复制MP3或者一些视频文件的时候,如果他的字节个数不是偶数的话,就会造成文件的缺损,
因为一个字符等于两个字节
利用字符流复制java文件(两种方式,一次读写一个字符,一次读写一个字符数组)
package com.edu_04;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyFile {
public static void main(String[] args) throws IOException {
/**
* 1.封装数据源和目的地
* 2.一次读写一个字符或者一次读写一个字符数组
* 3.关流
*/
//1.封装数据源和目的地
FileReader fr = new FileReader("InputStreamReaderDemo.java");
FileWriter fw = new FileWriter("d.java");
//2.1一次读写一个字符
/*int ch;
while ((ch=fr.read())!=-1) {
fw.write(ch);//一次写一个字符
fw.flush();//每写一次刷新缓冲区
}*/
//2.2一次读写一个字符数组
char[] chs = new char[1024];
int len;
while ((len=fr.read(chs))!=-1) {
fw.write(chs, 0, len);
fw.flush();
}
//3.关流
fw.close();
fr.close();
}
}
1.6 高效流:(重要)
需求:
给文件中写入十个”helloworld”,每写一个换一行,每写一行必须写入一个换行符
package com.edu_05;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
fw.write("helloworld"+"\r\n");
fw.flush();
}
//3.释放资源
fw.close();
}
}
“/r/n”这样写的弊端,windows系统下的换行符是“/r/n”,Linux是”\n”,Mac是”\r”,这样会造成代码的通用性不强
* BufferedReader:字符缓冲输入流
构造:BufferedReader(Reader in)
特殊方法:public String readLine():包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
package com.edu_06;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
/**
* 需求:使用高效字符输入流读取f.txt文件
* 1.创建高效字符输入流对象,指向f.txt
* 2.一次读取一行,readLine()
* 3.关流
*/
//1.创建高效字符输入流对象,指向f.txt
//BufferedReader(Reader in)
BufferedReader br = new BufferedReader(new FileReader("f.txt"));
//2.一次读取一行,readLine(),当读取文件末尾的时候返回null
/* System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());*/
//使用循环改进
String line;
while ((line= br.readLine())!=null) {
System.out.println(line);
}
//3.关流
br.close();
}
}
* BufferedWriter:字符缓冲输出流
构造:BufferedWriter(Writer out)
特殊方法:public void newLine():会根据系统来确定写入不同的换行符
package com.edu_05;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo2 {
public static void main(String[] args) throws IOException {
//使用高效字符输出流写入10个helloworld,每写一个换一行
/**
* 1.创建字符高效输出流,并指向一个txt文件
* 2.调用里面写数据的方法,给文件中写入数据
* 3.调用换行的方法,给写入的数据换行
* 4.刷新换新区
* 5.关流
*/
//1.创建字符高效输出流,并指向一个txt文件
BufferedWriter bw = new BufferedWriter(new FileWriter("f.txt"));
//2.调用里面写数据的方法,给文件中写入数据
for (int i = 0; i < 10; i++) {
//给文件中写入helloworld
bw.write("helloworld");
//写入换行符
bw.newLine();
//刷新缓冲区
bw.flush();
}
//关流
bw.close();
}
}
最终练习:
复制文本文件:
4种
基本字符流一次读写一个字符
基本字符流一次读写一个字符数组
高效字符流一次读写一个字符
高效字符流一次读写一个字符数组
数据源:
a.txt
目的地:
b.txt
package com.edu_07;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
method();//基本字符流一次读写一个字符
method2();//基本字符流一次读写一个字符数组
method3();//高效字符流一次读写一个字符
method4();//高效字符流一次读写一个字符数组
}
private static void method4() throws IOException {
//高效字符流一次读写一个字符数组
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("j.txt"));
//一次读写一个字符数组
char[] chs = new char[1024];
int len;
while ((len = br.read(chs))!=-1) {
bw.write(chs, 0, len);
bw.flush();
}
//释放资源
bw.close();
br.close();
}
private static void method3() throws IOException {
//高效字符流一次读写一个字符
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("j.txt"));
//一次读写一个字符
int ch;
while ((ch=br.read())!=-1) {
bw.write(ch);
bw.flush();
}
//关流
bw.close();
br.close();
}
private static void method2() throws IOException {
//基本字符流一次读写一个字符数组
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("j.txt");
//一次读写一个字节数组
char[] chs = new char[1024];
int len;
while ((len = fr.read(chs))!=-1) {
fw.write(chs, 0, len);
fw.flush();
}
//关流
fw.close();
fr.close();
}
private static void method() throws IOException {
//基本字符流一次读写一个字符
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("j.txt");
//一次读取一个字符,返回的是该字符对应的int值
/* System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
*/
int ch;
while ((ch=fr.read())!=-1) {
//System.out.println((char)ch);
fw.write(ch);
fw.flush();
}
//释放资源
fr.close();
fw.close();
}
}
1.7
讲解(必须掌握,字符流中最常用的使用方式)
BufferedReader:字符缓冲输入流
BufferedWriter:字符缓冲输出流
的特性。
1.需求:向文件中写入十个中国好,每写一个换一行(普通方式实现,高效流输出流特性实现)
package com.edu_08;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
//创建高效字符输出流对象,并指向ff.txt文件
BufferedWriter bw = new BufferedWriter(new FileWriter("ff.txt"));
//写入数据
for (int i = 0; i < 10; i++) {
/**
* 1.写一行
* 2.换行
* 3.刷新
*/
bw.write("中国好");
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
}
2.利用字符高效流的一次读写一行的特性复制文件
写数据注意三部曲:
bw.write(line);
bw.newLine();
bw.flush();
package com.edu_08;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.annotation.processing.Filer;
import javax.lang.model.element.Element;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileManager.Location;
public class Test {
public static void main(String[] args) throws IOException {
//封装数据源和目的地
BufferedReader br = new BufferedReader(new FileReader("InputStreamReaderDemo.java"));
BufferedWriter bw = new BufferedWriter(new FileWriter("copy.java"));
//读取一行写一行
String line;
while ((line = br.readLine())!=null) {
//System.out.println();
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
br.close();
}
}
二:IO流练习
1.键盘录入数据并存储
键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件
分析:
A:定义学生类
B:创建集合,采用TreeSet集合,并按照比较器排序
C:键盘录入5个学生信息并存入集合
D:遍历集合,并把数据写到文本文件
package com.edu_09;
public class Student {
private String name;
private int chinese;
private int math;
private int english;
public Student(String name, int chinese, int math, int english) {
super();
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
//获取总成绩的方法
public int getAllScore(){
return chinese+math+english;
}
}
package com.edu_09;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
public class StudentTest {
public static void main(String[] args) throws IOException {
//创建一个TreeSet集合,并写一个比较器
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getAllScore() - s2.getAllScore();
int num2 = num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
//键盘录入5个学生信息
for (int i = 0; i < 5; i++) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//接受键盘录入数据
System.out.println("请输入你的姓名");
String name = sc.nextLine();
System.out.println("请输入你的语文成绩");
int chinese = sc.nextInt();
System.out.println("请输入你的数学成绩");
int math = sc.nextInt();
System.out.println("请输入你的英语成绩");
int english = sc.nextInt();
//封装成学生对象,存储集合
Student s = new Student(name, chinese, math, english);
ts.add(s);
}
System.out.println("数据录入完毕。。");
//遍历集合,将集合中的数据全取不出来之后写入文件中,每一个学生信息占一行
BufferedWriter bw = new BufferedWriter(new FileWriter("score.txt"));
for (Student s : ts) {
String info = s.getName()+" "+s.getChinese()+" "+s.getMath()+" "+s.getEnglish()+" "+s.getAllScore();
//将拼接成的字符串写入文件中
bw.write(info);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
}
三:设计模式(了解)
A:设计模式概述
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性以及代码的结构更加清晰.
B:设计模式分类
创建型模式(创建对象的): 单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
行为型模式(对象的功能): 适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
结构型模式(对象的组成): 模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、
解释器模式、状态模式、策略模式、职责链模式、访问者模式。
单例设计模式(掌握)
A:单例设计思想
保证类在内存中只有一个对象
B:如何实现类在内存中只有一个对象呢?
构造私有
本身提供一个对象
通过公共的方法让外界访问
C:案例演示: 单例模式之饿汉式, 懒汉式
问题:面试中写哪种设计模式呢?
package com.edu_10;
public class SingleInstanceDemo {
/**
* 饿汉式:当这个类一被加载,就在内存中创建了一个对象
*
* 1.保证内存中只有一个对象(构造私有)
* 2.在本类中创建一个该类的对象
* 3.创建一个公共的访问方式给外界获取该对象
*/
private SingleInstanceDemo(){}
//静态的随着类的加载而加载
private static SingleInstanceDemo instance = new SingleInstanceDemo();
//给外界提供公共的访问方式,返回该对象
public static SingleInstanceDemo getInstance(){
return instance;
}
}
package com.edu_10;
public class SingleInstanceDemo2 {
/**
* 单例设计模式之懒汉式:
* 需要的时候才去创建对象,不需要的时候不创建
*/
private SingleInstanceDemo2(){}
private static SingleInstanceDemo2 instance = null;
public static SingleInstanceDemo2 getInstance(){
if (instance==null) {
instance = new SingleInstanceDemo2();
}
return instance;
}
}
工厂设计模式(掌握)
(简单工厂模式概述和使用)(理解)
A:简单工厂模式概述: 又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例
B:优点: 使用静态工厂模式的优点是实现责任的分割,该模式的核心是工厂类,工厂类含有必要的选择逻辑,可以决定什么时候创建哪一个产品的实例,而客户端则免去直接创建产品的责任,而仅仅是消费产品。也就是说静态工厂模式在不改变客户端代码的情况可以动态的增加产品。明确了类的职责
C:缺点
这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护
D:案例演示
package com.edu_11;
public abstract class Animal {
public abstract void eat();
}
package com.edu_11;
public class AnimalFactory {
//专门用来生产对象
public static Animal getAnimal(String type){
if ("dog".equals(type)) {
return new Dog();
}else if ("cat".equals(type)) {
return new Cat();
}
return null;
}
}
package com.edu_11;
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
package com.edu_11;
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
package com.edu_11;
public class Test {
public static void main(String[] args) {
// Dog d = new Dog();
// Dog d2 = new Dog();
// d.eat();
// d2.eat();
//
// Cat c = new Cat();
// Cat c2 = new Cat();
// c.eat();
// c2.eat();
//如果说我们的类和对象比较多的话,这样每次去new对象的话,就显得不是非常的方便了
//此时我们需要专门创建一个工厂类,专门负责生产对象
Animal a = AnimalFactory.getAnimal("dog");
a.eat();
a = AnimalFactory.getAnimal("cat");
a.eat();
}
}
(抽象工厂模式的概述和使用)(理解)
A:工厂方法模式概述
工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现。
B:优点
客户端不需要在负责对象的创建,从而明确了各个类的职责,如果有新的对象增加,只需要增加一个具体的类和具体的工厂类即可,不影响已有的代码,后期维护容易,增强了系统的扩展性
C:缺点: 需要额外的编写代码,增加了工作量
package com.edu_12;
public abstract class Animal {
public abstract void eat();
}
package com.edu_12;
public abstract class AnimalFactory {
//创建动物的功能
public abstract Animal getAnimal();
}
package com.edu_12;
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
package com.edu_12;
public class CatFactory extends AnimalFactory{
@Override
public Animal getAnimal() {
// TODO Auto-generated method stub
return new Cat();
}
}
package com.edu_12;
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
package com.edu_12;
public class DogFactory extends AnimalFactory{
@Override
public Animal getAnimal() {
// TODO Auto-generated method stub
return new Dog();
}
}
package com.edu_12;
public class Test {
public static void main(String[] args) {
//需要一个狗对象
AnimalFactory af = new DogFactory();
Animal a = af.getAnimal();
a.eat();
//需要一个猫对象
af = new CatFactory();
a = af.getAnimal();
a.eat();
//需要一个老虎类
af = new TigerFactory();
a = af.getAnimal();
a.eat();
}
}
package com.edu_12;
public class Tiger extends Animal{
@Override
public void eat() {
System.out.println("虎吃人");
}
}
package com.edu_12;
public class TigerFactory extends AnimalFactory{
@Override
public Animal getAnimal() {
// TODO Auto-generated method stub
return new Tiger();
}
}