I/O 框架
流的概念
概念:内存与存储设备之间传输数据的通道
数据借助流传输
流的分类
-
按方向【重点】
- 输入流:将<存储设备>中的内容读入到<内存>中
- 输出流:将<内存>中的内容写入到<存储设备>中
-
按单位
- 字节流:以字节为单位,可以读写所有数据
- 字符流:以字符为单位,只能读写文本数据
-
按功能
- 节点流:具有实际传输数据的读写功能
- 过滤流:在节点流的基础之上增强功能
字节流
- 字节流的父类(抽象类)
- InputStream: 字节输入流
- OutputStream: 字节输出流
文件字节流
-
FileInputStream:
- public int read(byte[] b)//从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数;如果达到文件的尾部,则返回-1
-
FileOutputStream
- public void write(byte[] b)//一次写入多个字节,将b数组中所有字节,写入输出流
/*
FileInputStream 的使用
*/
//文件不一定存在,会有异常 先创建文件内容为abcdefg
public static void main(String[] args) throws Exception{
//创建对象,指定路径
FileInputStream fis=new FileInputStream("d:\\aaa.txt");
//单个字节读取
int data=0;
while((date=fis.read())!=-1){
System.out.print((char)data);
}
//关闭文件
fis.close();
//多个字节读取
byte[] buf = new byte[3];
// int count=fis.read(buf); //返回值是读取的个数
int count=0;
while((count=fis.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}
}
/*
FileOutputStream
*/
public static void main(String[] args) throws Exception{
//创建文件字节输出流对象
FileOutputStream fos = new FileOutputStream("d\\bbb.txt");
//传入参数 除了文件路径外 还有true 不会覆盖文件
//写入文件
fos.write(97); //a
fos.write('b');
//会覆盖 ab
String str= "helloworld";
fos.write(str.getBytes());
//关闭
fos.close();
}
字节缓存流
- 缓存流:BufferedInputStream/BufferedOutputStream
- 提高IO效率,减少访问磁盘的次数
- 数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close.
/*
使用字节缓冲流读取
*/
public static void main(String[] args) throw Exception{
//创建BufferedInputStream
FileInputStream fis=new FileInputStream("d:\\aaa.txt");
BufferedInputStream bis=new BufferedInputStream(fis);
//读取
int data=0;
while((data=bis.read())!=-1){
System.out.print((char)data);
}
//关闭
bis.close();//默认会把文件字节流也关闭
}
//也可以自己创建缓冲区
/*
字节缓冲流写入文件
*/
public static void main(String[] args) throws Exception{
//创建字节输出
FileOutputStream fos=new FileOutputStream("d:\\buffer.txt");
BufferedOutputStream bos=new BufferedOutputStream(fos);
//写入文件
for(int i=0;i<10;i++){
bos.write("helloworld\n".getBytes());//写入8k缓冲区
bos.flush();//刷新到硬盘
}
//关闭
bos.close();//内部调用flush方法
}
对象流
- ObjectOutputStream/ObjectInputStream
- 增强了缓冲区功能
- 增强了读写8种基本数据类型和字符串功能
- 增强了读写对象的功能
使用流传输对象的过程称为序列化、反序列化
创建好Student类 属性 为name ,age
必须要实现 接口Serializable使用接口就行
序列化(写入对象)
/*
ObjectOutputStream
要求序列化的类必须实现 接口Serializable
*/
public static void main(String[] args) throws Exception{
//创建对象
FileOutputStream fos=new FileOutputStream("d:\\stu.bin");
ObjectOutputStream oos=new ObjectOutputStream(fos);
//序列化
Student zhangsan=new Student("张三",23);
oos.writeObject(zhangsan);
//关闭
oos.close();
}
反序列化(读取对象)
/*
ObjectInputStream
*/
public static void main(String[] args) throws Exception{
//创建流
FileInputStream fis=new FileInputStream("b:\\stu.bin");
ObjectInputStream ois=new ObjectInputStream(fis);
//读取文件。反序列化
Student s= (Student)ois.readObject();
//只有一个对象读多个会异常
System.out.println(s.toString());
ois.close()
}
注意事项
1)序列化类必须事项Serializable接口
2)序列化类中对象属性要求实现Serializable接口
3)序列化版本号ID,保证序列化的类和反序列化的类是同一个类
4)使用transient(瞬间的)修饰属性,这个属性不能序列化了
5)静态属性也不能序列化
6)序列化多个对象,可以把对象放到集合里面。序列化集合就可以
编码方式
- ISO-8859-1 收录除了ASCII外,西欧、希腊、泰国、阿拉伯、希伯来对应的文字符号
- UTF-8 针对Unicode码表的可变长度字符编码
- GB2312 简体中文
- GBK 简体中文、扩充
- BIG5 台湾,繁体
当编码方式和解码方式不一样 就会出现乱码
字符流
字节流读取中文 会出现乱码
- 字符流的父类(抽象类)
- Reader:字符输入流
- Writer:字符输出流
文件字符流
- FileReader:
- public int read(char[] c)//从流中读取多个字符,将读到内容存入c数组,返回实际读到的字符数;如果读到文件的尾部,则返回-1
- FileWriter
- public void write(String str);//一次写入多个字符,将b数组中所有字符,写入输出流
不能复制 图片,声音等二进制编码的文件
字节流可以复制任意文件
/*
FileReader
*/
public static void main(String[] args) throws Exception{
//创建
FileReader fr=new FileReader("d:\\hello.txt");
//读取
//单个字符读取
int data=0;
while((data=fr.read())!=-1){ //读取一个字符
System.out.print((char)data);
}
//用缓冲区
char[] buf=new char[1024];
int count=0;
while((count=fr.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}
//关闭
fr.close();
}
/*
FileWriter
*/
public static void main(String[] args)throws Exception{
//创建对象
FileWriter fw=new FileWriter("d:\\write.txt");
//写入
for(int i=0;i<5;i++){
fw.write("我真棒!\r\n");
fw.flush();
}
//关闭
fw.close();
}
字符缓存流
- BufferedReader/BufferedWriter
- 高效读写
- 支持输入换行符
- 可以一次写一行、读一行
/*
BufferedReader
*/
public static void main(String[] args)throws Exception{
//创建对象
FileReader fr=new FileReader("d:\\write.txt");
BufferedReader br=new BufferedReader(fr);
//读取
char[] buf=new char[1024];
int count=0;
while((count=br.read(buf))!=-1){
System.out.print(new String(buf,0,count));
}
//一行一行读
String line=null;
while((line= br.readLine())!=-1){
System.out.println(line);
}
//关闭
br.close();
}
/*
BufferedWriter
*/
public static void main(String[] args)throws Exception{
//创建对象
FileWriter fw=new FileWriter("d:\\buffer.txt");
BufferedWriter bw=new BufferedWriter(fw);
//写入
for(int i=0;i<5;i++){
bw.write("我真厉害");
bw.newLine();//写入一个换行符
bw.flush();
}
//关闭
bw.close();
}
打印流
- PrintWriter:
- 封装了 print()/println()方法,支持吸入后换行
- 支持数据原样打印
/*
PrintWriter
*/
public static void main(String[] args) throws Exception{
PrintWriter pw =new PrintWriter("d:\\print.txt");
//打印数据
pw.println(97);
pw.println(true);
pw.println(3.14);
pw.println('a');
//关闭
pw.close();
}
转换流
- 桥转换流:InputStreamReader / OutputStreamWriter
- 可将字节流转换为字符流
- 可设置字符的编码方式
//InputStreamReader读取文件,指定编码
FileInputStream fis=new FileInputStream("d:\\write.txt");
InputStreamReader isr=new InputStreamReader(fis,"utf-8");
//读取文件
int data=0;
while((data=isr.read())!=-1){
System.out.print((char)data);
}
//关闭
isr.close();
//OutputStreamWriter 写入文件 使用指定编码
FileOutputStream fos=new FileOutputStream("d:\\info.txt");
OutputStreamWriter osw=new OutputStreamWriter(fos,"gbk");
//写入
for(int i=0;i<10;i++){
osw.write("我是最胖的\r\n");
osw.flush();
}
//关闭
osw.close();
File类
- 代表物理盘符中的一个文件或者文件夹
/*
File 类的使用
分隔符
文件操作
文件夹操作
*/
public static void main(String[] args){
separator();
fileOpe();
}
public static void separator(){
System.out.println("路径分隔符"+File.pathSeparator);//;
System.out.println("名称分隔符"+File.separator);// /
}
//文件操作
public static void fileOpe() throws Exception{
//创建文件
File file=new File("d:\\file.txt");
//判断文件是否已经存在,不存在就创建
if(!file.exists()){
boolean b=file.createNewFile();
}
//删除文件
//1.直接删除
boolean f=file.delete();
//2.使用jvm退出时删除
file.deleteOnExit();
//获取文件信息
//绝对路径
file.getAbsolutePath();
//获取路径
file.getPath();
//获取文件名称
file.getName();
//获取父目录
file.getParent();
//获取文件长度
file.length();
//创建时间
new Date(file.lastModified().toLocaleString());
//判断
//是否可写
file.canWrite();
//是不是分件
file.isFile();
//是否隐藏
file.isHidden();
}
//文件夹操作
public static void directoryOpe() throws Exception{
//创建
File dir=new File("d:\\aaa\\bbb\\ccc");
if(!dir.exisits()){
//dir.mkdir();//只能创建单级目录
dir.mkdirs();//创建多级目录
}
//删除文件夹
//直接删除 只删除 最底层ccc ,而且必须是空目录
dir.delete();
//使用jvm删除
dir.deleteOnExit();
//获取文件夹信息
//绝对路径
dir.getAbsolutePath();
//路径
dir.getPath();
//文件夹名称 最底层
dir.getName();
//父目录
dir.getParent();
//创建时间
new Date(dir.lastModified()).toLocaleString();
//判断
//是否是文件夹
dir.isDirectory();
//是否隐藏
dir.isHidden();
//遍历文件夹
File dir2=new File("d:\\图片");
String[] files=dir2.list();
for(String s : files){
System.out.println(s);
}
}
FileFilter 接口
- public interface FIleFilter
- boolean accept(File pathname)
- 当调用File类中的listFiles()方法时,支持传入File Filter接口实现类,对获取文件进行过滤,只有满足条件的文件才能出现在listFiles()的返回值中
File dir2=new File("d:\\图片");
File[] files=dir2.listFiles(new FileFilter(){
public boolean accept(File pathname){
//只有 jpg格式的文件
if(pathname.getName().endsWith(.jpg)){
return true;
}
return false;
}
});
for(File s : files){
System.out.println(s);
}
//递归遍历文件夹
public static void main(String[] args){
listDir(new File("d:\\myfiles"));
}
public static void listDir(File dir){
File[] files=dir.listFiles();
System.out.println(file.getAbsolutePath())
if(files!= null && files.length>0){
for(File file : files){
if(file.isDirectory()){
listDir(file);
}else{
System.out.println(file.getAbsolutePath());
}
}
}
}
//递归删除目录
public static void deleteDir(File dir){
File[] files=dir.listFiles();
if(files!= null && files.length>0){
for(File file : files){
if(file.isDirectory()){
deleteDir(file);
}else{
files.delete();
}
}
}
dir.delete();
}
补充:Properties
属性集合
特点:
- 存储属性名和属性值
- 属性名和属性值都是字符串类型
- 没有泛型
- 和流有关
//创建
Properties ps=new Properties();
//添加数据
ps.setPeoperty("username","zhangsan");
ps.setPeoperty("age","20");
//遍历
//1 keySet
//2 entrySet
//3 stringPropertyNames()
Set<String> prs=ps.stringPropertyNames();
for(String pro : prs){
System.out.println(pro+prs.getProperty(pro));
}
//和流有关的方法
PrintWriter pw =new PrintWriter("d:\\print.txt");
prs.list(pw);
pw.close();
//保存
FileOutputStream fos=new FileOutputStream("d:\\store.properties");
prs.store(fos,"zhushi");
fos.close();
//load方法 加载
Properties prs2=new Properties();
FileInputStream fis=new FileInputStream("d:\\store.properties");
prs2.load(fis);
fis.close();
System.out.println(prs2.toString());