目录
1.文件内容的操作
- 打开文件
- 读文件
- 写文件
- 关闭文件
针对文件内容的读写,java标准库提供了一组类,根据文件的内容分成了两个系列:
1.字节流对象,针对二进制文件,是以字节流为单位进行读写的
1)读:InputStream---------》FileInputStream
2)写:OutputStream---------》FileOutputStream
2.字符流对象,针对文本文件,是以字符为单位进行读写的
1)读:Reader---------》FileReader
2)写:Writer---------》FileWriter
为什么文件内容要称为流对象?
这里的流Stream其实是一个形象的比喻,此处我们说的流就像水流一样源源不断的感觉
举个例子,如果想要通过水龙头接100ml水,可以一次接10ml,分十次接完,也可以一次接20ml,分5次接完,还可以一次接100ml,一次接完。这里的文件内容也是一样,想通过流对象来读取100个字节,可以一次读10个字节,分10次读完,也可以一次读20个字节,分5次读完,还可以一次读取100个字节,一次读完,当然,写文件内容也是一个道理
2.四个类的具体使用
2.1InputStream

read()提供了三个版本的重载
- 无参数版本:一次读取一个字节,返回的值是读到这个字节
- 一个参数版本:一次读取若干个字节,把读到的结果放到参数中指定的数组中,返回的值就是读到的字节数
- 三个参数版本:一次读取若干个字节,把参数的结果放到指定的数组中,返回值就是读到的字节数,不是从数组的起始下标放置元素,而是从中间位置开始放元素,off表示这下标的位置,len表示最多能放多少个元素(字节)
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test1 {
public static void main(String[] args) {
try(InputStream inputStream = new FileInputStream("d:/study.txt")) {
//一次读取一个字节
while (true) {
int data = inputStream.read();
if(data == -1){
break;
}
System.out.println(data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test1 {
public static void main(String[] args) {
try(InputStream inputStream = new FileInputStream("d:/study.txt")){
//一次读取若干个字节
while (true) {
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
if (len == -1) {
break;
}
String s = new String(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
这里要注意的是为什么返回值的类型用int来表示:
一个字节的范围是 0 -> 255 or -128 -> 127,如果返回的是byte,本身就是-128 -> 127,当读到一个 -1 的时候,你到底是读到文件尾了,还是说正好有个字节就是-1这个值
所以未来表示这个非法状态,就约定了-1来表示,因此就需要使用一个比byte更大的范围来表示 int 或者 short
所以上述代码的-1的意思就是读到了文件末尾

2.2OutputStream
![]()
注意:字节流的写会清空原有文件的内容!!!
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Test2 {
public static void main(String[] args) {
try(OutputStream outputStream = new FileOutputStream("d:/study.txt")){
// outputStream.write(97);
// outputStream.write(99);
// outputStream.write(98);
//两种方法都可以
byte[] data = new byte[]{97,98,99};
outputStream.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}

2.3.Reader

字符流的读同样是包含三个方法,和字节流的用法是一样的
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class Test3 {
public static void main(String[] args) {
try(Reader reader = new FileReader("d:/study.txt")){
while (true) {
//一次读取若干个字符
char[] chars = new char[1024];
int len = reader.read(chars);
if(len == -1){
break;
}
String s = new String(chars,0,len);
System.out.println(s);
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
2.4Writer
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Test4 {
public static void main(String[] args) {
try(Writer writer = new FileWriter("d:/study.txt")){
// writer.write("a");
// writer.write("g");
// writer.write("f");
writer.write("agf");
} catch (IOException e) {
e.printStackTrace();
}
}
}
关于字符流的操作和字节流的使用基本是一致的,文件内容的写都会使原文件内容清除
3.文件内容操作的三个实例
1)扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要 删除该文件
//案例1 查找文件并删除
//扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class Demo6 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入要扫描的目录");
String mainPath = sc.next();
System.out.println("请输入包含的指定字符");
String todeleteDir = sc.next();
File file = new File(mainPath);
if(!file.isDirectory()){
System.out.println("输入有误");
return;
}
// 2. 遍历目录, 把 指定目录 中的所有文件和子目录都遍历一遍, 从而找到要删除的文件
// 通过这个方法来实现递归遍历并删除的操作
try {
scanDir(file,todeleteDir);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void scanDir(File file, String todeleteDir) throws IOException {
//1.先列出文件中都有那些内容
File[] files = file.listFiles();
if (files == null) {
//说明是一个空目录
return;
}
for(File f:files){
if(f.isFile()){
//说明是一个文件
if(f.getName().contains(todeleteDir)){
//如果包含了相同的名字就删掉
deletFile(f);
}
} else if (f.isDirectory()) {
//说明是一个目录
scanDir(f,todeleteDir);
}
}
}
private static void deletFile(File f) throws IOException {
System.out.println(f.getCanonicalFile()+"Y删除 n否定");
Scanner sc = new Scanner(System.in);
String choice = sc.next();
if(choice.equals("Y") || choice.equals("y")){
f.delete();
System.out.println("确认删除");
}else{
System.out.println("否定删除");
}
}
}
2)进行普通文件的复制
import java.io.*;
import java.util.Scanner;
//普通文件的复制
//需要让用户输入两个路径,一个源路径,一个复制的路径,将源路径的文件复制到复制路径里
public class Demo7 {
public static void main(String[] args) {
//输入源路径
System.out.println("输入源路径");
Scanner scanner = new Scanner(System.in);
String mianDirPath = scanner.next();
System.out.println("输入目标路径");
String dest = scanner.next();
File file = new File(mianDirPath);
if(!file.isFile()){
System.out.println("源路径不对");
return;
}
//先进行读
try(InputStream inputStream = new FileInputStream(mianDirPath)) {
//在进行写
try(OutputStream outputStream = new FileOutputStream(dest)){
byte[] bytes = new byte[1024];
while (true) {
int len = inputStream.read(bytes);
if(len == -1) {
break;
}
outputStream.write(bytes,0,len);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3)扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
import java.io.*;
import java.util.Scanner;
//案例三
//扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
public class Demo8 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入目录");
String src = scanner.next();
System.out.println("请输入要删除的关键字");
String words = scanner.next();
File file = new File(src);
if(!file.isDirectory()){
return;
}
scanDir(file,words);
}
private static void scanDir(File file, String words) {
//先列出文件有那些内容
File[] files = file.listFiles();
if (files == null) {
return;
}
for(File f : files){
if(f.isFile()){
if(containsWord(f,words)){
}
}else if(f.isDirectory()){
scanDir(f,words);
}
}
}
//
private static boolean containsWord(File f, String words) {
StringBuilder stringBuilder = new StringBuilder();
try(Reader reader = new FileReader(f)) {
char[] chars = new char[1024];
while (true) {
int len = reader.read(chars);
if(len == -1){
break;
}
stringBuilder.append(chars,0,-1);
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuilder.indexOf(words) != -1;
}
}
这篇博客详细介绍了JavaEE中文件操作的概念,包括为何将文件内容视为流对象,以及InputStream、OutputStream、Reader和Writer四个类的具体使用。博主通过实例展示了如何进行文件的读写,强调了字节流和字符流的区别,以及文件内容操作可能涉及的注意事项,如写操作会清空原有文件内容。

57

被折叠的 条评论
为什么被折叠?



