目录
1.文件操作(IO)
1.1文件操作定义
1.2绝对路径与相对路径
1.3文本文件与二进制文件
2.Java中操作文件
2.1File类
2.1.1构造方法
2.1.2常用方法
3.文件内容的读写
2.1输入流概述
2.1.1FileInputStream概述
2.1.2 FileReader概述
2.3输出流概述
2.3.1FileOutputStream概述
2.3.2FileWriter概述
3.文件io小练习
IO是input和output的缩写,翻译为中文就是输入流、输出流。
IO操作就是将数据写入内存或从内存输出的过程,也指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接 。
在输入输出中,我们需要知道以什么为基准来定义输入、输出,我们所说的输入、输出是以cpu为基准来看待的。
路径的含义:文件目录是树状结构,我们取到一个文件所经过的所有节点,就是这个文件的文件路径。
绝对路径:从根结点开始,一层一层向下找,经过的所有节点,就是绝对路径。
相对路径:从给定的某个目录出发,一层一层向下找,经过的所有节点,就是相对路径。在相对路径时,我们需要明确基准目录是哪个。
文本文件: 存储的文本遵守某些字符集编码(ASCII、utf8等),打开时,会通过对比字符集编码进行内容显示,就像我们打开文本文件时,我们都可以看懂是什么,在打开二进制文件时,内容就会出现乱码的情况(在字符集编码中无法找到相匹配的内容)。
二进制文件:二进制文件大大加大了存储的内容,它可以存储图片、音乐、视频,打开时以二进制的形式打开。
常见的文本文件(后缀):.txt、.java、.c等。
常见的二进制文件(后缀):.class、.exe、.jpg、.mp3、.docx等。
如何辨别二进制文件和文本文件?
非常简单,我们只需打开记事本,把文件拉入到记事本中,不乱码就是文本文件,乱码就是二进制文件,如下图,打开.java文件没有出现乱码,打开.docx 文件就变成了乱码。
在Java中,它给出了File类对文件进行操作。
签名 | 说明 |
---|---|
File(File parent, String child) |
根据父目录 + 孩子文件路径,创建一个新的 File 实例 |
File(String pathname) | 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者 相对路径 |
File(String parent, String child) |
根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用 路径表示 |
修饰符及返回 值类型 |
方法签名 | 说明 |
---|---|---|
String | getParent() | 返回 File 对象的父目录文件路径 |
String | getName() | 返回 FIle 对象的纯文件名称 |
String | getPath() | 返回 File 对象的文件路径 |
String | getAbsolutePath() | 返回 File 对象的绝对路径 |
String | getCanonicalPath() | 返回 File 对象的修饰过的绝对路径 |
boolean | exists() | 判断 File 对象描述的文件是否真实存在 |
boolean | isDirectory() | 判断 File 对象代表的文件是否是一个目录 |
boolean | isFile() | 判断 File 对象代表的文件是否是一个普通文件 |
boolean | createNewFile() | 根据 File 对象,自动创建一个空文件。成功创建后返 回 true |
boolean | delete() | 根据 File 对象,删除该文件。成功删除后返回 true |
void | deleteOnExit() | 根据 File 对象,标注文件将被删除,删除动作会到 JVM 运行结束时才会进行 |
String[] | list() | 返回 File 对象代表的目录下的所有文件名 |
File[] | listFiles() | 返回 File 对象代表的目录下的所有文件,以 File 对象 表示 |
boolean | mkdir() | 创建 File 对象代表的目录 |
boolean | mkdirs() | 创建 File 对象代表的目录,如果必要,会创建中间目 录 |
boolean | renameTo(File dest) |
进行文件改名,也可以视为我们平时的剪切、粘贴操 作 |
boolean | canRead() | 判断用户是否对文件有可读权限 |
boolean | canWrite() | 判断用户是否对文件有可写权限 |
IO流体系如下,它分为两组,一组是字节流,一组是字符流,对于二进制文件进行文件内容读写可以使用InputStream(读)和OutputStream(写)操作,对于文本文件进行读写使用Reader(读)和Writer(写)进行操作,上方所说的四个类是抽象类,如果需要具体实现,我们需要实例化它的子类,通过子类完成任务。
我们下面对于字节流中的类进行详细讲解:
读文件时使用的方法
修饰符及 返回值类 型 |
方法签名 | 说明 |
int | read() | 读取一个字节的数据,返回 -1 代表已经完全读完了 |
int | read(byte[] b) | 最多读取 b.length 字节的数据到 b 中,返回实际读到的数 量;-1 代表以及读完了 |
int | read(byte[] b, int off, int len) |
最多读取 len - off 字节的数据到 b 中,放在从 off 开始,返 回实际读到的数量;-1 代表以及读完了 |
void | close() | 关闭字节流 |
在read()方法中,它的返回值是byte类型,但是为什么我们要使用int来接收呢?
用int类型来代替byte类型是为了解决读到结尾时出现难以辨别的情况,因为byte的取值范围是-128~127,当我们读到文件内容的末尾时,read()的返回值会是-1(文本内容也可能是-1),因为-1在buye的取值范围内,因此你不能确定它是文本内容还是到了文本结尾,而改为int,int的取值范围是0-255,返回-1,就很容易辨别是末尾了。
该类是对字节流的读操作实现。
构造方法
方法签名 | 说明 |
FileInputStream(File file) | 利用 File 构造文件输入流 |
FileInputStream(String name) | 利用文件路径构造文件输入流 |
因为InputStream类是一个抽象类,我们想要使用,就要实例它的子类(FileInputStream)。
代码使用FileInputStream类:
import java.io.*;
public class ioDemo1 {
public static void main(String[] args) {
File file=new File("F:/test.txt");
try(InputStream inputStream=new FileInputStream("F:/test.txt")) {
while (true){
int ret=inputStream.read();
//返回-1,读到尾部
if(ret==-1) {
break;
}
System.out.println(ret);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码运行结果(ASCII码):
该类是对字符流的读操作实现。
构造方法
方法签名 | 说明 |
---|---|
FileReader(File file) | 创建一个新的 FileReader ,给出 File读取 |
FileReader(FileDescriptor fd) | 创建一个新的 FileReader ,给定 FileDescriptor读取。 |
FileReader(String fileName) | 创建一个新的 FileReader ,给定要读取的文件的名称。 |
代码使用FileReader类:
import java.io.*;
public class ioDemo3 {
public static void main(String[] args) {
File file=new File("F:/test.txt");
try(Reader reader=new FileReader("F:/test.txt")) {
while (true) {
int r = reader.read();
if (r == -1) {
break;
}
System.out.print((char)r);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码运行结果:
观察得出,他是打印的字符,他是如何打印的呢?原理很简单,在读取数据时,系统会对比对照,我们设置什么字符集编码它就以什么字符集编码对比。
写文件时使用的方法
返回 值类 型 |
方法签名 | 说明 |
---|---|---|
void | write(int b) | 写入要给字节的数据 |
void | write(byte[] b) |
将 b 这个字符数组中的数据全部写入 os 中 |
int | write(byte[] b, int off, int len) |
将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个 |
void | close() | 关闭字节流 |
void | flush() | 重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为 了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的 一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写 入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的 数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置, 调用 flush(刷新)操作,将数据刷到设备中。 |
该类是字节流的写操作。
构造方法:
方法签名 | 说明 |
---|---|
FileOutputStream(File file) | 创建文件输出流以写入由指定的 File对象表示的文件。 |
FileOutputStream(File file, boolean append) | 创建文件输出流以写入由指定的 File对象表示的文件。 |
FileOutputStream(FileDescriptor fdObj) | 创建文件输出流以写入指定的文件描述符, 表示与文件系统中实际文件的现有连接。 |
FileOutputStream(String name) | 创建文件输出流以指定的名称写入文件。 |
FileOutputStream(String name, boolean append) | 创建文件输出流以指定的名称写入文件。 |
代码使用FileOutputStream类:
import java.io.*;
public class ioDemo4 {
public static void main(String[] args) {
try (OutputStream outputStream=new FileOutputStream("F:/test.txt") ){
outputStream.write(1);
outputStream.write(2);
outputStream.write(3);
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码会将1 2 3以二进制的形式写入到F:/test.txt这个目录中的test文件中。
该类是字符流写操作
构造方法:
方法签名 | 说明 |
FileWriter(File file) | 给一个File对象构造一个FileWriter对象。 |
FileWriter(File file, boolean append) | 给一个File对象构造一个FileWriter对象。 |
FileWriter(FileDescriptor fd) | 构造与文件描述符关联的FileWriter对象。 |
FileWriter(String fileName) | 构造一个给定文件名的FileWriter对象。 |
FileWriter(String fileName, boolean append) | 构造一个FileWriter对象,给出一个 带有布尔值的文件名,表示是否附加写入的数据。 |
代码使用FileWriter类:
import java.io.*;
public class ioDemo5 {
/**
* 文本写
* @param args
*/
public static void main(String[] args) {
try(FileWriter fileWriter=new FileWriter("F:/test.txt")){
fileWriter.write(1);
fileWriter.write(2);
fileWriter.write("c");
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码会以文本的形式将 1,2,c写入文件test中。
要求:扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
public class ioDemo2 {
/**
* 查询一个字符是否存在这个目录
* @param args
*/
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
//1.输入搜索根目录
System.out.println("输入需要找到扫描的路径");
String findRootPath=sc.next();
File findRoot=new File(findRootPath);
if(!findRoot.isDirectory()) {
System.out.println("您选择的不是路径,退出");
return;
}
//2.输入需要查询的字符
System.out.println("输入需要找的字符");
String findStr=sc.next();
//3.递归进行目录遍历
scanDirWithContent(findRoot, findStr);
}
private static void scanDirWithContent(File findRoot, String findStr) {
File[] files=findRoot.listFiles();
if(files.length==0 || files==null) {
return;
}
for (File file:files) {
//是目录
if(file.isDirectory()) {
scanDirWithContent(file,findStr);
//是文件
}else if(file.isFile()) {
String content=readFile(file);
if(content.contains(findStr)) {
System.out.println(file.getAbsolutePath()+"包含字符");
}
//其他文件
}else {
continue;
}
}
}
/**
* 找字符,对的拼接起来
* @param file
* @return
*/
private static String readFile(File file) {
StringBuilder sb=new StringBuilder();
try(Reader reader=new FileReader(file)){
while (true) {
int read=reader.read();
if(read==-1) {
break;
}
sb.append((char)read);
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
}
写在最后:
以上就是本文全部内容,如果对你有所帮助,希望能留下你的点赞+关注,我会更加努力的更新内容!非常感谢
若本篇文章有错误的地方,欢迎大佬们指正!