读完本文你能学会使用FileInputStream和FileOutputStream进行文件内容的输入输出。
在本文的最后有小案例:在指定目录下递归查询该目录下的所有子文件,进行文件的复制等,这些操作都是使用FileInputStream和FileOutputStream类进行文件操作完成的
// 获得文件的相关信息
public static void main(String[] args) throws IOException {
// pathname:可以是绝对路径也可以是相对路径
// 如果直接写文件名,默认是相对路径
File file = new File("./test.txt");
System.out.println(file.getName());
System.out.println(file.getParent());
System.out.println(file.getPath());
System.out.println(file.getAbsolutePath());
System.out.println(file.getCanonicalPath());
}
// 创建普通文件和文件夹,并且删除普通文件和文件夹
public static void main(String[] args) throws IOException, InterruptedException {
// test.txt文件不存在
File file = new File("test.txt");
// 创建文件,并立刻删除(为了效果显示中间使用thread进行了休眠)
file.createNewFile(); // 创建文件
Thread.sleep(3000);
file.delete(); // 删
// 创建文件,并在退出的时候删除该文件
file.createNewFile(); // 创建文件
Thread.sleep(3000);
file.deleteOnExit(); // 不立即删除文件,而是在程序退出的时候删除
Thread.sleep(300
// 创建目录
File dir = new File("./dir");
dir.mkdir(); // 使用mkdir只能创建单级目录
System.out.println(dir.isDirectory());
Thread.sleep(1000);
dir.deleteOnExit(); // 不立即删除文件夹,而是在程序退出的时
File dirs = new File("./dir1/dir2/dir3");
dirs.mkdirs(); // 使用mkdirs可以创建多级目录
System.out.println(dirs.isDirectory());
// 注意delete不能删除多级目录,只能通过递归的方式来删除多级目录
// 调用deleteDir函数
deleteDir("./dir1");
Thread.sleep(1000);
}
public static void deleteDir(String basePath) {
File file = new File(basePath);
if (file.isFile()) {
file.delete();
}
String[] dir = file.list();
for (String d : dir) {
deleteDir(basePath + "/" + d);
}
file.delete();
}
// 显示所有文件列表
public static List<String> files = new ArrayList<>(); // 文件列表
public static void main(String[] args) {
// 打印当前目录(.)下的所有文件
File file = new File(".");
String[] list = file.list(); // 使用list()方法可以返回当前目录下的所有文件
System.out.println(Arrays.toString(list)); // 将String[]数组转换成Str
// 打印当前目录下的所有文件及其子文件
showAllFile(".");
for (String f : files) {
System.out.println(f);
}
public static void showAllFile(String basePath) {
// 如果是普通文件直接打印文件名,如果是目录就使用list()列出当前目录下的所有文件
File file = new File(basePath);
if (file.isFile()) {
files.add(file.getName());
return;
}
// 这里只考虑目录文件
String[] dir = file.list();
for (String s : dir) {
showAllFile(basePath + "/" + s);
}
}
// 文件的移动(文件的剪贴)
public static void main(String[] args) throws IOException {
// 在当前目录下创建一个test.txt文件,并将这个目录移动到tmp目录下
File file = new File("./test.txt");
file.createNewFile();
File dir = new File("./tmp");
dir.mkdir();
File newFile = new File("./tmp/test.txt");
file.renameTo(newFile); // 将file文件改名成newFile文件就相当于file文件剪贴到tmp目录下
}
// 文件的输入输出
public static void main(String[] args) throws IOException { // 对于异常的处理直接throws
// 创建一个FileInputStream文件流
/第一种写法/
InputStream inputStream = new FileInputStream("./test.txt");
// 方法一:使用输入文件流中的read()可以将文件的内容进行读取
while (true) {
int b = inputStream.read();
if (b == -1) break;
System.out.printf("%c", b);
}
inputStream.close(); // 记得一定要关闭输入文件流
/第二种写法/
// 方法二:使用try catch finally更科学地调用close方法
InputStream inputStream1 = null;
try {
inputStream1 = new FileInputStream("./test.txt");
while (true){
int b = inputStream1.read();
if (b == -1) break;
System.out.printf("%c", b);
}
} catch(IOException e) {
e.printStackTrace();
} finally {
try {
inputStream1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/第三种写法
// 方法三:try with resources语法,在try的()中new一个FileInputStream对象
// 在文件不用的时候,自动调用close方法,这样就不用手动调用close()了
try (InputStream inputStream2 = new FileInputStream("./test.txt")) {
while (true) {
int b = inputStream2.read();
if (b == -1) break;
System.out.printf("%c", b);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 使用byte[]作为缓冲区进行文件读取
// 使用try with resouce创建一个FileInputstream
try (InputStream inputStream = new FileInputStream("./test.txt")) {
byte[] buffer = new byte[1024];
while (true) {
// 将文件内容放入buffer缓冲区中
int len = inputStream.read(buffer);
if (len == -1) break;
// 不同的编码格式下,一个字符所用的字节数不同,所以不能直接按%c的方式进行读取,否则有可能出现乱码
for (int i = 0; i < len; i ++) {
System.out.printf("%c", buffer[i]);
}
for (int i = 0; i < len; i += 3) {
String s = new String(buffer, i, 3, "UTF-8");
System.out.printf(s);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 处理字节转换成字符的编码格式问题
public static void main(String[] args) {
// 按照utf-8的规则,将3个字节合成一个字节进行处理
try (InputStream inputStream = new FileInputStream("./test.txt")) {
byte[] buffer = new byte[1024];
while (true) {
int len = inputStream.read(buffer);
if (len == -1) break;
// 使用utf-8的标准,将每三个字节拼接成一个字符打印出来
for (int i = 0; i < len; i += 3) {
String s = new String(buffer, i, 3, "UTF-8");
System.out.print(s);
}
}
} catch (IOException e) {
e.printStackTrace();
}
// 使用Scanner进行文件内容的编码格式处理
try (InputStream inputStream = new FileInputStream("./test.txt")) {
// 将inputStream从文件中读取到的数据交给Scanner,让Scanner处理字符集的问题
// Scanner使用完inputStream应该是要关闭的,但是由于外面包了一层try(),所以inputstream可以自动关闭
// 如果Scanner接收的inputStream是System.in标准输入的话,一般不关闭
try(Scanner scanner = new Scanner(inputStream)) {
while (scanner.hasNext()) {
System.out.print(scanner.next());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 使用OutputStream向文件写入内容
public static void main(String[] args) {
// 创建一个OutputStream对象就会覆盖式写入内容到文件当中
// 但是使用OutputStream对象中的方法(例如:write())写入都是追加式写入
try (OutputStream outputStream = new FileOutputStream("./test.txt")) {
// 写入一个字节
outputStream.write('a');
// 写入多个字节
byte[] buffer = new byte[] {
(byte)'a', (byte)'b', (byte)'c'
};
outputStream.write(buffer);
// 将字符串转换成byte()格式
String s = "hello world";
outputStream.write(s.getBytes(
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 使用PrintWriter类接收OutputStream对象打开的文件进行写入更方便
// 使用PrintWriter对象中的方法可以像输出内容到显示屏一样,输出到文件中
try (OutputStream outputStream = new FileOutputStream("./test.txt")) {
try(PrintWriter printWriter = new PrintWriter(outputStream)) {
printWriter.println("hello world");
}
}catch (IOException e) {
e.printStackTrace();
}
}
案例
// 指定一个目录,并输入需要查找文件的字符,扫描整个目录去寻找并询问用户有指定字符的文件是否要删除
public static void main(String[] args) throws IOException {
// 获得需要扫描的目录
System.out.print("请输入一个根目录(绝对路径): ");
Scanner scanner = new Scanner(System.in);
String root;
while (true) {
root = scanner.next();
File rootDir = new File(root);
if (!rootDir.isDirectory()) {
System.out.println("输入的路径有误,请重新输入");
continue;
}
break;
}
// 获得需要查找的文件包含的字母
System.out.print("请输入文件包含的字符:");
String token = scanner.next();
// 扫描整个目录中的文件,将包含指定字符的文件放入res中
List<String> res = new ArrayList<>();
scanWholeDir(root, token, res);
// 询问用户是否要删除找到的文件
for (String file : res) {
System.out.print(file + " 是否要删除 (Y/N): ");
String input = scanner.next();
if (input.equals("Y")) {
File delFile = new File(file);
delFile.delete();
}
}
}
private static void scanWholeDir(String root, String token, List<String> res) throws IOException {
File file = new File(root);
if (file.isFile()) {
// 获得文件的决定路径
String name = file.getCanonicalPath();
// 判断文件的名字中是否包含指定字符
if (name.contains(token)) {
res.add(name);
}
} else {
String[] files = file.list();
for (String f : files) {
scanWholeDir(root + "/" + f, token, res);
}
}
}
// 进行文件的复制
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 获得源文件地址
System.out.print("请输入需要复制的文件的地址(绝对路径):");
String srcPath = scanner.next();
File srcFile = new File(srcPath);
if (!srcFile.isFile()) {
System.out.println("输入地址有误, 程序退出");
return ;
}
// 获得目标文件地址
System.out.print("请输入要将文件复制到的路径(绝对路径):");
String destPath = scanner.next();
File destFile = new File(destPath);
if (destFile.exists()) {
System.out.println("当前文件已存在,不能将文件复制到该文件中。程序退出");
return ;
}
// 进行文件内容的拷贝
try (InputStream inputStream = new FileInputStream(srcFile);
OutputStream outputStream = new FileOutputStream(destFile)
) {
byte[] buffer = new byte[1024];
while (true) {
int len = inputStream.read(buffer);
if (len == -1) break;
outputStream.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 在指定目录中找出文件名包含或者文件内容包含关键字的文件
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
// 1. 获得需要搜索的根目录
System.out.print("请输入根目录(绝对路径): ");
String rootDir = scanner.next();
File rootFile = new File(rootDir);
if (!rootFile.isDirectory()) {
System.out.println("路径错误,程序退出");
return ;
}
// 2. 获得搜索的关键字
System.out.print("请输入搜索关键字:");
String query = scanner.next();
// 3. 进行扫描
List<File> res = new ArrayList<>();
scanDirWithQuery(rootFile, query, res);
// 4. 打印结果
for (File file : res) {
System.out.println(file.getCanonicalPath());
}
}
private static void scanDirWithQuery(File rootFile, String query, List<File> res) {
if (rootFile.isDirectory()) {
File[] files = rootFile.listFiles();
for (File f : files) {
scanDirWithQuery(f, query, res);
}
} else {
if (rootFile.getName().contains(query) ||
contentContainQuery(rootFile, query)) {
res.add(rootFile);
}
}
}
private static boolean contentContainQuery(File rootFile, String query) {
// 将文件中的内容拼接成一个字符串,然后在这个字符串中查询指定的字符串是否存在
StringBuffer stringBuffer = new StringBuffer();
try (InputStream inputStream = new FileInputStream(rootFile)) {
try (Scanner scanner = new Scanner(inputStream)) {
while (scanner.hasNextLine()) {
stringBuffer.append(scanner.nextLine() + "\n");
}
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuffer.indexOf(query) != -1;
}