一.字符流
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
会读写各种码表的文件中的文本数据
3.File
掌握文件夹递归
拷贝一个带内容的文件夹