- 文件流:文件在程序中以流的形式操作
输入流:数据输入程序(内存)的路径输出流:数据从程序(内存)输出的路径 创建文件对象及相关操作
File file = new File(String path); //根据路径创建对象 File file = new File(String parent,String child); //父目录文件+子路径 File file = new File(File parent,String child); //父目录+子路径 //此时file还在内存中 file.createNewFile(); //执行该方法后才会真正的在磁盘创建该文件 //在IO中目录也会被当作一种file file.delete() //删除文件或空目录,返回为boolean file.mkdir(); //创建目录,返回为boolean file.mkdirs() //创建多级目录,返回为boolean
File实现了Serializable(串行化)和Comparable(比较)接口
流的分类
按照操作数据单位分为:字节流(按字节处理,8bit,保证二进制文件的操作不损失),字符流(按字符为单位处理,比如操作文本文件)
按照数据流向:输入流,输出流
字节流分为字节输入流和字节输出流:InputStream和OutputStream
字符流也分为输入输出:Reader和Writer
IO流涉及40多个类都是从上面4个抽象基类派生的
InputStream 该抽象类是所有类字节输入流的超类
FileInputStream:文件输入流
BufferedInputStream:缓冲字节输入流
ObjectInputStream:对象字节输入流
转换:InputStreamReader、OutputStreamWriter
FileInputStream使用FileInputStream fileInputStream = null; //为了能在finally中关闭流,如果在try中声明,finally就无法获得这个对象
byte[] buf = new byte[8];
int readLen = 0; //记录读取到多少字节
try {//操作
fileInputStream = new FileInputStream(filePath);
while ((readLen = fileInputStream.read(buf)) != -1) {
System.out.print(new String(buf, 0, readLen));//显示
//注意这里如果读取的文件有中文,一个字占2/3个字节,因为一组一组读取(包括一个字节一个字节读取,一个字节一个字节转化为字符)因为是把这一段读取的字节转化为字符,所以很有可能出现乱码情况(一个字节读取的肯定会出现乱码)
}
}catch(IOException e){ e.printStackTrace(); //异常
}finally{
fileInputStream.close(); //关闭文件流,释放资源
}
FileOutputStream
//char-->int char会自动转为int
String str = "world!";
str.getBytes() //可以把 字符串-> 字节数组
fileOutputStream.write(str.getBytes());
FileOutputStream fileOutputStream = null;
try {
fileOutputStream=new FileInputStream(path);
fileOutputStream.write("hello".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
fileOutputStream.close();
}
FileWriter
new FileWriter(File/String) 覆盖模式new FileWriter(File/String,true) 追加模式FileWriter使用后,必须要关闭(close())或者刷新(flush()),否则内容还在内存中,没写入指定文件 节点流和处理流
节点流是直接从文件(数据源)连接,进行读取/写入。处理流(也叫包装流)是在已存在的流之上进行包装以提供更强大的读写功能,消除各种流的差异,不直接与数据源相连。以bufferedReader为例
public class BufferedReader extends Reader {
private Reader in;
……
}
定义了一个Reader型变量,因此可以接受所有Reader的子类,包括FileReader,CharArrayReader等。这种定义基类变量接收所有子类的模式成为装饰器模式
为对象动态添加功能
装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component),具体组件的方法实现不需要依赖于其它对象,而装饰者组合了一个组件,这样它可以装饰其它装饰者或者具体组件
使用处理流时,最后关闭只需要关闭处理流即可(处理流内部关闭包装的节点流)注意插入时换行 对象处理流
ObjectInputStream 和 ObjectOutputStream 处理流,也是修饰器模式,传入InputStream/OutputStream 进行处理
对基本数据类型或对象进行序列化和反序列化的操作
序列化:保存数据时,保存数据的值和类型
反序列化:保存数据时,恢复数据的值和类型
如果相让某个对象支持序列化,则其类是可序列化的,这种类必须实现下面两个接口之一
Serializable //这是一个标记接口,接口里没有方法,推荐使用Externalizable //使用该接口需要实现接口的方法
ObjectOutputStream
String filePath = "e:\data.dat"; //序列化后的文件有特定格式.dat
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//基本类型会自动封箱,转化的对象都是实现了Serializable接口的
oos.writeInt(100);// int -> Integer (实现了 Serializable)
oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)
oos.writeChar('a');// char -> Character (实现了 Serializable)
oos.writeDouble(9.5);// double -> Double (实现了 Serializable)
//String类型保存
oos.writeUTF("韩顺平教育");//String
//保存一个 dog 对象 注意!!!!!Dog对象要序列化才能够被保存
oos.writeObject(new Dog("旺财", 10, "日本", "白色"));
oos.close();
注意:写入的对象是要能支持序列化的,所以写入的对象都要实现接口
ObjectInputStream
反序列化的读取顺序一定要和保存的数据顺序一致,注意读取对象时,如果希望对象输出具体内容,需要重写toString()方法,想要调用对象中的方法,需要向下转型,且对象的类要能被引用到。
// 1.创建流对象
ObjectInputStream ois =
new ObjectInputStream(new FileInputStream("src\data.dat"));
// 2.读取, 注意顺序
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
//读取对象
Object dog=ois.readObject(); //Dog的编译类型是Object,运行类型是Dog
//如果想要调用Dog中定义的方法,需要向下转型,且这个Dog类要能被引用到
Dog dog2=(Dog)dog;
System.out.println(dog2.getName());
// 3.关闭
ois.close();
private static final SerialVersionUID 用来提高版本的兼容性,修改该类是认为是版本的改变而不是一个新的类实现Serializable的类默认所有属性序列化,除了static或transient修饰的成员序列化的对象里,如果属性有其他对象,要求这个对象的类也要实现序列化接口序列化是可继承的,如果一个类实现了序列化,则子类也默认实现序列化 标准输入流输出流
public final class System{
public final static InputStream in = null;
public final static PrintStream out = null;
}
System.in //标准输入,默认键盘
//System.in 编译类型为 InputStream
//System.in 运行类型为 BufferedInputStream
System.out //标准输出,默认显示器
//System.out 编译类型为 PrintStream
//System.out 运行类型为 BufferedInputStream
转换流
包括InputStreamReader和OutputStreamWriter,将字节流转换成字符流。
为什么不直接用字符流:因为字符流默认UTF-8编码,如果要处理的文件不是这种编码,会出现乱码问题,因此使用转换流,指定编码格式写入/读取,转为对应的字符流,这样可以避免乱码问题
String file="F:\a.txt"; InputStreamReader isr=new InputStreamReader(new FileInputStream(file), "GBK"); BufferedReader buffer=new BufferedReader(isr); buffer.close();//关闭外层流打印流
包括PrintStream和PrintWriter
打印流只有输出流没有输入流
PrintStream out = System.out;
out.print("john, hello"); //因为 print 底层使用的是 write , 所以也可以直接调用 write 进行打印/输出
out.write("韩顺平,你好".getBytes()); out.close();
//通过打印流修改输出位置
System.setOut(new PrintStream("e:\f1.txt")); System.out.println("hello");
Properties类
专门用于读取配置文件的集合类,要求配置文件的格式为:键=值 (没有空格,没有引号)
Properties 父类是 Hashtable , 底层就是 Hashtable 核心方法
Properties properties = new Properties();
properties.load(new FileReader(path));//加载
properties.list(System.out); //显示
String user = properties.getProperty("user");
properties.setProperty("user", "汤姆");//注意保存时,是中文的 unicode 码值
properties.setProperty("pwd", "888888");
properties.store(new FileOutputStream("src\mysql2.properties"), null); //将 k-v 存储到文件中



