⭐️前言⭐️
咱们在Java中,一般谈到文件,都是指一个存储在磁盘上的文件(狭义的文件),如果抛开Java,站在系统角度来看,操作系统在管理很多软件资源和硬件设备的时候,都是把这些东西抽象成了一个一个的文件。
博客主页: 【如风暖阳】
精品Java专栏【JavaSE】、【Java数据结构】、【备战蓝桥】、【JavaEE初阶】
欢迎点赞 收藏 ⭐留言评论 私信必回哟本文由 【如风暖阳】 原创,首发于 CSDN
博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言
博客中涉及源码及博主日常练习代码均已上传码云(gitee)
文件在程序中以流的形式来操作
数据从数据源(文件)到程序之间的路径为输入流,从程序到数据源(文件)之间的路径为输出流
new File(String pathname)//路径构建
public void create01() {
String pathname="d:\\news1.txt";
File file = new File(pathname);
try {
file.createNewFile();
System.out.println("创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
new File(File parent,String child)//父目录文件+子路径
public void create02() {
File parentFile = new File("d:\\");
String fileName="news2.txt";
File file=new File(parentFile,fileName);
try {
file.createNewFile();
System.out.println("创建成功02");
} catch (IOException e) {
e.printStackTrace();
}
new File(String parent,String child)//父目录+子路径
public void create03() {
String parent="d:\\";
String child="news3.txt";
File file = new File(parent, child);
try {
file.createNewFile();
System.out.println("创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
常用方法:
getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory
d:\news1.txt 是否存在,如果存在就删除
public void m1() {
String filePath = "e:\\news1.txt";
File file = new File(filePath);
if (file.exists()) {
if (file.delete()) {
System.out.println(filePath + "删除成功");
} else {
System.out.println(filePath + "删除失败");
}
} else {
System.out.println("该文件不存在...");
}
}
D:\demo02 是否存在,存在就删除,否则提示不存在
(在java编程中,目录也被当做文件)
public void m2() {
String filePath="D:\\demo2";
File file = new File(filePath);
if(file.exists()) {
if(file.delete()) {
System.out.println(filePath+"删除成功");
}else {
System.out.println(filePath+"删除失败");
}
}else {
System.out.println("该目录不存在...");
}
}
判断 D:\demo\a\b\c 目录是否存在,如果存在就提示已经存在,否则就创建
public void m3() {
String directoryPath="D:\\锤子\\a\\b\\c";
File file = new File(directoryPath);
if(file.exists()) {
System.out.println("目录存在");
}else {
if(file.mkdirs()) {
//创建一级目录使用mkdir() ,创建多级目录使用mkdirs()
System.out.println("创建成功");
}else {
System.out.println("创建失败");
}
}
}
Input/Output 实现数据的输入/输出操作(以流的方式进行)
public void readFile01() {
String filePath = "d:\\hello.txt";
int readData = 0;
FileInputStream fileInputStream = null;
try {
//创建 FileInputStream 对象,用于读取 文件
fileInputStream = new FileInputStream(filePath);
//从该输入流读取一个字节的数据。 如果没有输入可用,此方法将阻止。
//如果返回-1 , 表示读取完毕
while ((readData = fileInputStream.read()) != -1) {
System.out.print((char)readData);//转成char显示
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭文件流,释放资源.
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void readFile02() {
String filePath = "d:\\hello.txt";
//字节数组
byte[] buf = new byte[8]; //一次读取8个字节.
int readLen = 0;
FileInputStream fileInputStream = null;
try {
//创建 FileInputStream 对象,用于读取文件
fileInputStream = new FileInputStream(filePath);
//从该输入流读取最多b.length字节的数据到字节数组。此方法将阻塞,直到某些输入可用。
//如果返回-1 , 表示读取完毕
//如果读取正常, 返回实际读取的字节数
while ((readLen = fileInputStream.read(buf)) != -1) {
System.out.print(new String(buf, 0, readLen));//显示
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭文件流,释放资源.
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
请使用 FileOutputStream 在 a.txt 文件,中写入 “hello,world”. 如果文件不存在,会创建
文件(注意:前提是目录已经存在.)
public void writeFile() {
//创建 FileOutputStream对象
String filePath = "e:\\a.txt";
FileOutputStream fileOutputStream = null;
try {
//得到 FileOutputStream对象
//1. new FileOutputStream(filePath) 创建方式,当写入内容是,会覆盖原来的内容
//2. new FileOutputStream(filePath, true) 创建方式,当写入内容是,是追加到文件后面
fileOutputStream = new FileOutputStream(filePath, true);
//写入一个字节
//fileOutputStream.write('H');//
//写入字符串
String str = "hsp,world!";
//str.getBytes() 可以把 字符串-> 字节数组
//fileOutputStream.write(str.getBytes());
/*
write(byte[] b, int off, int len) 将 len字节从位于偏移量 off的指定字节数组写入此文件输出流
*/
fileOutputStream.write(str.getBytes(), 0, 3);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例1
扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要
删除该文件
public class Demo8 {
public static void main(String[] args) throws IOException {
// 1. 让用户指定一个待扫描的根目录 和 要查询的关键词
System.out.println("请输入要扫描的根目录(绝对路径): ");
Scanner scanner = new Scanner(System.in);
String root = scanner.next();
File rootDir = new File(root);
if (!rootDir.isDirectory()) {
System.out.println("您输入的路径错误! 程序直接退出!");
return;
}
System.out.println("请输入要查找的文件名中包含的关键词: ");
String token = scanner.next();
// 2. 递归的遍历目录
// result 表示递归遍历的结果. 就包含着所有带有 token 关键词的文件名.
List<File> result = new ArrayList<>();
scanDir(rootDir, token, result);
// 3. 遍历 result, 问用户是否要删除该文件. 根据用户的输入决定是否删除
for (File f : result) {
System.out.println(f.getCanonicalPath() + " 是否要删除? (Y/n)");
String input = scanner.next(); if (input.equals("Y")) {
f.delete();
}
}
}
// 递归的来遍历目录, 找出里面所有符合条件的文件.
private static void scanDir(File rootDir, String token, List<File> result) throws IOException {
// list 返回的是一个文件名(String), 使用 listFiles 直接得到的是 File 对象, 用起来更方便一些.
File[] files = rootDir.listFiles();
if (files == null || files.length == 0) {
// 当前的目录是一个空的目录
return;
}
for (File f : files) {
if (f.isDirectory()) {
// 如果当前的文件是一个目录, 就递归的进行查找
scanDir(f, token, result);
} else {
// 如果当前文件是一个普通的文件, 就判定这个文件是否包含了待查找的关键词
if (f.getName().contains(token)) {
result.add(f.getCanonicalFile());
}
}
}
}
}
示例2
扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
注意:我们现在的方案性能较差,所以尽量不要在太复杂的目录下或者大文件下实验
public class Demo9 {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
// 1. 让用户输入一个路径. 待搜索的路径
System.out.println("请输入要扫描的根目录: ");
String rootDir = scanner.next();
File rootFile = new File(rootDir);
if (!rootFile.isDirectory()) {
System.out.println("该目录不存在或者不是文件! 直接退出. ");
return;
}
// 2. 再让用户输入一个查询词, 表示要搜索的结果中要包含这个词.
System.out.println("请输入要查询的词: ");
String query = scanner.next();
// 3. 遍历目录以及文件, 进行匹配
List<File> results = new ArrayList<>();
scanDirWithContent(rootFile, query, results);
// 4. 把结果打印出来
for (File f : results) {
System.out.println(f.getCanonicalPath());
}
}
private static void scanDirWithContent(File rootFile, String query, List<File> results) {
File[] files = rootFile.listFiles();
if (files == null || files.length == 0) {
// 针对空的目录, 直接返回
return;
}
for (File f : files) {
if (f.isDirectory()) {
scanDirWithContent(f, query, results);
} else {
if (f.getName().contains(query)) {
// 看看文件名称中是否包含
results.add(f);
} else if (isContentContains(f, query)) {
// 看看文件内容中是否包含
results.add(f);
}
}
}
}
private static boolean isContentContains(File f, String query) {
// 打开 f 这个文件, 依次取出每一行结果, 去和 query 来进行一个 indexOf
StringBuilder stringBuilder = new StringBuilder();
//实现了Closeable接口的类,可以放到try()中,自动完成资源回收
try (InputStream inputStream = new FileInputStream(f)) {
//用标准输入流来读取文件内容
Scanner scanner = new Scanner(inputStream, "UTF-8");
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
stringBuilder.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
}
// 只要结果不等于 -1, 就说明查到了.
return stringBuilder.indexOf(query) != -1;
}
}
思路分析:
public static void main(String[] args) {
String srcfilePath="d:\\大美女.jpg";
String desfilePath="d:\\小美女.jpg";
FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;
try {
fileInputStream= new FileInputStream(srcfilePath);
fileOutputStream = new FileOutputStream(desfilePath);
byte[]buf=new byte[1024];
int readLen=0;
while ((readLen=fileInputStream.read(buf))!=-1) {
fileOutputStream.write(buf,0,readLen);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fileInputStream!=null) fileInputStream.close();
if(fileOutputStream!=null) fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileReader:
/**
* 单个字符读取文件
*/
@Test
public void readFile01() {
String filePath = "d:\\story.txt";
FileReader fileReader = null;
int data = 0;
//1. 创建FileReader对象
try {
fileReader = new FileReader(filePath);
//循环读取 使用read, 单个字符读取
while ((data = fileReader.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 字符数组读取文件
*/
@Test
public void readFile02() {
System.out.println("~~~readFile02 ~~~");
String filePath = "d:\\story.txt";
FileReader fileReader = null;
int readLen = 0;
char[] buf = new char[8];
//1. 创建FileReader对象
try {
fileReader = new FileReader(filePath);
//循环读取 使用read(buf), 返回的是实际读取到的字符数
//如果返回-1, 说明到文件结束
while ((readLen = fileReader.read(buf)) != -1) {
System.out.print(new String(buf, 0, readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileWriter:
public void fileWriter() {
String filePath="d:\\note.txt";
FileWriter fileWriter=null;
char[]chars=new char[]{'a','b','c'};
try {
fileWriter=new FileWriter(filePath);
// write(int):写入单个字符
fileWriter.write('H');
// write(char[]):写入指定数组
fileWriter.write(chars);
// write(char[],off,len):写入指定数组的指定部分
fileWriter.write("韩顺平教育".toCharArray(), 0, 3);
// write(string):写入整个字符串
fileWriter.write(" 你好北京~");
fileWriter.write("风雨之后,定见彩虹");
// write(string,off,len):写入字符串的指定部分
fileWriter.write("上海天津", 0, 2);
//在数据量大的情况下,可以使用循环操作.
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fileWriter!=null)
fileWriter.flush();
//fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.节点流是底层流(低级流),直接与数据源相接。
2.处理流(包装流)对节点流进行包装,消除不同节点流的实现差异,提供更方便的方法来完成输入输出。
关闭处理流时,只需关闭外层流即可。
BufferedReader、BufferedWriter
BufferedReader
public void BufferedReader_() throws IOException {
String filePath="d:\\story.txt";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
String line;
while ((line=bufferedReader.readLine())!=null) {
System.out.println(line);
}
bufferedReader.close();
}
BufferedWriter
public void BufferedWriter_() throws IOException {
String filePath="d:\\hello.txt";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
bufferedWriter.write("\"hello, 韩顺平教育!\"");
bufferedWriter.newLine();
bufferedWriter.write("1234");
bufferedWriter.newLine();
bufferedWriter.write("99ihsdkhf");
bufferedWriter.close();
}
综合使用,完成文本文件拷贝
注意:BufferedReader和BufferedWriter是按照字符操作,不能去操作二进制文件(图片,声音,视频,doc,pdf),否则会造成文件损坏。
public void BufferedCopy() {
String srcFilePath="d:\\story.txt";
String destFilePath="d:\\aabbcc.txt";
BufferedReader br=null;
BufferedWriter bw=null;
String line;
try {
br=new BufferedReader(new FileReader(srcFilePath));
bw=new BufferedWriter(new FileWriter(destFilePath));
while ((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
}
System.out.println("拷贝完毕...");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(br!=null)
br.close();
if(bw!=null)
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedInputStream、BufferedOutputStream
public void BufferedCopy02() {
String srcFilePath="d:\\大美女.jpg";
String destFilePath="d:\\小美女.jpg";
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try {
bis=new BufferedInputStream(new FileInputStream(srcFilePath));
bos=new BufferedOutputStream(new FileOutputStream(destFilePath));
byte[]buff=new byte[1024];
int readLen=0;
while ((readLen=bis.read(buff))!=-1) {
bos.write(buff,0,readLen);
}
System.out.println("拷贝完毕");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(bis!=null)
bis.close();
if(bos!=null)
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ObjectOutputStream、ObjectInputStream
对数据的数据类型和数据的值都进行保存。
序列化保存数据
反序列化恢复数据
ObjectOutputStream
public class ObjectOutStream_ {
public static void main(String[] args) throws Exception {
//序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
String filePath = "e:\\data.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到 e:\data.dat
oos.writeInt(100);// int -> Integer (实现了 Serializable)
oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)
oos.writeChar('a');// char -> Character (实现了 Serializable)
oos.writeDouble(9.5);// double -> Double (实现了 Serializable)
oos.writeUTF("韩顺平教育");//String
//保存一个dog对象
oos.writeObject(new Dog("旺财", 10, "日本", "白色"));
oos.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
ObjectInputStream
public class ObjectInputStream_ {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//指定反序列化的文件
String filePath="d:\\test.dat";
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(filePath));
//读取(反序列化)的顺序需要和你保存数据(序列化)的顺序一致
//否则会出现异常
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());
ois.close();
}
}
注意事项:
InputStreamReader 、OutputStreamWriter
乱码问题引出转换流的必要性:
默认读取文件按照UTF-8的形式来读取,但若文件的保存方式不是UTF-8,将会出现乱码的情况
所以需要通过转换流来指定文件的读取方式
InputStreamReader
* 演示使用 InputStreamReader 转换流解决中文乱码问题
* 将字节流 FileInputStream 转成字符流 InputStreamReader, 指定编码 gbk/utf-8
public class InputStreamReader_ {
public static void main(String[] args) throws IOException {
String filePath="d:\\a.txt";
InputStreamReader isr=new InputStreamReader(new FileInputStream(filePath),"gbk");
BufferedReader br=new BufferedReader(isr);
//上两步和在一起
//BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gbk"));
String s= br.readLine();
System.out.println("读取内容"+s);
br.close();
}
}
OutputStreamWriter
* 把FileOutputStream 字节流,转成字符流 OutputStreamWriter
* 指定处理的编码 gbk/utf-8/utf8
public class OutputStreamWriter_ {
public static void main(String[] args) throws IOException {
String filePath = "d:\\hsp.txt";
String charSet = "utf-8";
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charSet);
osw.write("hi, 韩顺平教育");
osw.close();
System.out.println("按照 " + charSet + " 保存文件成功~");
}
}
当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,建议将字节流转换为字符流
只有输出流,没有输入流
PrintStream(字节打印流)、PrintWriter(字符打印流)
PrintStream
public class PrintStream_ {
public static void main(String[] args) throws IOException {
PrintStream out=new PrintStream(System.out);
out.println("hello,world");
out.write("刘格你好".getBytes(StandardCharsets.UTF_8));
out.close();
//写入文件
System.setOut(new PrintStream("d:\\demo.txt"));
System.out.println("还得是你");
}
}
PrintWriter
public class PrintWriter_ {
public static void main(String[] args) throws IOException {
PrintWriter printWriter=new PrintWriter(new FileWriter("d:\\test.dat"));
printWriter.write("风雨之后,定见彩虹");
printWriter.close();
}
}
是专门用于读写配置文件的集合类
配置文件的格式:
键=值
键=值
代码示例:
1.使用Properties 类来读取mysql.properties 文件
public class Properties02 {
public static void main(String[] args) throws IOException {
//1. 创建Properties 对象
Properties properties = new Properties();
//2. 加载指定配置文件
properties.load(new FileReader("src\\mysql.properties"));
//3. 把k-v显示控制台
properties.list(System.out);
//4. 根据key 获取对应的值
String user = properties.getProperty("user");
String pwd = properties.getProperty("pwd");
System.out.println("用户名=" + user);
System.out.println("密码是=" + pwd);
}
}
2.使用Properties 类来创建 配置文件, 修改配置文件内容
public class Properties03 {
public static void main(String[] args) throws IOException {
Properties properties=new Properties();
//创建
//1.如果该文件没有key 就是创建
//2.如果该文件有key ,就是修改
properties.setProperty("charset", "utf8");
properties.setProperty("user", "汤姆");//注意保存时,是中文的 unicode码值
properties.setProperty("pwd", "888888");
//将k-v 存储文件中即可
properties.store(new FileWriter("src\\mysql2.properties"),null);
//properties.store()后边这个参数为注解
System.out.println("保存配置文件成功~");
}
}
1:
(1) 在判断e盘下是否有文件夹mytemp ,如果没有就创建mytemp
(2) 在e:\mytemp 目录下, 创建文件 hello.txt
(3) 如果hello.txt 已经存在,提示该文件已经存在,就不要再重复创建了
(4) 并且在hello.txt 文件中,写入 hello,world~
public class HomeWork01 {
public static void main(String[] args) throws IOException {
String directoryPath="d:\\mytemp";
File file=new File(directoryPath);
if(!file.exists()) {
if(file.mkdirs()) {
System.out.println("创建 " + directoryPath + " 创建成功" );
} else {
System.out.println("创建 " + directoryPath + " 创建失败" );
}
}
String filePath="d:\\mytemp\\hello.txt";
file=new File(filePath);
if(!file.exists()) {
if(file.createNewFile()) {
System.out.println(filePath + " 创建成功~");
BufferedWriter bw=new BufferedWriter(new FileWriter(file));
bw.write("hello, world~~ 韩顺平教育");
bw.close();
} else {
System.out.println(filePath + " 创建失败~");
}
}else {
System.out.println(filePath + " 已经存在,不在重复创建...");
}
}
}
2:
使用BufferedReader读取一个文本文件,为每行加上行号,
再连同内容一并输出到屏幕上。
public class HomeWork02 {
public static void main(String[] args) {
String filePath="d:\\story.txt";
BufferedReader br=null;
String line;
int count=0;
try {
br=new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gbk"));
while((line= br.readLine())!=null) {
System.out.println(++count+" "+line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(br!=null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3:
(1) 要编写一个dog.properties name=tom age=5 color=red
(2) 编写Dog 类(name,age,color) 创建一个dog对象,读取dog.properties 用相应的内容完成属性初始化, 并输出
(3) 将创建的Dog 对象 ,序列化到 文件 d:\dog.txt 文件
public class HomeWork03 {
public static void main(String[] args) throws IOException {
String path="src\\dog.properties";
Properties properties=new Properties();
properties.load(new FileReader(path));
String name=properties.getProperty("name");
int age= Integer.parseInt(properties.getProperty("age"));
String color=properties.getProperty("color");
Dog dog=new Dog(name,age,color);
System.out.println(dog);
String filePath="d:\\dog.txt";
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(filePath));
oos.writeObject(dog);
oos.close();
}
//反序列化
@Test
public void test() throws IOException, ClassNotFoundException {
String filePath="d:\\dog.txt";
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(filePath));
Dog dog=(Dog)ois.readObject();
System.out.println(dog);
ois.close();
}
}
class Dog implements Serializable {
String name;
int age;
String color;
public Dog(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
}
⚡️最后的话⚡️
总结不易,希望uu们不要吝啬你们的哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正