文件是存储在硬盘上的
操作系统把硬盘上的内容抽象成文件,供程序来使用
下面是read的使用方法
往往读一个比较大的文件,需要循环读取
如何循环读取呢,我们看看代码
public static void main(String[] args) throws IOException {
try(Reader reader = new FileReader("d:/test.txt")){
while(true){
char buf[] = new char[1024];
int n = reader.read(buf);//把空数组填入内容
if (n==-1){//如果读到的不是文件末尾,就会返回你读到多少个字符这样的个数
//读完了,读到文件末尾了
break;
}
for (int i = 0;i<n;i++){
System.out.print(buf[i]+" ");//打印出每个字符
}
}
}
}
test是我放在D盘里的txt文件,里面的内容是"hello world"
运行结果如图
这段代码的运行逻辑是在while里,创建一个数组,在数组中读入文件中的字符,尽可能填满,n是你读到多少个字符,然后判断n是否是-1,如果是-1说明已经读到文件末尾了,就可以跳出循环,如果n不等于-1,就打印字符
InputStream是字节流,用法和Reader非常相似
文本文件也可以使用字节流打开,只不过此时你读到的每个字节,就不是完整字符了
public class Demo7 {
public static void main(String[] args) throws IOException {
try(InputStream inputStream = new FileInputStream("d:/test.txt")){
while (true){
byte[]buf = new byte[1024];
int n = inputStream.read(buf);
if (n==-1){
break;
}
for (int i = 0;i<n;i++){
System.out.printf("%x ",buf[i]);//十六进制
}
}
}
}
}
运行结果如图
把文本的每个字节都读取出来,就能看到实际的中文是怎么编码的了
Java虽然有char,更多的是使用String
此处,借助一些额外的工具类,就可以完成从字节/字符到字符串的转换
虽然也可以直接使用String 的构造方法完成char[]或者byte[]=>字符串的转换,但是这比较麻烦
===>麻烦
我们可以这样做
public class Demo8 {
public static void main(String[] args) throws IOException {
try(InputStream inputStream = new FileInputStream("d:/test.txt")){
Scanner scanner = new Scanner(inputStream);
//此时就是从test.txt这个文件中读取数据
String s = scanner.next();
System.out.println(s);
}
}
}
运行结果如图
以前学过的Scanner的操作,在这里完全试用
但是Scanner只是用来读文本文件的,不适合读取二进制文件
在标准库中,还提供了一些工具类,辅助更方便地读写二进制格式的文件
输出的使用方法和输入非常相似
write之前要打开文件,用完了也需要关闭文件
接下来我们看看代码
public class Demo9 {
public static void main(String[] args) throws IOException {
try(Writer writer = new FileWriter("d:/test.txt")){
//write是可以直接写一个字符串,这个很方便
writer.write("你好世界");
}
}
}
运行完以后文件内容变为
我们发现之前的hellowould不见了
这是因为输出流对象(无论字节流还是字符流)会在打开文件之后,清空文件内容
我们也可以按照追加写方式打开,此时就不会清空内容了
public class Demo9 {
public static void main(String[] args) throws IOException {
try(Writer writer = new FileWriter("d:/test.txt",true)){
//write是可以直接写一个字符串,这个很方便
writer.write("你好世界");
}
}
}
我们在构造方法那里加上true
然后看看运行结果
这样就不会清空之前的内容了
OutputStream使用方式完全一样.只不过write方法不能支持字符串参数,只能按照字节,或者字节数组来写入
读操作和写操作也能支持"随机访问",可以移动光标到指定位置,进行读写
接下来我们看一些实例
扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除文件
import java.io.File;
import java.util.Scanner;
public class Demo10 {
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
//先让用户输入一个目录,我们后续的查找都是根据这个目录进行的
System.out.println("请输入要搜索的根目录");
File rootPath = new File(scanner.next());
//再让用户输入要搜索/要删除的关键词
System.out.println("请输入要删除的关键词");
String word = scanner.next();
//判断一下当前目录是否有效
if (!rootPath.isDirectory()){
System.out.println("您此时输入的路径不是合法目录!");
return;
}
//遍历目录,从根目录出发,根据深度优先(递归)的方式,进行遍历
scanDir(rootPath,word);
}
public static void scanDir(File currentDir,String word){//currentDir是你当前根据哪一个目录进行扫描
//先列出当前目录中都包含哪些内容
File[] files = currentDir.listFiles();
if (files == null||files.length ==0){
//空的目录或者是非法的目录
return;
}
//遍历列出的文件,分两个情况分别讨论
for (File f:files){
//加个日志,方便我们去看文件执行的过程
System.out.println(f.getAbsolutePath());
if (f.isFile()) {
//如果当前文件是普通文件,看看文件名是否包含了Word,来决定是否要删除
dealFile(f,word);
}else{
//如果当前文件是目录文件,就递归执行scanDir
scanDir(f,word);
}
}
}
private static void dealFile(File f, String word) {
//先判断当前文件名是否包含Word
if (!f.getName().contains(word)){
//此时这个文件不包含Word关键词,直接跳过
return;
}
//包含Word就需要询问用户是否要删除该文件
System.out.println("该文件是:"+f.getAbsolutePath()+",是否要确认删除?(Y/N)");
String choice = scanner.next();
if (choice.equals("Y")||choice.equals("y")){
f.delete();
}
//如果是其他的值,都忽略
}
}
运行测试结果如图
这样就成功删除test文件了
这道题也是一道经典面试题,让你写一个代码递归遍历目录
下一题进行普通文件的复制,把一个文件给复制成另一个文件
如果要把文件A复制成文件B,只要打开A依次读出每个字节,再写入到文件B就行
import java.io.*;
import java.util.Scanner;
//完成文件复制
public class Demo11 {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
//输入路径并且进行合法性判定
System.out.println("请输入要复制的源文件路径:");
String src = scanner.next();
File srcFile = new File(src);
if (!srcFile .isFile()){
System.out.println("您输入的源文件路径非法");
return;
}
System.out.println("请输入要复制到的目标路径:");
String dest = scanner.next();
File destFile = new File(dest);
//不要求目标文件存在,但是得保证目标文件所在的目录是存在的
//假设目标文件写作d:/tmp/cat2.jpg,就需要保证d:/tmp是存在的
if (!destFile.getParentFile().isDirectory()){
System.out.println("您输入的目标文件路径非法!");
return;
}
//进行复制操作的过程,按照字节流打开
try(InputStream inputStream = new FileInputStream(srcFile);
OutputStream outputStream = new FileOutputStream(destFile)){
while (true){
byte[]buffer = new byte[1024];
int n = inputStream.read(buffer);
//System.out.println("n="+n);
if (n==-1){
System.out.println("读取到eof,循环结束.");
break;
}
outputStream.write(buffer,0,n);
}
}
}
}
运行结果如图
然后我们就能看见两个cat.jpg文件了