1 字符流
1.1 常见编码表
ASCII字符集
GBXXX字符集
Unicode字符集
1.2 常见方法
byte[] getBytes() 使用平台的默认字符集将该 String编码为一系列字节
byte[] getBytes(String charsetName) 使用指定的字符集将该 String编码为一系列字节
String(byte[] bytes) 使用平台的默认字符集解码指定的字节数组来创建字符串
String(byte[] bytes, String charsetName) 通过指定的字符集解码指定的字节数组来创建字符串
InputStreamReader(InputStream in) 使用默认字符编码创建InputStreamReader对象
InputStreamReader(InputStream in,String chatset) 使用指定的字符编码创建InputStreamReader对象
OutputStreamWriter(OutputStream out) 使用默认字符编码创建OutputStreamWriter对象
OutputStreamWriter(OutputStream out,String charset) 使用指定的字符编码创建OutputStreamWriter对象
1.3 字符流写数据的五种方式
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) 写一个字符串的一部分
1.4 刷新和关闭的方法
flush() 刷新流,之后还可以继续写数据
close() 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
1.5 字符流读数据的两种方式
int read() 一次读一个字符数据
int read(char[] cbuf) 一次读一个字符数组数据
1.6 字符流复制java文件
把模块目录下的“ConversionStreamDemo.java” 复制到模块目录下的“Copy.java”
public static void main(String[] args) throws IOException {
//根据数据源创建字符输入流对象
FileReader fr = new FileReader("myCharStream\\ConversionStreamDemo.java");
//根据目的地创建字符输出流对象
FileWriter fw = new FileWriter("myCharStream\\Copy.java");
//读写数据,复制文件
// int ch;
// while ((ch=fr.read())!=-1) {
// fw.write(ch);
// }
char[] chs = new char[1024];
int len;
while ((len=fr.read(chs))!=-1) {
fw.write(chs,0,len);
}
//释放资源
fw.close();
fr.close();
}
1.7 字符缓冲流
BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途
BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途
BufferedWriter(Writer out) 创建字符缓冲输出流对象
BufferedReader(Reader in) 创建字符缓冲输入流对象
1.8 字符缓冲流复制java文件
把模块目录下的ConversionStreamDemo.java 复制到模块目录下的 Copy.java
public static void main(String[] args) throws IOException {
//根据数据源创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("myCharStream\\ConversionStreamDemo.java"));
//根据目的地创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\Copy.java"));
//读写数据,复制文件
//一次读写一个字符数据
// int ch;
// while ((ch=br.read())!=-1) {
// bw.write(ch);
// }
//一次读写一个字符数组数据
char[] chs = new char[1024];
int len;
while ((len=br.read(chs))!=-1) {
bw.write(chs,0,len);
}
//释放资源
bw.close();
br.close();
}
1.9 字符缓冲流特有功能
void newLine() 写一行行分隔符,行分隔符字符串由系统属性定义
String readLine() 读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null
1.10字符缓冲流特有功能复制java文件
使用特有功能把模块目录下的ConversionStreamDemo.java 复制到模块目录下的 Copy.java
public static void main(String[] args) throws IOException {
//根据数据源创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("myCharStream\\ConversionStreamDemo.java"));
//根据目的地创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\Copy.java"));
//读写数据,复制文件
//使用字符缓冲流特有功能实现
String line;
while ((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
br.close();
}
1.11 IO流小结
字节流可以复制任意文件数据,有四种方式一般采用字节缓冲流一次读取一个字节数组的方式
字符流只能复制文本数据,有五种方式,一般采用字符缓冲流的特有方式
练习题:
集合到文件:
把文本文件中的数据读取到集合中,并遍历集合。要求:文件中每一行数据是一个集合元素
文件到集合:
把ArrayList集合中的字符串数据写入到文本文件。要求:每一个字符串元素作为文件中的一行数据
点名器:
我有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要求通过程序实现随点名器
集合到文件改进版(使用学生类)
文件到集合改进版(使用学生类)
集合到文件排序改进版:
键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩)。要求按照成绩总分从高到低写入文本文件
复制单极文件夹:
把“E:\itcast”这个文件夹复制到模块目录下
复制多级文件夹:
把“E:\itcast”这个文件夹复制到 F盘目录下
复制文件的异常处理:
基本做法
jdk7版本改进(重点)
jdk9版本改进0
2 IO特殊操作流
2.1 标准输入流
public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标
2.2 标准输出流
输出语句的本质:是一个标准的输出流
public static void main(String[] args) {
//public static final PrintStream out:标准输出流
PrintStream ps = System.out;
//能够方便地打印各种数据值
// ps.print("hello");
// ps.print(100);
// ps.println("hello");
// ps.println(100);
//System.out的本质是一个字节输出流
System.out.println("hello");
System.out.println(100);
System.out.println();
// System.out.print();
}
}
2.3 字节打印流
打印流分类:
字节打印流:PrintStream
字符打印流:PrintWriter
打印流的特点:
只负责输出数据,不负责读取数据
永远不会抛出IOException
有自己的特有方法
public static void main(String[] args) throws IOException {
//PrintStream(String fileName):使用指定的文件名创建新的打印流
PrintStream ps = new PrintStream("myOtherStream\\ps.txt");
//写数据
//字节输出流有的方法
// ps.write(97);
//使用特有方法写数据
// ps.print(97);
// ps.println();
// ps.print(98);
ps.println(97);
ps.println(98);
//释放资源
ps.close();
}
2.4 字符打印流
PrintWriter(String fileName) 使用指定的文件名创建一个新的PrintWriter,而不需要自动执行刷新
PrintWriter(Writer out, boolean autoFlush) 创建一个新的PrintWriter out:字符输出流 autoFlush: 一个布尔值,如果为真,则println , printf ,或format方法将刷新输出缓冲区
public static void main(String[] args) throws IOException {
//PrintWriter(String fileName) :使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新
// PrintWriter pw = new PrintWriter("myOtherStream\\pw.txt");
// pw.write("hello");
// pw.write("\r\n");
// pw.flush();
// pw.write("world");
// pw.write("\r\n");
// pw.flush();
// pw.println("hello");
/*
pw.write("hello");
pw.write("\r\n");
*/
// pw.flush();
// pw.println("world");
// pw.flush();
//PrintWriter(Writer out, boolean autoFlush):创建一个新的PrintWriter
PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\pw.txt"),true);
// PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\pw.txt"),false);
pw.println("hello");
/*
pw.write("hello");
pw.write("\r\n");
pw.flush();
*/
pw.println("world");
pw.close();
}
2.5 复制java文件打印流改进版
把模块目录下的PrintStreamDemo.java 复制到模块目录下的 Copy.java
public static void main(String[] args) throws IOException {
/*
//根据数据源创建字符输入流对象
BufferedReader br = new BufferedReader(new FileReader("myOtherStream\\PrintStreamDemo.java"));
//根据目的地创建字符输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("myOtherStream\\Copy.java"));
//读写数据,复制文件
String line;
while ((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
br.close();
*/
//根据数据源创建字符输入流对象
BufferedReader br = new BufferedReader(new FileReader("myOtherStream\\PrintStreamDemo.java"));
//根据目的地创建字符输出流对象
PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\Copy.java"),true);
//读写数据,复制文件
String line;
while ((line=br.readLine())!=null) {
pw.println(line);
}
//释放资源
pw.close();
br.close();
}
2.6 对象序列化
对象序列化流: ObjectOutputStream
ObjectOutputStream(OutputStream out) 创建一个写入指定的OutputStream的ObjectOutputStream
void writeObject(Object obj) 将指定的对象写入ObjectOutputStream
例子:
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ObjectOutputStreamDemo { \\测试
public static void main(String[] args) throws IOException {
//ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myOtherStream\\oos.txt"));
//创建对象
Student s = new Student("林青霞",30);
//void writeObject(Object obj):将指定的对象写入ObjectOutputStream
oos.writeObject(s);
//释放资源
oos.close();
}
}
2.7 对象反序列化流
ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream
Object readObject() 从ObjectInputStream读取一个对象
public class ObjectInputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myOtherStream\\oos.txt"));
//Object readObject():从ObjectInputStream读取一个对象
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
}
2.8 serialVersionUID&transient
serialVersionUID
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
会出问题,会抛出InvalidClassException异常如果出问题了,如何解决呢? 重新序列化
给对象所属的类加一个serialVersionUID
private static final long serialVersionUID = 42L;
transient
给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
例子:
public class Student implements Serializable {
private static final long serialVersionUID = 42L;
private String name;
// private int age;
private transient int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// @Override
// public String toString() {
// return "Student{" +
// "name='" + name + '\'' +
// ", age=" + age +
// '}';
// }
}
public class ObjectStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// write();
read();
}
//反序列化
private static void read() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myOtherStream\\oos.txt"));
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
//序列化
private static void write() throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myOtherStream\\oos.txt"));
Student s = new Student("林青霞", 30);
oos.writeObject(s);
oos.close();
}
}
2.9 Properties集合
Properties介绍
是一个Map体系的集合类
Properties可以保存到流中或从流中加载
属性列表中的每个键及其对应的值都是一个字符串
Properties基本使用:
public class PropertiesDemo01 {
public static void main(String[] args) {
//创建集合对象
// Properties<String,String> prop = new Properties<String,String>(); //错误
Properties prop = new Properties();
//存储元素
prop.put("itheima001", "林青霞");
prop.put("itheima002", "张曼玉");
prop.put("itheima003", "王祖贤");
//遍历集合
Set<Object> keySet = prop.keySet();
for (Object key : keySet) {
Object value = prop.get(key);
System.out.println(key + "," + value);
}
}
}
2.10 Properties集合作为MAP集合的特有方法
Object setProperty(String key, String value) 设置集合的键和值,都是String类型,底层调用 Hashtable方法 put
String getProperty(String key) 使用此属性列表中指定的键搜索属性
Set<String> stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
public class PropertiesDemo02 {
public static void main(String[] args) {
//创建集合对象
Properties prop = new Properties();
//Object setProperty(String key, String value):设置集合的键和值,都是String类型,底层调用Hashtable方法put
prop.setProperty("itheima001", "林青霞");
/*
Object setProperty(String key, String value) {
return put(key, value);
}
Object put(Object key, Object value) {
return map.put(key, value);
}
*/
prop.setProperty("itheima002", "张曼玉");
prop.setProperty("itheima003", "王祖贤");
//String getProperty(String key):使用此属性列表中指定的键搜索属性
// System.out.println(prop.getProperty("itheima001"));
// System.out.println(prop.getProperty("itheima0011"));
// System.out.println(prop);
//Set<String> stringPropertyNames():从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
Set<String> names = prop.stringPropertyNames();
for (String key : names) {
// System.out.println(key);
String value = prop.getProperty(key);
System.out.println(key + "," + value);
}
}
}
2.11 Properties和IO流结合的方法
void load(InputStream inStream) 从输入字节流读取属性列表(键和元素对)
void load(Reader reader) 从输入字符流读取属性列表(键和元素对)
void store(OutputStream out, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法的格式写入输出字节流
void store(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流
public class PropertiesDemo03 {
public static void main(String[] args) throws IOException {
//把集合中的数据保存到文件
// myStore();
//把文件中的数据加载到集合
myLoad();
}
private static void myLoad() throws IOException {
Properties prop = new Properties();
//void load(Reader reader):
FileReader fr = new FileReader("myOtherStream\\fw.txt");
prop.load(fr);
fr.close();
System.out.println(prop);
}
private static void myStore() throws IOException {
Properties prop = new Properties();
prop.setProperty("itheima001","林青霞");
prop.setProperty("itheima002","张曼玉");
prop.setProperty("itheima003","王祖贤");
//void store(Writer writer, String comments):
FileWriter fw = new FileWriter("myOtherStream\\fw.txt");
prop.store(fw,null);
fw.close();
}
}