------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
一.字符流
1.字符流是什么
字符流是可以直接读写字符的IO流
字符流读取字符, 就要先读取到字节数据, 然后转为字符.如果要写出 字符, 需要把字符转为字节再写出.
2.FileReader, FileWriter
FileReader类的read()方法可以按照字符大小读取
FileWriter类的write()方法可以自动把字符转为字节写出
- import java.io.FileReader;
- import java.io.IOException;
- public class Demo1_FileReader {
- /**
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- //demo1();
- FileReader fr = new FileReader("aaa.txt");
- int ch;
- while((ch = fr.read()) != -1) {
- System.out.print((char)ch);
- }
- fr.close();
- }
- }
- import java.io.FileWriter;
- import java.io.IOException;
- public class Demo2_FileWriter {
- /**
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- FileWriter fw = new FileWriter("bbb.txt");
- fw.write("基础班快毕业了,革命尚未成功,大家继续努力");
- fw.close();
- }
- }
3.什么情况下使用字符流
字符流也可以拷贝文本文件,但不推荐使用. 因为读取时会把字节转为字符, 写出时还要把字符转回字节.
程序需要读取一段文本, 或者需要写出一段文本的时候可以使用字符流
是否可以用字符流拷贝非纯文本的文件,例如音频,视频,图片?
字符流只能操作纯文本的文件
- public static void main(String[] args) throws IOException {
- //demo1();
- FileReader fr = new FileReader("IO图片.png");
- FileWriter fw = new FileWriter("copy.png");
- int ch;
- while((ch = fr.read()) != -1) {
- fw.write(ch);
- }
- fr.close();
- fw.close();
- }
- private static void demo1() throws FileNotFoundException, IOException {
- FileReader fr = new FileReader("day22笔记.txt");
- FileWriter fw = new FileWriter("copy.txt");
- int ch;
- while((ch = fr.read()) != -1) {
- fw.write(ch);
- }
- fr.close();
- fw.close();
- }
- }
4.带缓冲的字符流
BufferedReader的read()方法读取字符时会一次读取若干字符到缓冲区, 然后逐个返回给程序, 降低读取文件的次数, 提高效率
BufferedWriter的write()方法写出字符时会先写到缓冲区, 缓冲区写满时才会写到文件, 降低写文件的次数, 提高效率
BufferedReader的readLine()方法可以读取一行字符(不包含换行符号)
BufferedWriter的newLine()可以输出一个跨平台的换行符号"\r\n"
- public class Demo5_Buffer {
- /**
- * @param args
- * @throws IOException
- * flush和close的区别
- * flush方法用来刷出缓冲区的数据,刷完之后,还可以继续写
- * close方法是关闭流对象,在关之前会调用一次flush刷新缓冲区最后的内容,并将流关闭,关闭之后,不能再写
- */
- public static void main(String[] args) throws IOException {
- //demo1();
- //demo2();
- BufferedReader br = new BufferedReader(new FileReader("day22笔记.txt"));
- BufferedWriter bw = new BufferedWriter(new FileWriter("copy.txt"));
- String line;
- while((line = br.readLine()) != null) {
- bw.write(line);
- //bw.write("\r\n");
- bw.newLine();
- /*
- * \r\n只支持的windows系统
- * newLine是跨平台的,支持任何操作系统
- */
- }
- br.close();
- bw.close();
- }
- }
5.LineNumberReader
LineNumberReader是BufferedReader的子类, 具有相同的功能, 并且可以统计行号
调用getLineNumber()方法可以获取当前行号
调用setLineNumber()方法可以设置当前行号
- import java.io.FileNotFoundException;
- import java.io.FileReader;
- import java.io.IOException;
- import java.io.LineNumberReader;
- public class Demo6_LineNumberReader {
- /**
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- LineNumberReader lnr = new LineNumberReader(new FileReader("day22笔记.txt"));
- String line;
- lnr.setLineNumber(100); //设置行号
- while((line = lnr.readLine()) != null) {
- System.out.println(lnr.getLineNumber() + ":" + line); //获取行号
- }
- lnr.close();
- }
- }
6.使用指定的码表读取字符
FileReader是使用默认码表读取文件, 如果需要使用指定码表读取, 那么可以使用InputStreamReader(字节流,编码表)
FileWriter是使用默认码表写出文件, 如果需要使用指定码表写出, 那么可以使用OutputStreamWriter(字节流,编码表)
- import java.io.FileOutputStream;
- import java.io.FileReader;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.OutputStreamWriter;
- import java.io.UnsupportedEncodingException;
- public class Demo8_TransIO {
- /**
- * @param args
- * 转换流
- * @throws IOException
- * 字符流(字节流+编码表)
- * 读gbk编码表的文件写到utf-8编码表文件
- * 高效
- */
- public static void main(String[] args) throws IOException {
- BufferedReader br =
- new BufferedReader(new InputStreamReader(new FileInputStream("day22笔记.txt"),"gbk"));
- BufferedWriter bw =
- new BufferedWriter(new OutputStreamWriter(new FileOutputStream("UTF-8.txt"),"UTF-8"));
- int ch;
- while((ch = br.read()) != -1) {
- bw.write(ch);
- }
- br.close();
- bw.close();
- }
- }
7.装饰设计模式
让被包装的对象变的更加强大
- public class Demo7_Wrap {
- public static void main(String[] args) {
- Student s = new Student();
- s.code();
- System.out.println("-------------------");
- ItcastStudent is = new ItcastStudent(s);
- is.code();
- }
- }
- interface Coder {
- public void code();
- }
- class Student implements Coder {
- @Override
- public void code() {
- System.out.println("javase");
- System.out.println("javaweb");
- }
- }
- class ItcastStudent implements Coder{
- private Student s;
- public ItcastStudent(Student s) {
- this.s = s;
- }
- @Override
- public void code() {
- s.code();
- System.out.println("数据库");
- System.out.println("安卓");
- System.out.println("ssh");
- System.out.println(".......");
- }
- }
二.序列流
1.什么是序列流
序列流可以把多个字节输入流整合成一个, 从序列流中读取数据时, 将从被整合的第一个流开始读, 读完一个之后继续读第二个, 以此类推.
2.使用方式
整合两个: SequenceInputStream(InputStream, InputStream)
整合多个: SequenceInputStream(Enumeration)
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.SequenceInputStream;
- import java.util.Enumeration;
- import java.util.Vector;
- public class Demo1_SequenceInputStream {
- public static void main(String[] args) throws IOException {
- demo1();
- demo2();
- //整合多个文件
- FileInputStream fis1 = new FileInputStream("a.txt"); //创建流对象,关联a.txt
- FileInputStream fis2 = new FileInputStream("b.txt"); //创建流对象,关联b.txt
- FileInputStream fis3 = new FileInputStream("c.txt"); //创建流对象,关联b.txt
- Vector<FileInputStream> v = new Vector<>(); //创建集合对象
- v.add(fis1); //存储流对象
- v.add(fis2);
- v.add(fis3);
- Enumeration<FileInputStream> en = v.elements(); //获取流对象
- SequenceInputStream sis = new SequenceInputStream(en); //传递给SequenceInputStream的构造函数
- FileOutputStream fos = new FileOutputStream("d.txt"); //创建流对象,关联c.txt
- int b;
- while((b = sis.read()) != -1) {
- fos.write(b);
- }
- sis.close();
- fos.close();
- }
- //整合两个文件
- private static void demo2() throws FileNotFoundException, IOException {
- FileInputStream fis1 = new FileInputStream("a.txt"); //创建流对象,关联a.txt
- FileInputStream fis2 = new FileInputStream("b.txt"); //创建流对象,关联b.txt
- SequenceInputStream sis = new SequenceInputStream(fis1, fis2); //创建流对象,把fis1和fis2整合成一个流对象
- FileOutputStream fos = new FileOutputStream("c.txt"); //创建流对象,关联c.txt
- int b;
- while((b = sis.read()) != -1) { //用SequenceInputStream读
- fos.write(b); //写到c.txt
- }
- sis.close(); //关流
- fos.close();
- }
- //普通的读写多个文件
- private static void demo1() throws FileNotFoundException, IOException {
- FileInputStream fis1 = new FileInputStream("a.txt");
- FileInputStream fis2 = new FileInputStream("b.txt");
- FileOutputStream fos = new FileOutputStream("c.txt");
- int b1;
- while((b1 = fis1.read()) != -1) {
- fos.write(b1);
- }
- int b2;
- while((b2 = fis2.read()) != -1) {
- fos.write(b2);
- }
- fis1.close();
- fis2.close();
- fos.close();
- }
- }
三.内存输出流
1.什么是内存输出流
该输出流可以向内存中写数据, 把内存当作一个缓冲区, 写出之后可以一次性获取出所有数据
2.使用方式
创建对象: new ByteArrayOutputStream()
写出数据: write(int), write(byte[])
获取数据: toByteArray()
- public class Demo2_ByteArrayOutputStream {
- /**
- * @param args
- * @throws IOException
- * 什么时候用ByteArrayOutputStream呢?
- * 当需要将内存当作缓冲区,而且是不断向内存中写数据的时候,比如发短信,聊qq,都是先将数据写到内存里
- * 再从内存将数据转换为字符串,写出
- */
- public static void main(String[] args) throws IOException {
- //demo1();
- FileInputStream fis = new FileInputStream("a.txt");
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- int b;
- while((b = fis.read()) != -1) {
- baos.write(b);
- }
- //byte[] arr = baos.toByteArray(); //将缓冲区的内容赋值给byte数组
- //System.out.println(new String(arr)); //将字节数组转换为字符串
- System.out.println(baos); //默认调用toString方法
- //String str = baos.toString();
- fis.close();
- }
- }
四.对象操作流
1.什么是对象操作流
该流可以将一个对象写出, 或者读取一个对象到程序中. 也就是执行了序列化和反序列化的操作.
2.使用方式
写出: new ObjectOutputStream(OutputStream), writeObject()
读取: new ObjectInputStream(InputStream), readObject()
3.注意
要写出的对象必须实现Serializable接口才能被序列化
(实现Serializable)
- import java.io.Serializable;
- public class Person implements Serializable {
- /**
- *
- */
- private static final long serialVersionUID = 3L; //可以加也可以不加,加就是为了让大家更清楚的看懂异常
- private String name;
- private int age;
- public Person() {
- super();
- }
- public Person(String name, int age) {
- super();
- 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 "Person [name=" + name + ", age=" + age + "]";
- }
- }
(1)序列化,将对象写到文件上
- import cn.itcast.bean.Person;
- public class Demo3_ObjectOutputStream {
- public static void main(String[] args) throws IOException {
- //demo1();
- ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c.txt")); //创建输出流对象
- Person p1 = new Person("张三", 23); //创建人对象
- Person p2 = new Person("李四", 24);
- ArrayList<Person> list = new ArrayList<>(); //创建集合对象
- list.add(p1); //将人添加到集合中
- list.add(p2);
- oos.writeObject(list); //写出集合对象
- oos.close(); //关流
- }
- private static void demo1() throws IOException, FileNotFoundException {
- Person p1 = new Person("张三", 23);
- //FileOutputStream fos = new FileOutputStream("b.txt");
- //fos.write(); 字节流不能写出对象
- //FileWriter fw = new FileWriter("b.txt");
- //fw.write(p1); 字符输出流不能写出对象
- ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("b.txt")); //创建对象输出流,关联b.txt
- oos.writeObject(p1); //写出一个对象
- oos.close();
- }
- }
(2)反序列化,将文件上数据读取出来
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.ObjectInputStream;
- import java.util.List;
- import cn.itcast.bean.Person;
- public class Demo4_ObjectInputStream {
- * @param args
- @throws IOException
- @throws FileNotFoundException
- @throws ClassNotFoundException
- public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
- //demo1();
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c.txt")); //创建对象输入流对象,关联c.txt
- List<Person> list = (List<Person>) ois.readObject(); //读取对象
- for (Person person : list) { //遍历集合
- System.out.println(person);
- }
- ois.close(); //关流
- }
- private static void demo1() throws IOException, FileNotFoundException,
- ClassNotFoundException {
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream("b.txt")); //创建对象输入流,关联b.txt
- Person p1 = (Person) ois.readObject(); //读取对象
- //Person p2 = (Person) ois.readObject(); //读取对象
- System.out.println(p1); //输出
- //System.out.println(p2); //输出
- ois.close();
- }
- }
五.打印流
1.什么是打印流
该流可以很方便的将对象的toString()结果输出, 并且自动加上换行, 而且可以使用自动刷出的模式
System.out就是一个PrintStream, 其默认向控制台输出信息
2.使用方式
打印: print(), println()
自动刷出: PrintWriter(OutputStream out, boolean autoFlush, String encoding)
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.PrintStream;
- import java.io.PrintWriter;
- import cn.itcast.bean.Person;
- public class Demo5_PrintStream {
- /**
- * @param args
- * @throws IOException
- * PrintWriter是打印字符流,可以自动刷出缓冲区的内容
- * 但是只针对于println
- */
- public static void main(String[] args) throws IOException {
- demo1();
- demo2();
- PrintStream ps = new PrintStream("e.txt");
- ps.println(97); //将97转换成字符串写出
- ps.write(97); //直接将97写出
- ps.close();
- }
- private static void demo2() throws FileNotFoundException {
- PrintWriter pw =
- new PrintWriter(newFileOutputStream("e.txt"),true);
- //pw.write("你好");
- //pw.close();
- pw.println("你好");
- //pw.print("你好");
- pw.close();
- }
- private static void demo1() {
- PrintStream ps = System.out;
- ps.println(97); //在打印97的时候,底层调用是Integer.toString(97)转换成字符串
- ps.println(new Person("张三",23));//当打印对象的时候,底层会调用String类里面valueOf方法
- Person p = null; //valueOf方法会对对象做判断,如果是null就返回null,如果对象有具体的值
- ps.println(p); //就调用该对象toString方法
- }
- }
六.标准输入输出流
1.什么是标准输入输出流
System.in是InputStream, 标准输入流, 默认可以从键盘输入读取字节数据
System.out是PrintStream, 标准输出流, 默认可以向Console中输出字符和字节数据
2.修改标准输入输出流
修改输入流: System.setIn(InputStream)
修改输出流: System.setOut(PrintStream)
- public class Demo6_SetInOut {
- /**
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- System.setIn(new FileInputStream("day23笔记.txt")); //改变标准输入流,指向的是day23笔记.txt
- System.setOut(new PrintStream("copy.txt")); //改变标准输出流,指向的是copy.txt
- InputStream is = System.in; //获取输入流
- PrintStream ps = System.out; //获取输出流
- int b;
- while((b = is.read()) != -1) { //到文件上逐个字节读
- ps.write(b); //将逐个字节写到文件上
- }
- is.close(); //关流
- ps.close();
- }
- }
七.数据输入输出流
1.什么是数据输入输出流
DataInputStream, DataOutputStream可以按照基本数据类型大小读写数据
例如按Long大小写出一个数字, 写出时该数据占8字节. 读取的时候也可以按照Long类型读取, 一次读取8个字节.
2.使用方式
DataInputStream(InputStream), readInt(), readLong()
DataOutputStream(OutputStream), writeInt(), writeLong()
- public class Demo7_DataOutputStream {
- /**
- * @param args
- * @throws IOException
- * 00000000 00000000 00000011 11100101
- * 00000000 00000000 00000000 11100101
- */
- public static void main(String[] args) throws IOException {
- //demo1();
- DataOutputStream dos = new DataOutputStream(new FileOutputStream("e.txt"));
- dos.writeInt(997); //写出一个int数
- dos.writeInt(998);
- dos.writeInt(999);
- dos.close();
- }
- private static void demo1() throws FileNotFoundException, IOException {
- FileOutputStream fos = new FileOutputStream("e.txt"); //创建输出流对象,关联e.txt
- fos.write(997); //写出一个字节,因为997超过byte的取值范围,所以会去掉前三个八位写出
- fos.write(998);
- fos.write(999);
- fos.close();
- }
- }
- public class Demo8_DataInputStream {
- /**
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- //demo1();
- DataInputStream dis = new DataInputStream(new FileInputStream("e.txt"));
- int x = dis.readInt(); //读取一个int数,读取到的是写入文件的
- int y = dis.readInt();
- int z = dis.readInt();
- System.out.println(x);
- System.out.println(y);
- System.out.println(z);
- dis.close();
- }
- private static void demo1() throws FileNotFoundException, IOException {
- FileInputStream fis = new FileInputStream("e.txt");
- int x = fis.read(); //读取到的不是原先写入的数据
- int y = fis.read();
- int z = fis.read();
- System.out.println(x);
- System.out.println(y);
- System.out.println(z);
- fis.close();
- }
- }
八.Properties
1.向内存中存入值,并通过键获取值setProperty(key,value) getProperty(key);
2.通过load方法,读取配置文件,propertyNames获取所有的key,返回Enumeration
3.根据键改值,并重新存入到配置文件setProperty(key,value),list(newPrintStream())
System.getProperties();获取系统属性,propertyNames将所有的键返回到枚举里,就可以迭代了
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.PrintStream;
- import java.util.Enumeration;
- import java.util.Properties;
- public class Demo9_Properties {
- /**
- * @param args
- * @throws IOException
- * @throws FileNotFoundException
- */
- public static void main(String[] args) throws FileNotFoundException, IOException {
- demo1();
- Properties prop = new Properties();
- prop.load(new FileInputStream("config.properties")); //通过load方法可以将配置文件的信息读取
- prop.setProperty("username", "lisi");
- prop.list(new PrintStream("config.properties")); //通过list方法将集合中的内容写回配置文件
- System.out.println(prop);
- }
- private static void demo1() {
- Properties prop = new Properties();
- prop.setProperty("username", "张三");
- prop.setProperty("password", "12345");
- prop.setProperty("qq", "54321");
- prop.setProperty("tel", "18987654321");
- //System.out.println(prop);
- Enumeration<?> en = prop.propertyNames();
- while(en.hasMoreElements()) {
- String key = (String) en.nextElement();
- String value = prop.getProperty(key);
- System.out.println(key + "=" +value);
- }
- }
- }
九.IO总结
1.字节流
FileInputStream, FileOutputStream, 自定义数组拷贝文件
BufferedInputStream, BufferedOutputStream, 内置缓冲区拷贝文件
2.字符流
FileReader, FileWriter
InputStreamReader, OutputStreamWriter
BufferedReader, BufferedWriter
会读写各种码表的文件中的文本数据