1.流的概念和分类
1.1 流的概念
概念:内存和存储设备之间传输数据的通道。
1.2 流的分类
1.按照方向分类:
- 输入流:将<存储设备>中的内容读入<内存>中。
- 输出流:将<内存>中的内容写入<存储设备>中。
2.按照单位分类:
- 字节流:以字节为单位,可以读写所有数据。
- 字符流:以字符为单位,只能读写文本数据。
3.按照功能分类:
- 节点流:具有实际传输数据的读写功能。
- 过滤流:在节点流的基础之上增强功能。
2.字节流
2.1 字节流的抽象类(父类)
1.InputStream:字节输入流(抽象类)
2.OutputStream:字节输出流(抽象类)
2.2 文件字节流(子类)
2.2.1 FileInputStream
文件字节输入流 FileInputStream
1.构造方法:
//构造方法
public int read(){}; //读取字节,每次读取1个
public int read(byte[] b){};//从流中读取多个字节,将读到的内容存入b 数组,返回实际读到的字节数;如果到达文件尾部,则返回 -1;
public int read(byte[] b, int off, int len){}; //读取字节,放入数组b中,从第off个开始放,长度为len
2.FileInputStream 代码示例:
public static void main(String[] args) throws IOException {
//1.创建FileInputStream,并制定文件路径
FileInputStream fis = new FileInputStream("C:\\Users\\Public\\Documents\\aaa.txt");
//2.读取文件,一次读取3个字节,
byte[] bytes = new byte[3];
int count;
while ((count=fis.read(bytes)) != -1){
System.out.println(count);
System.out.println(new String(bytes,0,count));
}
//3关闭
fis.close();//关闭输入流
System.out.println();
System.out.println("执行完毕");
}
2.2.2 FileOutputStream
文件字节输出流 FileOutputStream
1.构造方法:
//构造方法:
public int write(){};
public int write(byte[] b){}; //一次写多个字节,将b数组中的多个字节,写入输出流。
public int write(byte[] b, int off, int len){};
2.FileOutputStream代码举例:
public static void main(String[] args) throws Exception {
//1创建文件字节输入流对象
FileOutputStream fos = new FileOutputStream("C:\\Users\\Public\\Documents\\bbb.txt",true);//true表示追加写入
//2.1写入文件,每次写入一个字节
fos.write(97);
fos.write(98);
fos.write('a');
fos.write('b');
//2.2写入文件,利用string.getBytes()方法把一个字符串转换为字节数组,然后一次写入文件中
String string = "HelloWorld";
fos.write(string.getBytes());
//3关闭
fos.close();
System.out.println("写入执行完毕");
}
2.2.3 文件节流复制文件
1.使用文件字节流复制文件代码示例:
public static void main(String[] args) throws Exception {
//1创建文件字节输入流对象,指定要复制的文件路径
FileInputStream fis = new FileInputStream("C:\\Users\\Administrator\\Pictures\\Saved Pictures\\007.JPG");
//2创建文件字节输出流对象,指定复制后的文件路径
FileOutputStream fos = new FileOutputStream("C:\\Users\\Administrator\\Pictures\\Saved Pictures\\010.JPG");
//3读取图片文件的同时输出文件,达到复制文件的效果
byte[] bytes = new byte[1024]; //每次读取1024个字节(1K)的文件
int count;//每次读取的字节数,如果读到文件最后返回-1
while ((count = fis.read(bytes)) != -1){
fos.write(bytes,0,count);
}
//4关闭流通道
fis.close();
fos.close();
System.out.println("文件复制完毕");
}
2.3 字节缓冲流(子类)
字节缓冲流作用:提高I/O效率,减少访问磁盘次数;数据存储在缓冲区中,Flush是缓存区的内容写入文件中,也可以直接close。
2.3.1 BufferedInputStream
BufferedInputStream 字节缓冲输入流
1.继承关系:
2.BufferedInputStream代码示例:
public static void main(String[] args) throws Exception{
//1创建字节缓冲输入流对象
FileInputStream fis = new FileInputStream("C:\\Users\\Public\\Documents\\eee.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
// //2.1读取文件,不在直接通过fis读取硬盘中的文件,而是通过bis读取其中缓存文件
// int data;
// while ((data = bis.read())!= -1){
// System.out.print((char) data);
// }
//2.1自己在读取过程中也可以再维护一个存放数据的缓存数组
System.out.println("================");
byte[] bytes = new byte[1024];
int count;
while ((count = bis.read(bytes))!=-1){
System.out.println(new String(bytes,0,count));
}
//3关闭流通道
bis.close();
System.out.println("文件读取完毕");
}
2.3.2 BufferedOutputStream
BufferedOutputStream 字节输出缓冲流
1. BufferedOutputStream代码示例:
public static void main(String[] args) throws Exception {
//1.创建字节输出缓冲流对象
FileOutputStream fos = new FileOutputStream("C:\\Users\\Public\\Documents\\eee.txt",true);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//2写入文件
for (int i = 0; i < 10; i++) {
bos.write("HelloWorld\n\r".getBytes());
//先写入到自带的8K缓冲区中,使用"HelloWorld\n\r".getBytes()将字符串转换为字节数组
bos.flush();//从缓冲区刷新到硬盘
}
//3关闭通道
bos.close();
System.out.println("执行完毕");
}
2.4 对象流(子类)
ObjectInputStream:对象输入流
ObjectOutputStream:对象输出流
优点:
1.增强了缓冲区功能;
2. 增强了读写8种基本数据类型和字符串功能
3.增强了读写对象的功能: readObject()从流中读取一个对象;
writerObject(Object obj)向 流中写入一个对象;
使用流传输对象的过程称为序列化和反序列化。
1.4.1 ObjectOutputStream
序列化:使用流输出对象的过程称为序列化。
ObjectOutputStream代码示例:
public static void main(String[] args) throws Exception {
//1创建对象输出流
FileOutputStream fos = new FileOutputStream("C:\\Users\\Public\\Documents\\ppp.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2创建对象,并进行序列化
Student s = new Student("张三",20);
oos.writeObject(s);
oos.flush();//从缓冲区刷新到硬盘
//2.关闭对象输出流
oos.close();
System.out.println("序列化完毕");
}
1.4.2 ObjectInputStream
反序列化:使用流读取对象的过程称为反序列化
ObjectInputStream代码示例:
public static void main(String[] args) throws Exception {
//1创建对象输入流对象
FileInputStream fis = new FileInputStream("C:\\Users\\Public\\Documents\\ppp.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
//2读取文件(反序列化)
Student s = (Student) ois.readObject();
//3关闭
ois.close();
System.out.println(s.toString());
}
1.4.2 注意事项
* (1)序列化类必须要实现Serializable接口
* (2)序列化类中对象属性要求实现Serializable接口
* (3)序列化版本号ID(serialVersionUID),保证序列化的类和反序列化 的类是同一个对象
* (4)使用transient(瞬间的)修饰属性,这个属性不能被序列化
* (5)静态属性不能被序列化
public class Student implements Serializable {//(1)序列化类必须要实现Serializable接口
private static final long serialVersionUID =100L;//(3)序列化版本号ID(serialVersionUID),保证序列化的类和反序列化 的类是同一个对象
private String name;
private transient int age;//(4)使用transient(瞬间的)修饰属性,这个属性不能被序列化
public static int num;//(5)静态属性不能被序列化
public Student(String name, int age) {
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 "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
* (6)序列化多个对象,可以借助集合实现;
代码示例:借助集合对多个对象进行序列化操作:
public static void main(String[] args) throws Exception {
//1.创建对象输出流
FileOutputStream fos = new FileOutputStream("C:\\Users\\Public\\Documents\\hhh.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2.实例化对象,创建1个ArrayList<>集合,把对象添加到集合中。
Student s1 = new Student("刘德华", 20);
Student s2 = new Student("张学友", 19);
Student s3 = new Student("林志玲", 21);
ArrayList<Student> students = new ArrayList<>();
students.add(s1);
students.add(s2);
students.add(s3);
//3.将对象输出到文件(序列化过程)
oos.writeObject(students);
oos.flush();//刷新缓冲区中的数据到硬盘;
//4.关闭流通道
oos.close();
System.out.println("序列化执行完毕");
}
借助集合序列化后的对象,通过对象输入流读取后类型为Object类型的集合,对其进行强制转换后即可。
代码示例2:读取借助集合进行对个对象序列化后的文件:
public static void main(String[] args) throws Exception {
//1.创建对象输出流
FileInputStream fis = new FileInputStream("C:\\Users\\Public\\Documents\\hhh.txt ");
ObjectInputStream ois = new ObjectInputStream(fis);
//2读取对象文件
ArrayList<Student> s = (ArrayList<Student>) ois.readObject();
System.out.println(s.toString());
//3关闭
ois.close();
System.out.println("反序列化执行完毕");
}
3. 字符流
3.1 常见字符编码
IOS-8859-1:收录了除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的
文字符号;
UTF-8 :针对Unicode码表的可变长字符编码;中文每个字占3个字节(Byte);
GB2312 :简体中文
BGK :简体中文、扩充
BIG5 :台湾繁体中文
当编码方式和解码方式不一致时,或出现乱码;
3.2 字符流的抽象类(父类)
Reader:字符输入流
Writer:字符输出流
3.3 文件字符流(子类)
3.3.1 FileReader
FileReader(字符输入流)代码示例:
public static void main(String[] args) throws Exception {
//1创建FileReader 文件字符输入流对象
FileReader fr = new FileReader("C:\\Users\\Public\\Documents\\HelloWorld.txt");
//2.1读取文件(方法1 一个字符一个字符读取)
int data;
while ((data = fr.read())!=-1){
System.out.print((char) data);
}
//2.2读取文件(方法2,读取后放入一个数组中)
char[] buf = new char[1024];
int count;
while ((count = fr.read(buf))!=-1){
System.out.print(new String(buf,0,count));
}
//3关闭文件字符输出流对象
fr.close();
}
3.3.2 FileWriter
FileWriter(字符输出流)代码示例:
public static void main(String[] args) throws Exception{
//1.创建FileWriter (字符输入流)
FileWriter fw = new FileWriter("C:\\Users\\Public\\Documents\\HelloWorld2.txt");
//2.写入文件
for (int i=0;i<10;i++){
fw.write("java 是世界上最好的语言\r\n");
fw.flush();
}
//3.关闭
fw.close();
System.out.println("文件写入完毕");
}
3.3.4 字符流复制文件
只能复制文本文件,不能复制图片、音频、视频等二进制文件;使用字节流可以复制任何文件
代码实例:
public static void main(String[] args) throws Exception{
//1.创建FileReader和FileWriter类
FileReader fr = new FileReader("C:\\Users\\Public\\Documents\\HelloWorld2.txt");
FileWriter fw = new FileWriter("C:\\Users\\Public\\Documents\\HelloWorld4.txt");
//2.读写文件(读一个字符写入一个字符)
int data;
while ((data = fr.read())!=-1){
fw.write(data);
fw.flush();
}
//3.关闭
fw.close();
fr.close();
System.out.println("完成文件复制");
}
3.4 字符缓冲流(子类)
字符缓冲输入流BufferedReader;字符缓冲输出流BufferedWriter
优势:高效读写;支持输入换行符的方法;提供一次读一行、写一行的方法;
3.4.1 BufferedReader
字符缓冲输入流BufferedReader代码示例:
public static void main(String[] args) throws Exception {
//1.创建文件字符写入缓冲流
FileReader fr = new FileReader("C:\\Users\\Public\\Documents\\ggg1.txt");
BufferedReader br = new BufferedReader(fr);
//2.1读取文件(方式1:一个字符一个字符读取)
char[] chars = new char[1024];
int count;
while ((count = br.read(chars))!=-1){
System.out.println(new String(chars,0,count));
}
//2.2读取文件(方式2:一次读取一行)
String s;
while ((s = br.readLine())!=null){
System.out.println(s);
}
//3关闭
br.close();
}
3.4.2 BufferedWriter
字符缓冲输出流BufferedWriter代码示例:
public static void main(String[] args) throws Exception {
//1.创建文件字符写入缓冲流
FileWriter fw = new FileWriter("C:\\Users\\Public\\Documents\\ggg2.txt");
BufferedWriter bw = new BufferedWriter(fw);
//2.写入文件
for (int i=0; i<10; i++){
bw.write("好好学习,天天向上");
bw.newLine();//写入一个换行符
bw.flush();
}
//3.关闭通道
bw.close();
System.out.println("执行完毕");
}
3.5 字符打印流PrintWriter
PrintWriter使用:封装了print()和println()方法;支持数据原样打印;
代码示例:
public static void main(String[] args) throws Exception {
//1.创建字符打印流
PrintWriter pw = new PrintWriter("C:\\Users\\Public\\Documents\\ggg3.txt");
//2.打印
pw.println(97);
pw.println(true);
pw.println('张');
pw.println(3.14);
//3.关闭
pw.close();
System.out.println("执行完毕");
}
3.6 转换流
3.6.1 InputStreamReade
输入转换流,InputStreamReader,在把硬盘上的文件读入内存过程中可以指定字符编码方式;
代码示例:
public static void main(String[] args) throws Exception {
//1.创建InputStreamReader
FileInputStream fis = new FileInputStream("C:\\Users\\Public\\Documents\\ggg1.txt");
InputStreamReader isr = new InputStreamReader(fis, "gbk");//可以选择读取文件时使用的字符编码标准
//2.读取文件
int data;
while ((data = isr.read())!=-1){
System.out.print((char) data);
}
//3关闭
isr.close();
}
3.6.2 InputStreamWriter
输出转换流,InputStreamWriter,把内存中的字符文件,转换成字节,写入到硬盘中,写入过程的可以指定编码方式;
public static void main(String[] args) throws Exception {
//1.创建转换流
FileOutputStream fos = new FileOutputStream("C:\\Users\\Public\\Documents\\ggg1.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk");
//2.写入文件
for(int i=0; i<10; i++){
osw.write("好好学习,天天向上\r\n");
osw.flush();
}
//3.关闭
osw.close();
System.out.println("执行完毕");
}
4. File类
4.1 文件操作
代码示例:
public class FileDemo01 {
public static void main(String[] args) throws IOException, InterruptedException {
separator();
fileOpe();
}
//(1)分隔符
public static void separator(){
System.out.println("路径分隔符:" + File.pathSeparator);
System.out.println("名称分隔符:" + File.separator);
}
//(2)文件操作
public static void fileOpe() throws IOException, InterruptedException {
//1.1创建文件
File file = new File("C:\\Users\\Public\\Documents\\mmm.txt");
System.out.println(file.toString());
//1.2先判断文件是否存在,如果不存在则创建文件
if (!file.exists()) {
boolean b = file.createNewFile();
System.out.println("文件是否创建成功:" + b);
}
//2.删除文件
//2.1直接删除
//System.out.println("文件是否被删除" + file.delete());
//2.2使用jvm退出时删除
//file.deleteOnExit();
//Thread.sleep(5000);//延时5秒钟
//3.获取文件的信息
System.out.println("获取文件的绝对路径:" + file.getAbsoluteFile());
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()));
//4判断
System.out.println("是否可写" + file.canWrite());
System.out.println("是否是文件类型" + file.isFile());
System.out.println("是否是隐藏" + file.isHidden());
}
}
4.2 文件夹操作
代码示例:
public class DirectoryOpeDemo01 {
public static void main(String[] args) throws InterruptedException {
directoryOpe();
}
public static void directoryOpe() throws InterruptedException {
//1创建文件夹
File dir = new File("C:\\333\\666\\888");
System.out.println(dir.toString());
//先判断文件夹是否存在,如果不存在就创建
if (!dir.exists()){
//dir.mkdir();//用于创建单个文件夹
System.out.println(dir.mkdirs());//用于创建多级目录
}
//2删除文件夹
//2.1直接删除
// System.out.println(dir.delete());
//2.2只用jvm退出删除
// dir.deleteOnExit();
// Thread.sleep(5000);
//3.获取文件信息
System.out.println("文件夹的绝对路径:" + dir.getAbsoluteFile());
System.out.println("文件夹的路径:" + dir.getPath());
System.out.println("文件夹的名称:" + dir.getName());
System.out.println("文件夹的父目录:" + dir.getParent());
System.out.println("文件夹的最后修改时间:" + new Date(dir.lastModified()));
//3 判断
System.out.println("是否是文件夹:" + dir.isDirectory());
System.out.println("是否是隐藏文件夹:" + dir.isHidden());
//4遍历
System.out.println("==================================");
File dir2 = new File("C:\\Users\\Administrator\\Pictures\\Saved Pictures");
String[] list = dir2.list();
assert list != null;//断言list不等于空
for (String s : list) {
System.out.println(s);
}
}
}
4.3 FileFilter接口
FileFilter接口,用于在文件的过滤。
代码示例:
public class DirectoryOpeDemo02 {
public static void main(String[] args) throws InterruptedException {
directoryOpe02();
}
public static void directoryOpe02() {
//使用FileFilter接口对文件进行过滤
//1.创建(指定)文件夹
File file2 = new File("C:\\Users\\Administrator\\Pictures\\Saved Pictures");
//2.只把文件夹中为.png的文件过滤出来,形成一个File[]数组
File[] files = file2.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.getName().endsWith(".png")){
return true;
}
return false;
}
});
//3.遍历File[]获取文件目录
assert files != null;
for (File file3 : files) {
System.out.println(file3.getName());
}
}
}
4.4 递归遍历和递归删除文件夹
代码示例:
public class ListDirectoryDemo01 {
public static void main(String[] args) {
listDirectory(new File("C:\\qqq"));
deleteDirectory(new File("C:\\qqq"));
}
//1:递归遍历文件夹
public static void listDirectory(File directory){
System.out.println(directory.getAbsoluteFile());
File[] files = directory.listFiles();
if (files!=null){
for (File file : files) {
if (file.isDirectory()){
listDirectory(file);//递归操作
}else {
System.out.println(file.getAbsoluteFile());
}
}
}
}
//2:递归删除文件夹
public static void deleteDirectory(File directory){
File[] files = directory.listFiles();
if (files!=null){
for (File file : files){
if (file.isDirectory()){
deleteDirectory(file);//递归操作
}else {
System.out.println("删除: " + file.getAbsoluteFile() +" " + file.delete());
}
}
}
System.out.println("删除: " + directory.getAbsoluteFile() + " " + directory.delete());
}
}
4.4 Properties 属性集合
特点:存储属性名和属性值;属性名和属性值都是字符串类型;没有泛型;和流有关;
代码示例:
public static void main(String[] args) throws Exception {
//1.创建属性集合
Properties properties = new Properties();
//2.添加元素
properties.setProperty("username","root");
properties.setProperty("age","20");
//3.打印集合元素
System.out.println(properties.toString());
//4.遍历集合
//4.1------使用keySet()遍历------(自己补齐)
//4.2------使用entrySet()遍历------(自己补齐)
//4.3------使用stringPropertyNames()遍历------
Set<String> propertyNames = properties.stringPropertyNames();
for (String propertyName : propertyNames) {
System.out.println(propertyName + "======" + properties.getProperty(propertyName));
}
//5.和流有关的方法
//5.1--------list()方法-------
PrintWriter printWriter = new PrintWriter("C:\\kkk.txt");
properties.list(printWriter);
printWriter.close();
//5.2--------store()方法,实现保存-------
FileOutputStream fos = new FileOutputStream("C:\\kkk.properties");
properties.store(fos,"Mr zhang");
fos.close();
//5.3--------load()方法,实现数据加载-------
Properties properties1 = new Properties();
FileInputStream fis = new FileInputStream("C:\\kkk.properties");
properties1.load(fis);
fis.close();
System.out.println("--------------");
System.out.println(properties1.toString());
}