常用的文件操作
创建文件
- createNewFile() + 三种构造方法
1、直接全部路径
File parentFile = new File("D:\\FileTest");
File file = new File(filePath);
file.createNewFile();
2、目录 + 文件名
String parentPath = "D:\\FileTest";
String fileName = "news03.txt";
File file = new File(parentPath, fileName);
System.out.println("创建成功");
3、目录对象 + 文件名
File parentFile = new File("D:\\FileTest");
String fileName = "news02.txt";
File file = new File(parentFile, fileName);
file.createNewFile();
文件已经存在? 不会报错,也不会再创建该文件,不会进行覆盖之类的操作
获取文件相关信息
file.getName()
:获取文件名字file.getAbsolutePath()
:获取绝对路径file.getParent()
:获取父级目录file.length()
:获取文件大小(字节)file.exists()
:判断文件是否存在file.isFile()
:判断是不是一个文件file.isDirectory()
:判断是不是一个目录
目录操作和文件删除
- 文件删除:
file.delete()
文件存在删除并返回true
,不存在返回false
String filePath = "D:\\FileTest1";
File file = new File(filePath);
if (file.exists()) {
if (file.delete())
System.out.println("删除成功");
else
System.out.println("删除失败");
} else {
System.out.println("该目录不存在");
}
- 目录删除,与文件删除同理,因为在java中,目录也被当作文件
String filePath = "D:\\FileTest1";
File file = new File(filePath);
if (file.exists()) {
if (file.delete())
System.out.println("删除成功");
else
System.out.println("删除失败");
} else {
System.out.println("该目录不存在");
}
- 目录创建,若存在,则不再创建,并返回
false
,若不存在,则创建且返回true
- 创建单级目录:
mkdir()
在已经存在的基础上,只能创建一级,若创建多级则返回false
- 创建多级目录:
mkdirs()
在已经存在的基础上,可以创建多级,也可以创建一级
String directoryPath = "D:\\FileTest\\test01"
File file = new File(directoryPath);
if (file.exists()) {
System.out.println("该目录存在");
} else {
if (file.mkdirs()) {
System.out.println("该目录创建成功");
} else {
System.out.println("该目录创建失败");
}
}
IO流原理与分类
IO流原理
1、对数据的输入和输出操作以”流(stream)“的方式进行
2、java.io包下提供了各种"流"类和接口,用以获取不同种类的数据,并通过方法输入或者输出数据
3、input:读取外部数据(磁盘,光盘等存储设备的数据)到程序(内存)中
4、output:将程序(内存)数据输出到磁盘,光盘等存储设备中
分类
字节流和字符流
基本介绍
节点流:可以从一个特定的数据源(如文件、数组、管道)读取数据,如FileReader、FileWriter
处理流:也叫做包装流,是"连接"在已存在的流(节点流或者处理流)之上,为程序提供跟各位i强大的读写功能,如BufferedReader,BufferedWriter
区别与联系
1、节点流是底层流/低级流,直接跟数据源连接
2、处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
3、处理流对节点流进行包装,使用了修饰器模式,不会直接与数据源相连接
分类图
分类 | 作用 | 字节流输入 | 字节流输出 | 字符流输入 | 字符流输出 |
---|---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer | |
节点流 | 访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
…… | 访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
…… | 访问管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
…… | 访问字符串 | StringReader | StringWriter | ||
处理流 | 缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
…… | 转换流 | InputStreamReader | OutputStreamWriter | ||
…… | 对象流 | ObjectInputStream | ObjectOutputStream | ||
…… | 抽象基类 | FilterInputStream | FilterOutputStream | FilterReader | Filterwriter |
…… | 打印流 | PrintStream | PrintWriter |
处理流的主要功能
性能的提高:主要以增加缓冲的方式来提高输入输出的效率
操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
案例
节点流 FileInputStream 和 FileOutputStream
- FileInputStream
1、读取一个字节
String filePath = "D:\\FileTest\\hello.txt";
int readData = 0;
// 创建FileInputStream对象,用于读取文件
FileInputStream fileInputStream = new FileInputStream(filePath);
//从该输入流读取一个字节的数据。如果没有输入可用,此方法将停止。
//如果返回-1,表示读取完毕
//read():该方法每次读取一个字节,返回该字节的十进制表示
while ((readData = fileInputStream.read()) != -1 )
System.out.println((char)readData); //若不转换为char,则输出每一个字节的十进制表示
fileInputStream.close(); //关闭文件流,释放资源
2、一次读取很多字节
String filePath = "D:\\FileTest\\hello.txt";
int readData = 0;
byte[] buf = new byte[8];
int readLen = 0;
FileInputStream fileInputStream = new FileInputStream(filePath);
//从该输入流读取最多buf.length字节的数据到字节数组
//如果读取正常则返回实际读取的字节数
//如果返回-1,表示读取完毕
while ((readLen = fileInputStream.read(buf)) != -1 )
System.out.println(new String(buf,0,readLen)); //读取buff内容中,从0到readLen-1 位置的数据
fileInputStream.close(); //关闭文件流,释放资源
- FileOutputStream
String filePath = "D:\\FileTest\\a.txt";
//如果不存在,则创建该文件
//1、new FileOutputStream(filePath)创建方式,当写入内容时,会覆盖
//2、new FileOutputStream(filePath,true)创建方式,当写入内容时,是追加到内容后面
FileOutputStream fileOutputStream = new FileOutputStream(filePath,true);
fileOutputStream.write('H'); //写如一个字节
//写入字符串,因为不能直接写入字符串
String str = "你好";
fileOutputStream.write(str.getBytes());
//从字节数组中,选择0~4的内容写入
String str01 = "hello,world";
fileOutputStream.write(str01.getBytes(),0,5);
fileOutputStream.close();
节点流:FileReader和FileWriter
- FileReader
1、一次读取一个字符
String filePath = "D:\\FileTest\\a.txt";
int data;
//1、创建一个FileReader对象
FileReader fileReader = null;
try {
fileReader = new FileReader(filePath);
//循环读取,读取单个字符
//read():该方法返回一个一个字符的编码的十进制
while ((data = fileReader.read()) != -1) {
System.out.print((char)data);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、一次读取多个字符
String filePath = "D:\\FileTest\\a.txt";
int readLen = 0;
char[] buf = new char[8];
//1、创建一个FileReader对象
FileReader fileReader = null;
try {
fileReader = new FileReader(filePath);
//循环读取,读取多个字符
//若读取成功,则返回读取的字符数,若失败,返回-1
while ((readLen = fileReader.read(buf)) != -1) {
System.out.println(readLen);
System.out.println(new String(buf,0,readLen));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
- FileWriter
String filePath = "D:\\FileTest\\note.txt";
FileWriter fileWrite = null;
char[] chars = {'韩', '顺', '平'};
try {
//无true则覆盖
//有true则添加
fileWrite = new FileWriter(filePath);
//write(int):写入单个字符
fileWrite.write('H');
//write(char[]):写入指定数组
fileWrite.write(chars);
//write(char[],off,len):写入数组的指定部分
fileWrite.write("韩顺平教育".toCharArray(),0,3);
//write(String):写入整个字符串
fileWrite.write(" ,你好中国");
fileWrite.write(" 风雨之后,定见彩虹 ");
//write(String,off,len):写入字符串的指定部分
fileWrite.write("上海天津",0,2);
//数量打的时候,可以使用循环操作
} catch (IOException e) {
e.printStackTrace();
} finally {
//对于FileWriter,一定要关闭流,或者flush才能真正的把数据写入到文件
try {
fileWrite.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("程序结束");
处理流理解
在这里举一个例子说明
public class BufferedReader_ extends Reader_ {
private Reader_ reader_; // 属性使Reader_类型
//可以接受Reader_ 子类对象
public BufferedReader_(Reader_ reader_) {
this.reader_ = reader_;
}
public void readFiles(int num) {
for (int i = 0; i < num; i++) {
reader_.readFile();
}
}
//扩展 readString, 批量处理字符串数据
public void readStrings(int num) {
for (int i = 0; i < num; i++) {
reader_.readString();
}
}
}
处理流:BufferedReader和BufferedWriter
- BufferedReader
String filePath = "D:\\FileTest\\a.txt";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//读取
//1、bufferedReader.readLine() 是按行读取文件
//2、当返回null时,表示文件读取完毕
String line;
while ((line = bufferedReader.readLine()) !=null)
System.out.println(line);
//关闭流,注意,只需要关闭 BufferedReader,因为底层会自动的去关闭 节点流
bufferedReader.close();
- BufferedWriter
String filePath = "D:\\FileTest\\b.txt";
//创建BufferedWriter
//1、new FileWrite(filePath,true) 表示以追加的方式写入
//2、new FileWrite(filePath) 表示以覆盖的方式写入
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write("hello,韩顺平教育!");
bufferedWriter.newLine();
bufferedWriter.write("hello2,韩顺平教育!");
bufferedWriter.newLine();
bufferedWriter.write("hello3,韩顺平教育!");
bufferedWriter.newLine();
//插入一个换行
bufferedWriter.close();
上述两个类属于字符流,是按照字符来读取数据的
关闭处理流时,只需关闭外层流留即可
处理流:BufferedInputStream和BufferedOutputStream
拷贝
byte[] c = new byte[1024];
int readLen = 0;
while ((readLen = bufferedInputStream.read(c)) != -1) {
bufferedOutputStream.write(c,0,readLen);
}
对象流:ObjectInputStream和ObjectOutputStream
作用:保存值和数据类型
序列化要求版本统一,会记住类的具体位置,若修改了类,则反序列化时,jvm会认为这是新的类,不是之前的类,会报错
class Dog implements Serializable {
private String name;
private int age;
//序列的版本号,可以提高兼容性
//当加入新的属性时,jvm不会认为这是一个新的类,而是认为这是同一个版本的修改
private static final long serialVersionUID = 1L;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
序列化:
//序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
String filePath = "D:\\FileTest\\data.txt";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据
oos.writeInt(100); // 底层自动装箱 int -> Integer(实现了Serializable)
oos.writeBoolean(true); // boolean -> Boolean
oos.writeChar('c'); //char -> Character
oos.writeDouble(9.5); //double -> Double
oos.writeUTF("韩顺平教育"); //String
//保存一个dog对象
oos.writeObject(new Dog("旺财",10));
oos.close();
反序列化:
String filePath = "D:\\FileTest\\data.txt";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//读取
//1、读取(反序列化)的顺序需要和保存的数据(序列化)的顺序一致
//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());
System.out.println(ois.readObject()); //底层 Object -> Dog
ois.close();
转换流:InputStreamReader和OutputStreamReader
- InputStreamReader
// InputStreamReader 转换流解决中文乱码问题
String filePath = "D:\\FileTest\\a1.txt";
//1、把FileInputStream 转成 InputStreamReader
//2、指定编码gbk
InputStreamReader gbk = new InputStreamReader(new FileInputStream(filePath), "gbk");
//3、把InputStreamReader 传入 BUfferedReader
BufferedReader bufferedReader = new BufferedReader(gbk);
//4、读取
String s = bufferedReader.readLine();
System.out.println("读取内容 = " + s );
bufferedReader.close();
- OutputStreamWriter
String filePath = "D:\\FileTest\\hsp.txt";
String charSet = "gbk";
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath,true), charSet);
osw.write("hi,韩顺平");
osw.close();
配置文件Properties
读取配置文件
Properties properties = new Properties();
// 加载指定配置文件
properties.load(new FileReader("src\\file\\mysql.properties"));
// 根据key获得对应的值
String user = properties.getProperty("user");
String pwd = properties.getProperty("pwd");
写入配置文件
// 使用Properties类来创建配置文件,修改配置文件内容
Properties properties = new Properties();
// 创建
// 如果该文件没有某个key,则添加,若有则修改
/*
Properties父类是Hashtable,底层就是Hashtable核心方法
*/
properties.setProperty("charset","utf8");
properties.setProperty("user","汤姆"); // 注意保存时,是中文的unicode码值
properties.setProperty("pwd","abc111");
//将K-V存储到文件中
properties.store(new FileOutputStream("src\\file\\mysql02.properties"),"hello,world");