1.1教学目标
- 流的概念
- 流的分类
- 字节流
- 编码方式
- 字符流
- File类
1.2 什么是流
概念:内存与存储设备之间的传输数据的通道
1.3 流的分类
按方向(重点)
- 输入流:将<存储设备>中的内容读入到<内存>中。
- 输出流:将<内存>中的内容写入到<存储设备>中。
按单位:
- 字节流:以字节为单位,可以读写所有数据。
- 字符流:以字符为单位,只能读写文本数据。
按功能
- 节点流:具有实际传输数据的读写功能。
- 过滤流:在节点流的基础之上增强功能。
1.4字节流
- 字节流的父类(抽象类):
- InputStream:字节输入流
- OutputStream:字节输出流
文件字节流
-
FileInputStream:从文件系统中的某个文件中获得输入字节。哪些文件可取决于主机环境。
public int read(byte[] b)
//从流中读取多个字节,将读到的内容存入b数组,返回实际读到的字节数;如果达到文件的尾部,则返回-1。
package IO;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.List;
public class FileInput {
public static void main(String[] args) throws Exception {
//1创建FileInputSteam,并指定文件路径
FileInputStream file = new FileInputStream("/Users/tianzhi/Library/CloudStorage/OneDrive-zjnu.edu.cn/MarkDown/java/1.txt");
// //2.1 读取文件,每读一个打印一个,单个字节打印
// int data=0;
// while ((data=file.read()) !=-1){
// System.out.print(data);//读出来ASCII码,如231,252,97等
// System.out.print(" "+(char) data);//强转换,可以转成char
//
// }
//2.2 一次读取多个字节。即传入一个数组,这个数据作为留接收器,保存
// byte[] by = new byte[3];
// int count = file.read(by);
// System.out.println(new String(by));//abc
// System.out.println(count);//3
//2.3 用while循环读数组
byte[] buf = new byte[3];
int count = 0;
while ((count = file.read(buf)) != -1) {
System.out.println(new String(buf));
}
//3 关闭。
file.close();
System.out.println("执行关闭");
}
}
-
FileOutputStream:
一次写多个字节,将b数组中所有字节,写入输出流。
package IO;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
public class FileOut {
public static void main(String[] args) throws Exception {
//1创建文件字节输出流对象
FileOutputStream file = new FileOutputStream("/Users/tianzhi/Library/CloudStorage/OneDrive-zjnu.edu.cn/MarkDown/java/2.txt");
file.write(97);
file.write('b');
file.write('c');
String a="你好啊";
file.write(a.getBytes());
file.close();
}
}
字节流复制文件
package IO;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
public class FileOut {
public static void main(String[] args) throws Exception {
//1 创建流
//1.1 文件字节输入流
FileInputStream filein = new FileInputStream("/Users/tianzhi/Library/CloudStorage/OneDrive-zjnu.edu.cn/MarkDown/java/2.jpg");
//1.2 文件字节输出流
FileOutputStream fileout = new FileOutputStream("/Users/tianzhi/Library/CloudStorage/OneDrive-zjnu.edu.cn/MarkDown/java/2-copy.jpg");
//2一边读,一边写
byte[] buf=new byte[1024];
int count = 0;
while ((count=filein.read(buf))!=-1){
fileout.write(buf,0,count);//因为有些末尾不是-1的,会保留,所以要用这个
}
filein.close();
fileout.close();
}
}
字节缓冲流
- 缓冲流:BufferedInputStream/BufferedOutputStream
- 提高IO效率,减少访问磁盘的次数。
- 数据存储在缓冲区中,
flush
是将缓存区的内容写入文件中,也可以直接close。
//BufferedInputStream
package IO;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class FileOut {
public static void main(String[] args) throws Exception {
//1创建BufferedInputStream
FileInputStream file = new FileInputStream("/Users/tianzhi/Library/CloudStorage/OneDrive-zjnu.edu.cn/MarkDown/java/1.txt");
BufferedInputStream bufile = new BufferedInputStream(file);
//2读取
int data=0;
while ((data=bufile.read()) != -1){
System.out.println((char)data);
}
//3 关闭
bufile.close();
}
}
//BufferedOutputStream
package IO;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class FileOut {
public static void main(String[] args) throws Exception {
//1创建字节输出缓冲流
FileOutputStream fileout = new FileOutputStream("/Users/tianzhi/Library/CloudStorage/OneDrive-zjnu.edu.cn/MarkDown/java/3.txt");
BufferedOutputStream bufileout = new BufferedOutputStream(fileout);
//2写入文件
for (int i = 0; i < 10; i++) {
bufileout.write("hello".getBytes());
bufileout.flush();//刷新到本地的硬盘
}
// bufileout.close();//也可以直接关闭
}
}
1.5对象流
对象流:ObjectOutputStream/ObectInputStream
- 增强了缓冲区功能
- 增强了读写8种基本数据类型和字符串功能
- 增强了读写对象的功能。
readObject
从流中读取一个对象;writeObject(Object obj)
向流中写入一个对象
使用流传输对象的过程称为序列化,反序列化。
序列流
//Student类 class 必须 加上 implements Serializable
package IO;
import java.io.*;
import java.nio.charset.StandardCharsets;
import base.Student;
import base.Student;
public class FileOut {
public static void main(String[] args) throws IOException {
//1 创建流
FileOutputStream fos = new FileOutputStream("/Users/tianzhi/IdeaProjects/untitled/src/IO/1.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2 序列化(写入操作)
Student s1 = new Student("张三","12");
Student s2 = new Student("李四","14");
oos.writeObject(s1);
oos.writeObject(s2);
//3 关闭
oos.close();
}
}
反序列化
import base.Student;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class ObjectInput {
public static void main(String[] args) throws Exception {
//1创建流
FileInputStream file = new FileInputStream("/Users/tianzhi/IdeaProjects/untitled/src/IO/1.bin");
ObjectInputStream ois = new ObjectInputStream(file);
//2读取文件(反序列化)
Student s = (Student) ois.readObject();
//3 关闭
ois.close();
System.out.println(s.toString());
}
}
序列化和反序列化注意事项
-
序列化类必须要实现
Serializable
接口 -
序列化类中对象属性要求实现
Serializable
接口
private static final long serialVersionUID = 1L;
serialverisonUID
是序列化版本号ID,保证序列化的类和反序列化是同一个类 -
使用
transient
修饰属性,这个属性不可以序列化 -
静态属性不能书序列化
-
序列化多个对象,可以借助集合实现
1.6 字符编码
-
ISO-8859-1收录除ASCII外,还包括秀,希腊语,泰语,阿拉伯语,希伯来语对应的文字符号。
-
UTF-8针对Unicode码表的可变长度字符编码。 1、2、3个字节
-
GB2312 简体中文 ;1个字节或者2个字节
-
GBK 简体中文、扩充
-
BIG5 台湾,繁体中文
当编码方式和解码方式不一致时,会出现乱码
1.7 字符流
- 字符流的父类(抽象类)
- Reader:字符输入流
- Writer:字符输出流
文件字符流
-
FileReader:
public int read(char[] c )
从流中读取多个字符,将读到内容存入C数组,返回实际读到的字符串;如果达到文件的尾部,则返回-1
package IO;
import base.Student;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.ObjectInputStream;
public class ObjectInput {
public static void main(String[] args) throws Exception {
//1 创建FileReader 文件字符输入流
FileReader fr = new FileReader("/Users/tianzhi/Library/CloudStorage/OneDrive-zjnu.edu.cn/MarkDown/java/1.txt");
//2 读取
//2.1 单个字符读取
// int data=0;
// while ((data=fr.read()) !=-1){
// System.out.print((char) data);
// }
//2.2 数组读取
char[] ch = new char[1024];
int num = 0;
while ((num=fr.read(ch))!=-1){
System.out.println(new String(ch,0,num));
}
System.out.println("===");
}
}
-
FileWriter:
public void wirite(String str)
//一次写入多个字符,将b数组中所有字符,写入输出流。
package IO;
import base.Student;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.ObjectInputStream;
public class ObjectInput {
public static void main(String[] args) throws Exception {
//1 创建FileWrite对象
FileWriter fw = new FileWriter("/Users/tianzhi/IdeaProjects/untitled/src/IO/1.txt");
//2 写入
for (int i = 0; i < 10; i++) {
fw.write("你好啊\r\n");
fw.flush();
}
fw.close();
}
}
字符流复制文件
package IO;
import base.Student;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.ObjectInputStream;
public class ObjectInput {
public static void main(String[] args) throws Exception {
//1 创建对象
FileReader fr = new FileReader("/Users/tianzhi/IdeaProjects/untitled/src/IO/1.txt");
FileWriter fw = new FileWriter("/Users/tianzhi/IdeaProjects/untitled/src/IO/1-copy.txt");
//2 读写
int data=0;
while ((data=fr.read())!=-1){
fw.write(data);
fw.flush();
}
fr.close();
fw.close();
}
}
字符缓冲流
- 缓冲流:BufferedReader/BufferedWriter
- 高效读写
- 支持输入换行符。
- 可一次写一行,读一行。
//BufferedReader
package IO;
import base.Student;
import java.io.*;
public class ObjectInput {
public static void main(String[] args) throws Exception {
//1 创建对象
FileReader fr = new FileReader("/Users/tianzhi/IdeaProjects/untitled/src/IO/1.txt");
BufferedReader br = new BufferedReader(fr);
//2.2 单个读写
// int data=0;
// while ((data=br.read())!=-1){
// System.out.print((char)data);
// }
//2.2 多个读写
// char[] buf= new char[1024];
// int count=0;
// while ((count=br.read(buf))!=-1){
// System.out.println(new String(buf,0,count));
// }
//2.3 一行一行读写
String line = null;
while ((line=br.readLine()) !=null){
System.out.println(line);
}
br.close();
fr.close();
}
}
//BufferedWiter
package IO;
import base.Student;
import java.io.*;
public class ObjectInput {
public static void main(String[] args) throws Exception {
//1 创建对象
FileWriter fw = new FileWriter("/Users/tianzhi/IdeaProjects/untitled/src/IO/1.txt");
BufferedWriter bw = new BufferedWriter(fw);
//2 写入
for (int i = 0; i < 10; i++) {
bw.write("好好学习,天天向上");
bw.newLine();//写入一个换行符 win \r\n linux \n
}
//3 关闭
bw.close();
}
}
1.8打印流
-
PrinterWriter
-
封装了print() / println() 方法,支持写入后换行
-
支持数据原样打印
-
1.9 转换流
桥转换流: InputStreamReader
和 OutputSteamWriter
- 可以将字节流转换为字符流
- 可设置字符的编码方式。
InputStreamReader:是字节流通向字符流的桥梁。把硬盘的字节写入到内存中。
package IO;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
public class FileInput {
public static void main(String[] args) throws Exception {
//创建流
FileInputStream fis = new FileInputStream("/Users/tianzhi/IdeaProjects/untitled/src/IO/1.txt");
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
//读取文件
int count=0;
while ((count=isr.read())!=-1){
System.out.println(count);
}
//关闭
isr.close();
}
}
OutputSteamWriter:是字符流通向字节流的桥梁。把内存的字符写入到硬盘上。
package IO;
import java.io.*;
import java.util.Arrays;
import java.util.List;
public class FileInput {
public static void main(String[] args) throws Exception {
//1创建OutputStreamWriter
FileOutputStream fos = new FileOutputStream("/Users/tianzhi/IdeaProjects/untitled/src/IO/1-copy3.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
//2 写入
for (int i = 0; i < 10; i++) {
osw.write("我爱北京");
osw.flush();
}
osw.close();
}
}
2.0 File类
- 概念:代表物理盘符中的一个文件或者文件夹。
- 方法
createNewFile()//创建一个新文件
mkdir()//创建一个新目录
delete()//删除文件或者空目录
existes()//判断File对象所对象所代表的对象是否存在
getAbsolutePate()//获取文件的绝对路径
getName()//获取名字
getParent()//获取文件/目录所在的目录
idDirectory()//是否是目录
isFile()//是否是文件
length()//获取文件的长度
listFiles()//列出目录中的所有内容
renameTo()//修改文件名为
//文件操作
package IO;
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class FileDemo {
public static void main(String[] args) throws IOException, InterruptedException {
//1 分隔符
System.out.println("路径分隔符" + File.pathSeparator);
System.out.println("名称分隔符" + File.separator);
//2 文件操作
//2.1 创建文件
File file = new File("../3.txt");
System.out.println(file.toString());// 路径/Users/tianzhi/IdeaProjects/untitled/src/IO/2.txt
if (!file.exists()) {
boolean b = file.createNewFile();
System.out.println("创建文件结果" + b);
}
//2.2删除文件
// boolean del = file.delete();
// System.out.println("删除结果"+del);
// Thread.sleep(5000);
//2.2.2使用jvm退出时删除
// file.deleteOnExit();
//3获取文件信息
System.out.println("获取文件的绝对路径"+file.getAbsoluteFile());//获取绝对路径/Users/tianzhi/IdeaProjects/untitled/3.txt
System.out.println("获取路径"+file.getPath());//获取的是相对路径
System.out.println("获取名称"+file.getName());//获取的名称
System.out.println("获取父目录"+file.getParent());//获取父目录
System.out.println("获取文件长度"+file.length());//获取文件长度
System.out.println("文件创建时间"+new Date(file.lastModified()).toLocaleString());//获取文件创建时间
//4判断
System.out.println("文件是否可读"+file.canRead());
System.out.println("是否是文件"+file.isFile());
System.out.println("是否隐藏"+file.isHidden());
}
}
//文件夹操作
package IO;
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class FileDemo {
public static void main(String[] args) throws Exception {
//1创建文件夹
File dir = new File("/Users/tianzhi/IdeaProjects/untitled/src/IO/ces");
System.out.println(dir.toString());
if (!dir.exists()) {
System.out.println("创建结果" + dir.mkdir());//只能创建单级目录
// dir.mkdirs();//创建多级目录
}
//2删除文件夹
// System.out.println("删除结果"+dir.delete());//注意删除空目录
// //2.1 使用jvm删除
// dir.deleteOnExit();
//3 获取文件夹信息,同文件。这里不不写了
System.out.println("获取文件夹的绝对路径" + dir.getAbsoluteFile());//获取绝对路径/Users/tianzhi/IdeaProjects/untitled/3.txt
System.out.println("获取路径" + dir.getPath());//获取的是相对路径
System.out.println("获取文件夹名称" + dir.getName());//获取的名称
System.out.println("获取父目录" + dir.getParent());//获取父目录
System.out.println("文件创建时间" + new Date(dir.lastModified()).toLocaleString());//获取文件创建时间
//4判断
System.out.println("是否是文件夹" + dir.isDirectory());
System.out.println("是否隐藏" + dir.isHidden());
//5遍历文件夹
File dir2 = new File("");//设定为当前目录
String[] files = dir2.listFiles();
for (String x : files) {
System.out.println(x);
}
}
}
2.1 FileFilter接口
public interface FileFilter
boolean accept(File pathname)
当调用File类中的listFiles()方法时,支持传入FileFilter接口实现类,对获取文件进行过滤,只有满足条件的文件才可以出现在listFiles()的返回值中。
File[] out = dir2.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.getName().endsWith(".jpg")) {
return true;
}
return false;
}
});
for (File file:out){
System.out.println(file.getName());
}
2.2 递归遍历和递归删除
递归遍历文件夹
package IO;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Date;
public class FileDemo {
public static void main(String[] args) throws Exception {
deleteDir(new File("/Users/tianzhi/IdeaProjects/untitled/src/IO/ces"));
}
//遍历文件夹
public static void listDir(File dir) {
File[] files = dir.listFiles();
if (files != null && files.length > 0)
for (int i = 0; i < files.length; i++) {
if (!files[i].isDirectory()) {
System.out.println(files[i].getName() + files[i].getAbsoluteFile());
}else {
listDir(new File(files[i].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{
System.out.println(file.getAbsoluteFile()+"删除"+file.delete());
}
}
}
dir.delete();
}
}
2.3 Properties
Properties
:属性集合
特点:
1. 存储属性名和属性值
2. 属性名和属性值都是字符串类型
3. 没有泛型
4. 和流有关
package IO;
import java.io.*;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import static java.lang.System.out;
public class FileDemo {
public static void main(String[] args) throws IOException {
//1创建集合
Properties properties = new Properties();
//2添加数据
properties.setProperty("username","zhangsan");
properties.setProperty("age","20");
out.println(properties.toString());
//3遍历
out.println("====方法1");
for (Object x:properties.keySet()){
out.println((String) x);
}
out.println("=====方法2");
Set<Map.Entry<Object, Object>> entries = properties.entrySet();
for (Map.Entry<Object,Object> x: entries){
out.println(x.getKey()+":"+x.getValue());
}
//3.3------stringProperyNames()---
Set<String> pro = properties.stringPropertyNames();
for (String x:pro){
out.println(x+":"+properties.getProperty(x));
}
//4 和流有关的方法
//----list-----
PrintWriter printWriter = new PrintWriter("/Users/tianzhi/IdeaProjects/untitled/src/IO/1.txt");
properties.list(printWriter);
printWriter.close();
//5 2 store 保存
FileOutputStream fot = new FileOutputStream("/Users/tianzhi/IdeaProjects/untitled/src/IO/1-stream.txt");
properties.store(fot,"注释");
fot.close();
//5 load加载办法
Properties proper = new Properties();
FileInputStream fileinputstream = new FileInputStream("/Users/tianzhi/IdeaProjects/untitled/src/IO/1-stream.txt");
proper.load(fileinputstream);
System.out.println(proper);
}
}
2.4总结
- 流的概念:内存与存储设备之间传输数据的通道。
- 流的分类:输入流、输出流;字节流,字符流;节点流、过滤流
- 序列化、反序列化:
- 将对象通过流写入到文件,或将回想通过流读取到内存,必须实现Serializable接口
- File对象:代表物理盘符的文件