一.IO流概述:
输入流(InputStream):把数据传到程序中(上传)。
输出流(OutStream):把数据从程序中输出(下载)。
根据传输的内容分为:字节数据和字符数据
字节数据:图片、音频、视频。字节输入流:InputStream;字节输出流:OutputStream。
字符数据:abcd。字符输入流:Reader;字符输出流:Writer。
二.实例化File类的三种方法:
import java.io.File;
public class TestFile {
public static void main(String[] args){
//第一种
File file1 = new File("D:\\a");
//第二种
File file2 = new File("D:\\a", "b.txt");
//第三种
File file = new File("D:\\a");
File file3 = new File(file, "b.txt");
}
}
三.File对象创建文件:
import java.io.File;
import java.io.IOException;
public class TestFile {
public static void main(String[] args) throws IOException {
File file = new File("D:\\a\\c.txt");
//创建文件操作,创建成功返回true,如果文件已经存在或创建失败则返回false。
boolean result = file.createNewFile();
System.out.println(result);
}
}
四.File对象创建文件夹:
import java.io.File;
import java.io.IOException;
public class TestFile {
public static void main(String[] args) throws IOException {
File file = new File("D:\\a\\b");
//创建文件夹操作,创建成功返回true,如果文件夹已经存在或创建失败则返回false。
boolean result = file.mkdir();
System.out.println(result);
}
}
五.File对象创建多层文件夹:
import java.io.File;
import java.io.IOException;
public class TestFile {
public static void main(String[] args) throws IOException {
File file = new File("D:\\a\\bb\\cc");
//创建文件夹操作,创建成功返回true,如果文件夹已经存在或创建失败则返回false。
boolean result = file.mkdirs();
System.out.println(result);
}
}
注意:同一个项目下,文件和文件夹不能重名。如果重名会创建失败。
六.File对象删除文件或文件夹:
import java.io.File;
public class TestFile {
public static void main(String[] args){
File file = new File("D:\\a\\b.txt");
//删除文件或文件夹操作,删除成功返回true,否则返回false。
boolean result = file.delete();
System.out.println(result);
}
}
注意:删除的文件夹下面不能有文件或文件夹。
七.File对象修改文件或文件夹名称:
import java.io.File;
public class TestFile {
public static void main(String[] args){
File file1 = new File("D:\\a\\bb");
File file2 = new File("D:\\a\\ccc");
//把bb文件夹改成ccc文件夹,修改成功返回true,否则返回false。
boolean result = file1.renameTo(file2);
System.out.println(result);
}
}
八.File对象移动文件或文件夹:
import java.io.File;
public class TestFile {
public static void main(String[] args){
File file1 = new File("D:\\a\\bb\\a.txt");
File file2 = new File("D:\\a\\a.txt");
//将bb文件夹下的a.txt移动到a文件夹下,移动成功返回true,否则返回false。
boolean result = file1.renameTo(file2);
System.out.println(result);
}
}
九.File对象的判断功能:
import java.io.File;
public class TestFile {
public static void main(String[] args){
File file1 = new File("D:\\a\\bb");
boolean result1 = file1.isDirectory();//判断是否是目录
boolean result2 = file1.isFile();//判断是否是文件
boolean result3 = file1.exists();//判断是否存在
boolean result4 = file1.canRead();//判断是否可读
boolean result5 = file1.canWrite();//判断是否可写
boolean result6 = file1.isHidden();//判断是否隐藏
System.out.println(result1);
System.out.println(result2);
System.out.println(result3);
System.out.println(result4);
System.out.println(result5);
System.out.println(result6);
}
}
十.File对象的获取功能:
import java.io.File;
import java.util.Date;
public class TestFile {
public static void main(String[] args){
File file1 = new File("D:\\a\\bb");
String absolutePath = file1.getAbsolutePath();//获取绝对路径
System.out.println(absolutePath);
String path = file1.getPath();//获取相对路径
System.out.println(path);
String name = file1.getName();//获取名称
System.out.println(name);
long length = file1.length();//获取字节数。只能求文件的字节数。
System.out.println(length);
long time = file1.lastModified();//获取最后一次的修改时间,毫秒值。
Date date = new Date(time);
String s = date.toLocaleString();//2020-8-9 16:30:58
System.out.println(s);
System.out.println("===========================");
File file2 = new File("D:\\a");
String[] list = file2.list();//获取指定目录下的所有文件或文件夹的名称数组。
for (String s1 : list) {
System.out.println(s1);
}
System.out.println("===========================");
File[] files = file2.listFiles();//获取指定目录下的所有文件或者文件夹的File数组。
for (File file : files) {
System.out.println(file);
}
}
}
十一.File类的实际应用实例:输出目录下的.png文件的绝对路径:
package test;
import java.io.File;
/**
* 功能:输出目录下的.png文件的绝对路径
* 实现:以下两种方法
*/
public class Test {
public static void main(String[] args) {
String s = getPngPath1("D:\\a\\bb");
System.out.println(s);
File pngPath2 = getPngPath2("D:\\a\\bb");
System.out.println(pngPath2);
}
/**
* 第一种方法
* @param path
* @return
*/
public static String getPngPath1(String path){
File file = new File(path);
String[] list = file.list();//得到该目录下所有的文件名称
for (String s : list) {
//获取最后一个.的位置
int lastIndexOf = s.lastIndexOf(".");
//获取文件的后缀名 .png
String suffix = s.substring(lastIndexOf);
if (suffix.equals(".png")){
String finalPath = file.getAbsolutePath() + "\\" + s;
return finalPath;
}
}
return "该目录下没有.png文件";
}
/**
* 第二种方法
* @param path
* @return
*/
public static File getPngPath2(String path){
File file = new File(path);
File[] files = file.listFiles();
for (File file1 : files) {
String name = file1.getName();
if (name.endsWith(".png")){
//这里也可以调用获取绝对路径的方法,把File类型转换成String类型。
return file1;
}
}
return file;//如果目录中没有.png结尾的文件,则返回当前路径。
}
}
十二.IO流入门案例(向文本文件中输入字节流):
import java.io.FileOutputStream;
import java.io.IOException;
public class TestIO{
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("D:\\a.txt");//不存在会自动创建,存在则覆盖原文件
String data = "Hello IO";
byte[] bytes1 ={65,97,48};//字节数据,在记事本中显示为Aa0
byte[] bytes2 = data.getBytes();//把字符数据转换为字节数据
fileOutputStream.write(bytes1);
fileOutputStream.write(bytes2);//通过管道把数据写进文件
fileOutputStream.close();//关闭管道释放资源
}
}
十三.往文本文件中追加数据以及数据换行:
import java.io.FileOutputStream;
import java.io.IOException;
public class TestIO{
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("D:\\b.txt",true);//true为允许在文件中追加
String data1 = "Hello";
String data2 = "\r\n";//换行
byte[] bytes1 = data1.getBytes();//把字符数据转换为字节数据
byte[] bytes2 = data2.getBytes();
for(int i = 0;i<10;i++){
fileOutputStream.write(bytes1);//通过管道把数据写进文件
fileOutputStream.write(bytes2);
}
fileOutputStream.close();//关闭管道释放资源
}
}
十四.字节输入流读取字节:
import java.io.FileInputStream;
import java.io.IOException;
public class TestIO{
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream("D:\\b.txt");
/**
* 一次性读取一个字节
*/
/* int read1 = 0;
//循环读取文件中的字节
while (read1 != -1){
read1 = fileInputStream.read();//一次性读取一个字节并返回,读取到文件的末尾则返回-1
System.out.println(read1);
System.out.println((char) read1);//转换成字符型,还原文件中的内容
}
*/
System.out.println("=====================");
/**
* 一次性读取多个字节
*/
byte[] bytes = new byte[1024];//一次性读取1024个字节
int length = 0;
while ((length = fileInputStream.read(bytes))!=-1){
//把字节数组的一部分转换为字符串,offset:数组的开始索引,length:转换的字节个数
System.out.println(length);
System.out.println(new String(bytes, 0, length));
//System.out.println(new String(bytes));
}
fileInputStream.close();
}
}
十五.文件(图片)复制:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestIO{
/**
* 文件复制原理:一读一写
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//把bb文件夹下的图片复制到a文件夹下
FileInputStream fileInputStream = new FileInputStream("D:\\a\\bb\\22.png");
FileOutputStream fileOutputStream = new FileOutputStream("D:\\a\\22.png");
/*int length = 0;
while ((length = fileInputStream.read())!=-1){
fileOutputStream.write(length);
}*/
/**
* 优化上面一次性读取一个字节,循环次数太多的问题
* 解决方法:使用数组缓冲读取多个字节,写入多个字节
*/
byte[] bytes = new byte[1024];
int length = 0;
while ((length = fileInputStream.read(bytes))!=-1){
fileOutputStream.write(bytes,0,length);
}
//先关写的,后关读的(因为写完了肯定就读完了)
fileOutputStream.close();
fileInputStream.close();
}
}
十六.字符输入流(读取包括中文等字符不出现乱码):
import java.io.FileReader;
import java.io.IOException;
public class TestIO{
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("D:\\b.txt");
/**
* 一次读取一个字符
*/
int length = 0;
while ((length = fileReader.read())!=-1){
System.out.print((char) length);//强转为字符
}
/**
* 一次读取多个字符
*/
/* char[] chars = new char[1];//数组缓冲区,设置一次读取两个字符
int length = 0;
while ((length = fileReader.read(chars))!=-1){
System.out.print(new String(chars,0,length));
}*/
fileReader.close();
}
}
十七.字符输出流:
import java.io.FileWriter;
import java.io.IOException;
public class TestIO{
public static void main(String[] args) throws IOException {
FileWriter fileWriter = new FileWriter("D:\\a\\bb\\a.txt");//要写入的目的地
/**
* 1.写入单个字符
*/
/* fileWriter.write(48);//把数据写入到内存缓冲区中(字符转换为字节的过程)
fileWriter.flush();//把内存缓冲区中的数据刷新到文件中
fileWriter.close();*/
/**
* 2.写入字符数组
*/
/*char[] chars = {'a','b','c'};
fileWriter.write(chars);
fileWriter.flush();
fileWriter.close();*/
/**
* 3.指定写入字符数组长度
*/
/* char[] chars = {'a','b','c','d','e','f'};
fileWriter.write(chars,1,3);//bcd
fileWriter.flush();
fileWriter.close();*/
/**
* 4.直接写入字符串
*/
/*String data = "早上好!";
fileWriter.write(data);
fileWriter.flush();
fileWriter.close();*/
/**
* 5.指定写入字符串的长度
*/
String data = "早上好!世界!!";
fileWriter.write(data,1,3);//上好!
fileWriter.flush();
fileWriter.close();
}
}
十八.字符输出流的续写和换行:
import java.io.FileWriter;
import java.io.IOException;
public class TestIO{
public static void main(String[] args) throws IOException {
//注意:要多次重复执行程序,才能达到续写的目的
FileWriter fileWriter = new FileWriter("D:\\a\\bb\\a.txt", true);//true为允许续写
fileWriter.write("你好!"+"\r\n");//\r\n为换行
fileWriter.flush();
fileWriter.close();
}
}
十九.实际开发中IO异常的处理:
import java.io.FileWriter;
import java.io.IOException;
public class TestIO{
public static void main(String[] args){
FileWriter fileWriter = null;
try{
fileWriter = new FileWriter("D:\\a\\bb\\a.txt");
fileWriter.write("测试异常");
}catch (IOException e){
e.printStackTrace();
}finally {
try {
if (fileWriter!=null){
fileWriter.close();//可以直接写close,少写一行flush
}else {
System.out.println("fileWriter is null");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
二十.Properties集合与IO流:
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
public class TestIO{
public static void main(String[] args) throws IOException {
/**
* 1.使用properties集合存储数据,遍历取出properties集合中的数据
*/
/*Properties properties = new Properties();
properties.setProperty("小明","19");
properties.setProperty("小红","18");
properties.setProperty("小军","17");
//使用stringPropertyNames()方法把properties集合中的键取出,存储到一个set集合中
Set<String> set = properties.stringPropertyNames();
//遍历set集合
for (String key : set) {
String value = properties.getProperty(key);
System.out.println(key+"是"+value+"岁");
}*/
/**
* 2.可以使用properties集合中的store()方法,把集合中的临时数据持久化写入到硬盘存储;
*/
/*Properties properties = new Properties();
properties.setProperty("小明","19");
properties.setProperty("小红","18");
properties.setProperty("小军","17");
FileWriter fileWriter = new FileWriter("D:\\a\\bb\\a.txt");
//comments参数为注释,只能写英文,不然乱码.也可以直接给空串
properties.store(fileWriter,"only comments");
fileWriter.close();*/
/**
* 3.可以使用properties集合中的load()方法,把硬盘中保存的文件(键值对),读取到集合中使用。
*
* 注意:文件中#开头的是注释。不会读取
*/
Properties properties = new Properties();
FileReader fileReader = new FileReader("D:\\a\\bb\\a.txt");
properties.load(fileReader);
Set<String> set = properties.stringPropertyNames();
for (String key : set) {
String value = properties.getProperty(key);
System.out.println(key+"="+value);
}
}
}
文件内容如下:
二十一.缓冲流:
缓冲流的基本原理是创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
1.字节缓冲输出流:
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestIO{
public static void main(String[] args) throws IOException{
FileOutputStream fileOutputStream = new FileOutputStream("D:\\a\\bb\\a.txt");
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
//使用write()方法,把数据写入到内部缓冲区中。使用getBytes()把字符串转换为字节数组
bufferedOutputStream.write("我把数据写入到内部缓冲区了".getBytes());
bufferedOutputStream.flush();//使用flush(),把内部缓冲区中的数据,刷新到文件中
bufferedOutputStream.close();//只关闭缓冲流,自动关闭字节流
}
}
2.字节缓冲输入流:
import java.io.*;
public class TestIO{
public static void main(String[] args) throws IOException{
FileInputStream fileInputStream = new FileInputStream("D:\\a\\bb\\a.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
/**
*从输入流中读取单个字节,并将其存储在缓冲区数组中
*/
/*int length = 0;
while ((length = bufferedInputStream.read())!=-1){
System.out.println(length);
}*/
/**
* 从输入流中读取一定数量的字节,并将其存储在缓冲区数组中
* 相当于既采用数组缓冲,又采用缓冲区数组缓冲
*/
int length = 0;
byte[] bytes = new byte[1024];
while ((length = bufferedInputStream.read(bytes))!=-1){
System.out.println(new String(bytes,0,length));
}
bufferedInputStream.close();//只关闭缓冲流,自动关闭字节流
}
}
3.字符缓冲输出流:
import java.io.*;
public class TestIO{
public static void main(String[] args) throws IOException{
FileWriter fileWriter = new FileWriter("D:\\a\\bb\\a.txt");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("早上好!同学们!");
//bufferedWriter.write("\r\n");//换行
bufferedWriter.newLine();//换行
bufferedWriter.write("吃早饭了吗?");
bufferedWriter.flush();
bufferedWriter.close();
}
}
4.字符缓冲输入流:
import java.io.*;
public class TestIO{
public static void main(String[] args) throws IOException{
/**
* read()方法的使用与前面的相同,这里不再赘述
* 这里主要探讨readLine()
*/
BufferedReader bufferedReader = new BufferedReader(new FileReader("D:\\a\\bb\\a.txt"));
String line;
//readLine()读取文本中的一行数据
while ((line = bufferedReader.readLine())!=null){
System.out.println(line);//循环打印文本中的所有数据
}
bufferedReader.close();
}
}
二十二.转换流:可以自定义输入输出流的编码格式
1.字符转换输出流:
import java.io.*;
public class TestIO{
public static void main(String[] args) throws IOException{
/**
* 1.使用utf-8编码格式
*/
/*FileOutputStream fileOutputStream = new FileOutputStream("D:\\a\\bb\\b.txt");
//第二个参数是指定的编码表名称(就是以什么编码格式存储),不区分大小写。不指定时默认使用utf-8编码
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8");
//使用write()方法把字符转换为字节存储在缓冲区中
outputStreamWriter.write("你好啊!");
//使用flush()方法把内存缓冲区中的字节刷新到文件中
outputStreamWriter.flush();
outputStreamWriter.close();*/
/**
* 2.使用gbk编码格式
*/
FileOutputStream fileOutputStream = new FileOutputStream("D:\\ideawork\\java\\d.txt");
//第二个参数是指定的编码表名称(就是以什么编码格式存储),不区分大小写。不指定时默认使用utf-8编码
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "gbk");
//使用write()方法把字符转换为字节存储在缓冲区中
outputStreamWriter.write("你好啊!!!");
//使用flush()方法把内存缓冲区中的字节刷新到文件中
outputStreamWriter.flush();
outputStreamWriter.close();
}
}
2.字符转换输入流:
import java.io.*;
public class TestIO{
public static void main(String[] args) throws IOException{
//使用指定的编码格式读取字节并将其解码为字符
//指定的编码表名称,不区分大小写,不指定默认使用utf-8
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("D:\\a\\bb\\a.txt"),"utf-8");
int length = 0;
while ((length = inputStreamReader.read())!=-1){
System.out.print((char) length);
}
inputStreamReader.close();
//注意:构造方法中指定的编码表名称要和文件的编码格式相同,否则会乱码
}
}
二十三.对象的序列化流和反序列化流
对象的序列化:把对象以流的方式,写入到文件中保存,也叫写对象。
对象的反序列化:把文件中保存的对象,以流的方式读取出来,也叫做读对象。
实例:
要先创建一个类:
import java.io.Serializable;
/**
* 要进行序列化和反序列化的类,必须实现Serializable接口;
* 否则程序会抛出java.io.NotSerializableException异常。
*/
public class Person implements Serializable{
private String userName;
private int age;
public Person() {
}
public Person(String userName, int age) {
this.userName = userName;
this.age = age;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"userName='" + userName + '\'' +
", age=" + age +
'}';
}
}
对象的序列化:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class TestObjectOutputStream {
public static void main(String[] args) throws IOException {
/**
* 对象的序列化
*/
FileOutputStream fileOutputStream = new FileOutputStream("D:\\a\\bb\\b.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
//使用writeObject()方法把对象写入到文件中
objectOutputStream.writeObject(new Person("小红",19));
objectOutputStream.close();
}
}
对象的反序列化:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class TestObjectInputStream {
public static void main(String[] args) throws IOException, ClassNotFoundException {
/**
* 对象的反序列化
*/
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\a\\bb\\b.txt"));
//使用readObject()方法读取保存对象的文件
Object object = objectInputStream.readObject();
objectInputStream.close();
System.out.println(object);
Person person = (Person) object;//强转为Person类型
System.out.println(person.getUserName()+person.getAge());
}
}
transient关键字说明:
static关键字:静态关键字。静态优先于非静态加载到内存中(静态优先于对象进入到内存中)。因此被static修饰的成员变量不能被序列化,序列化的都是对象。
transient关键字:瞬态关键字。将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化。
注意:
每次修改类的定义,都会给class文件生成一个新的序列号,这样可能会出现InvalidClassException异常。因此我们可以手动给类添加一个序列号,无论是否对类的定义进行修改,都不会重新生成新的序列号。如下图:
二十四.序列化集合
作用:想在文件中保存多个对象的时候,可以把多个对象存储到一个集合中,对集合进行序列化和反序列化操作。
实体类:
import java.io.Serializable;
/**
* 要进行序列化和反序列化的类,必须实现Serializable接口;
* 否则程序会抛出java.io.NotSerializableException异常。
*/
public class Person implements Serializable{
private static final long serialVersionUID = 42L;
private String userName;
private int age;
public Person() {
}
public Person(String userName, int age) {
this.userName = userName;
this.age = age;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"userName='" + userName + '\'' +
", age=" + age +
'}';
}
}
操作:
import java.io.*;
import java.util.ArrayList;
public class TestIO{
public static void main(String[] args) throws IOException, ClassNotFoundException {
ArrayList<Person> list1 = new ArrayList<>();
list1.add(new Person("小红",10));
list1.add(new Person("小军",13));
list1.add(new Person("小明",12));
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\a\\bb\\b.txt"));
objectOutputStream.writeObject(list1);//把集合序列化
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\a\\bb\\b.txt"));
Object readObject = objectInputStream.readObject();//反序列化
//把Object类型的集合转换为ArrayList类型,方便遍历
ArrayList<Person> list2 = (ArrayList<Person>) readObject;
//遍历打印
for (Person person : list2) {
System.out.println(person);
}
objectInputStream.close();
objectOutputStream.close();
}
}
二十五.打印流:可以更方便的输出数据
import java.io.FileNotFoundException;
import java.io.PrintStream;
public class TestIO{
public static void main(String[] args) throws FileNotFoundException {
PrintStream printStream = new PrintStream("D:\\a\\bb\\b.txt");//输出目的地
printStream.write(97);
printStream.println(97);
printStream.println("hello!!");
printStream.println(0.333333);
printStream.println(true);
printStream.close();
}
}
特殊用法:可以改变输出语句目的地
import java.io.FileNotFoundException;
import java.io.PrintStream;
public class TestIO{
public static void main(String[] args) throws FileNotFoundException {
System.out.println("控制台打印");
PrintStream printStream = new PrintStream("D:\\a\\bb\\b.txt");
System.setOut(printStream);//把输出语句的目的地改变为打印流的目的地
System.out.println("指定的b.txt中输出");
printStream.close();
}
}
=完结!!=================================================================