java文件操作
File类
File类是对文件和文件夹操作的一个类,它有以下几个功能:
- 创建文件/文件夹
- 删除文件/文件夹
- 查找文件/文件夹(判断是否存在)
- 获取文件/文件夹
- 遍历文件夹
- 获取文件大小
由于不同操作系统的分隔符可能不同,所以File类有以下成员变量用于表示分隔符: - 默认名称分隔符:File.separatorr,即""
- 默认路径分隔符:File.pathSeparator,即";"
File类的创建
File的构造方法有三种:
一个参数:其参数是文件的路径,创建File的对象,其参数表示的文件可以不存在;
两个参数:前者表示父路径,后者表示子路径,组合起来表示文件路径;
两个参数:前者表示父类文件,后者表示子类文件;
当我们直接打印File对象时,将会打印出file的路径,即传递的参数:
File file1 = new File("D:/IDEA/FileMode/1.txt");
System.out.println(file1); //D:\IDEA\FileMode\1.txt
File file2 = new File("D:/IDEA/FileMode/","1.txt");
System.out.println(file2); //D:\IDEA\FileMode\1.txt
File file3 = new File("D:/IDEA/FileMode/");
File file4 = new File(file1,"1.txt");
System.out.println(file4); //D:\IDEA\FileMode\1.txt
File类的方法
1.获取文件路径,名称,大小
- String getPath(); //获取文件路径
- String getName(); //获取文件名
- long length(); //获取文件大小
File file = new File("D:/IDEA/FileMode/1.txt");
System.out.println(file.getAbsolutePath()); //D:\IDEA\FileMode\1.txt
System.out.println(file.getName()); //1.txt
System.out.println(file.getAbsoluteFile()); //D:\IDEA\FileMode\1.txt
System.out.println(file.getPath()); //D:\IDEA\FileMode\1.txt
System.out.println(file.length()); //15
2.判断文件类型及是否存在
- boolean exists(); //判断文件是否存在
- boolean isFile(); //判断文件是否位文件
- boolean isDirectory(); //判断文件是否为文件夹
File file = new File("D:/IDEA/FileMode/1.txt");
System.out.println(file.exists()); //true
System.out.println(file.isFile()); //true
System.out.println(file.isDirectory()); //false
3.创建,删除文件/文件夹(路径中的后缀无效,默认为名称)
- boolean createNewFile(); //创建新文件
- boolean delete(); //删除文件/文件夹
- boolean mkdir(); //创建单级目录
- boolean mkdirs(); //创建单级目录或多级目录
File file1 = new File("D:/javaTestFile/temp1.txt");
//创建文件
try{
if(!file1.exists()) file1.createNewFile();
}catch (IOException e){
System.out.println("文件创建失败");
}
//创建单级文件夹
File file2 = new File("D:/javaTestFile/temp2");
try {
if(!file2.exists()) file2.mkdirs();
}catch (NullPointerException e) {
System.out.println("创建目录失败");
}
//创建多级文件夹
File file3 = new File("D:/javaTestFile/temp3/temp3_1/temp3_2");
try {
if(!file3.exists()) file3.mkdirs();
}catch (NullPointerException e) {
System.out.println("创建目录失败");
}
//删除文件和文件夹
file1.delete();
file2.delete();
4.获取文件夹下所有文件及文件夹(路径必须为文件夹路径)
- String[] list(); //获取文件夹下所有文件和文件夹,返回字符串数组
- File[] listFiles(); //获取文件夹下所有文件和文件夹,返回文件数组
File file = new File("D:/javaTestFile");
String list[] = file.list();
for(String s : list){
System.out.println(s);
}
File files[] = file.listFiles();
for(File f : files){
System.out.println(f.getName());
}
遍历多级目录查找目标文件
使用递归遍历目录即可,下面的代码演示了查找javaTestFile目录下的所有txt文件
import java.io.File;
public class FileTest_3 {
public static void main(String[] args) throws NullPointerException{
File file = new File("D:/javaTestFile");
searchFile(file);
}
public static void searchFile(File file){
File lists[] = file.listFiles();
for(File f : lists) {
if (f.isDirectory()) {
searchFile(f);
}
if (f.getName().endsWith("txt")) {
System.out.println(f.getPath());
}
}
}
}
FileFilter——文件过滤器
FileFilter,即文件过滤器,是java库中的一个接口,用于筛选文件,文件过滤器使用原理如下图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/9ddec8d1d4514e2b49278bb2286ee3b2.png)
- 创建子类实现FileFilter,重写accept方法定义过滤规则,然后将子类对象传递进listFile(FileFilterImpl ff)方法的参数中,示例如下:
1.实现FileFilter,重写accept的规则为查找txt文件
import java.io.FileFilter;
import java.io.File;
public class FileFilterImpl implements FileFilter {
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().endsWith("txt");
}
}
2.创建过滤器过滤文件
import java.io.File;
import java.io.FilenameFilter;
public class FileTest_3 {
public static void main(String[] args) throws NullPointerException{
File file = new File("D:/javaTestFile");
searchFile(file);
}
public static void searchFile(File file){
File lists[] = file.listFiles(new FileFilterImpl());
for(File f : lists) {
if (f.isDirectory()) {
searchFile(f);
}
if (f.getName().endsWith("txt")) {
System.out.println(f.getPath());
}
}
}
}
- 或者使用匿名内部类,下面以FileNameFilter,另一个文件过滤器(效果同FileFilter)示例:
import java.io.File;
import java.io.FilenameFilter;
public class FileTest_3 {
public static void main(String[] args) throws NullPointerException{
File file = new File("D:/javaTestFile");
searchFile(file);
}
public static void searchFile(File file){
File lists[] = file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir,name).isDirectory() || name.endsWith("txt");
}
});
for(File f : lists) {
if (f.isDirectory()) {
searchFile(f);
}
if (f.getName().endsWith("txt")) {
System.out.println(f.getPath());
}
}
}
}
RandomAccessFile——随机读写文件
RandomAccessFile即可以读取文件内容,也可以向文件中写入内容,它包含了一个记录指针,用以标记当前读写处的位置,它的每次操作都是在指针所在处,所以它可以直接跳到文件的任意位置来读写数据。
RandomAccessFile的创建
RandomAccessFile的构造方法有两个参数,第一个是文件,第二个是权限管理:“r” 只读;“rw” 可读可写;“rws” 可读可写,并要求对文件内容或元数据的每个更新都同步写入到底层设备;“rwd” 可读可写,并要求对文件内容每个更新都同步写入到底层设备。
File file = new File(filePath);
RandomAccessFile raf = new RandomAccessFile(file,"rw"); //可读可写
RandomAccessFile的方法及注意事项
RandomAccessFile常用的方法如下:
- RandomAccessFile的read()和write()方法,同其他文件操作类
- long getFilePointer(); //返回文件记录指针的当前位置
- void seek(long pos); //将文件记录指针定位到pos位置
注意事项: - 在seek方法中指针是从0~n-1的,所以当指针指向length,读取的值是-1
- 用了RandomAccessFile的read方法后,指针会往后移动一个字符,而readline后会移动到下一行的开头,也就是再read就是下一行的开头第一字符。
RandomAccessFile实现在任意位置写文件和读文件
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RamdomAccessFileTest {
public static void main(String[] args) {
//创建readme.txt
File file = new File("D:/javaTestFile/Readme.txt");
try {
if (!file.exists()) {
file.createNewFile();
}
//创建RamdomAccess对象
RandomAccessFile raf = new RandomAccessFile(file, "rw");
//写第一行和第二行
String line1 = "line1";
String line2 = "line2";
raf.write(line1.getBytes());
raf.write("\n".getBytes());
raf.write(line2.getBytes());
//将指针移至第二行开始处
int pos = 0;
while(pos++ < raf.length()){
raf.seek(pos);
if(raf.read() == '\n') break;
pos++;
}
raf.seek(++pos);
//读第二行内容
String l2 = raf.readLine().toString();
System.out.println(l2);
//指针移至文件末尾
String line3 = "line3";
raf.seek(raf.length());
//追加内容写第三行
raf.write("\n".getBytes());
raf.write(line3.getBytes());
raf.close();
}catch (IOException e){
System.out.println("读写异常");
}
}
}
IO流
IO流,即输入输出流,表示数据在内存和硬盘之间的传输,Input输入流就是从硬盘读取数据到内存,output输出流就是从内存将数据存储到硬盘中
- 输入流:即读取源中的数据,输出流:传送数据到目的地
![](https://i-blog.csdnimg.cn/blog_migrate/242e81c681717d9225aa77295a880e11.png)
OutputStream字节输出流
OutputStream是所有输出流的超类,有以下方法供所有输出流使用:
- void close(); //关闭流
- void flush(); //刷新流,写出所有缓冲字节
- void write(byte b[]); //以字节数组写入
- void write(byte b[],int offset,int len); //写入b[offset]~b[len]的字节
- void write(int b) //写入字节b
FileOutputStream——文件字节输出流
FileOutputStream是文件字节输出流,用于把内存数据写入到硬盘中
FileOutputStream的创建
FileOutputStream有构造方法有3种形式,都需要抛出FileNotFoundException:
- FileOutputStream(File file); //创建文件输出流以写入由指定的 File对象表示的文件。
- FileOutputStream(String name); //创建文件输出流以路径写入文件。
- FileOutputStream(File file,boolean append); //同上,第二个参数有true和false两种形式,若为true,则表示将字节将写入文件的末尾而不是开头,为false则表示写入文件开头,即覆盖原内容
package IOlearining;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class FileOutputStreamTest {
public static void main(String[] args) {
File file1 = new File("D:/javaTestFile/1.txt");
try {
FileOutputStream fos1 = new FileOutputStream(file1);
FileOutputStream fos2 = new FileOutputStream("D:/javaTestFile/2.txt");
FileOutputStream fos3 = new FileOutputStream("D:/javaTestFile/3.txt",true);
}catch (FileNotFoundException e){
System.out.println("文件未找到");
}
}
}
FileOutputStream的使用
- 写数据,write方法演示:
File file = new File("D:/javaTestFile/1.txt");
try{
FileOutputStream fos =new FileOutputStream(file,false);
fos.write(46); //ASCII编码,46对应“."
fos.write("\n".getBytes()); //换行
fos.write("abc".getBytes()); //写入abc
fos.write("\n".getBytes()); //换行
fos.write("defg".getBytes(),1,2); //写入ef
fos.close();
}catch (FileNotFoundException e){
System.out.println("文件未找到");
}catch (IOException e){
System.out.println("写文件异常");
}
- 注意FileOutputStream是字节流,将文本按字节写入文件,而一个汉字是两个字节,无法一次写入,直接写入中文就会出现乱码,可以使用OutputStreamWriter将字节流转换为字符流写入:
FileOutputStream fos =new FileOutputStream(file,false);
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
osw.append("中文输入"); //写入成功,没有乱码
osw.close();
ByteArrayOutputStream——字节数组输出流
ByteArrayOutputStream在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组缓冲区中,写入到文件等其他outputStream
ByteArrayOutputStream的创建
ByteArrayOutputStream有2个构造方法:
- ByteArrayOutputStream bops = new ByteArrayOutputStream(); //无参数默认缓冲大小为32
- ByteArrayOutputStream bops = new ByteArrayOutputStream(int size); //设置缓冲大小为size
ByteArrayOutputStream的使用
ByteArrayOutputStream的方法如下:
- 3个继承于OutputStream的write方法,使用相同
- writeTo(OutputStream os); //将此字节数组输出流的全部内容写入到指定的输出流参数中。
- toString(); //将缓冲区的内容转换为字符串
- toByteArray(); //复制输出流的字节数组内容
- size(); //返回缓冲区大小
- reset(); //重置字节输出流,清除存储的数据
示例:获取字符串,将除空格以外的数据写入流中并输出:
package Test_02;
import java.io.*;
public class SkipWhiteSpaceOutputStream extends ByteArrayOutputStream{
void putSkipWhitespaceString(String str){
byte b[] = str.getBytes();
ByteArrayOutputStream bops = new ByteArrayOutputStream(100);
for(int i = 0 ; i < b.length ; i++){
if((char)b[i] != ' ') bops.write(b[i]);
}
String out = bops.toString();
System.out.println(out);
}
public static void main(String[] args) throws IOException {
String str;
Scanner sc = new Scanner(System.in);
str = sc.nextLine();
SkipWhiteSpaceOutputStream swops = new SkipWhiteSpaceOutputStream();
swops.putSkipWhitespaceString(str);
}
}
测试结果:
![](https://i-blog.csdnimg.cn/blog_migrate/eade6c87afecf22c9d5dd6d7f2213eaa.png)
BufferedOutputStream——字节缓冲输出流
BufferedOutputStream字节缓冲输出流,使用缓存流将数据写入文件,使用BufferedOutputStream的好处就是能够提高效率:
![](https://i-blog.csdnimg.cn/blog_migrate/8fb6ecae82f0a4f5c49439610d4fe71b.png)
BufferedOutputStream的构造
BufferedOutputStream有2种构造方法:
- BufferedOutputStream(OutputStream os); //构造一个字节缓冲输出流对象
- BufferedOutputStream(OutputStream os,int size); //指定size缓冲区大小构造缓冲输出流对象
BufferedOutputStream的使用
package IOlearining;
import java.io.*;
public class BufferdTest {
public static void main(String[] args) throws FileNotFoundException, IOException {
FileOutputStream fos = new FileOutputStream("D:/javaTestFile/1.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write(97);
bos.close();
}
}
Inputstream字节输入流
InputStream是所有输入流的超类,有以下方法供所有输入流使用:
- void close(); //关闭流
- void read(); //读取数据的下一个字节
- void read(byte b[]); //读取数据,大小为b的大小
FileInputStream——文件输入流
FileInputStream类是文件输入流,从文件中读取字节。
FileInputStream的构建
类似于FileOutputStream,FileInputStream也有2种构造方法,且需要抛出FileNotFoundException异常:
- FileInputStream(File file): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的file命名。
- FileInputStream(String name): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名命名。
FileInputStream的使用
- 读取字节数据read()方法,需要抛出IOException异常:
package IOlearining;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamTest {
public static void main(String[] args) throws IOException,FileNotFoundException {
File file = new File("D:/javaTestFile/1.txt");
FileInputStream fis = new FileInputStream(file);
int i;
while((i=fis.read())!=-1){
System.out.print((char)i);
}
fis.close();
}
}
- read(byte[] b)方法,需要抛出IOException异常,注意需要注意有效位,因为是将数据传入byte数组并覆盖,若数据位数不足,会导致byte数组没有被替换完全,如下所示:
package IOlearining;
import java.io.*;
public class FileInputStreamTest {
public static void main(String[] args) throws IOException{
FileInputStream fis = new FileInputStream("D:/javaTestFile/1.txt"); // 文件中为abcde
int len ;
byte[] b = new byte[2];
while ((len= fis.read(b))!=-1) {
System.out.println(new String(b)); //错误,最后一次会输出de,因为最后一次只有1个数据,所以byte数组中的数据d没有被替换
System.out.println(new String(b,0,len)); // 正确写法,len 每次读取的有效字节个数
}
fis.close();
}
}
- 同样的,FileInputStream的read方法只能读取一个字节,不能读取汉字,否则会乱码,可以使用InputStreamWriter将字节流转换为字符流写入:
package IOlearining;
import java.io.*;
public class FileInputStreamTest {
public static void main(String[] args) throws IOException,FileNotFoundException {
File file = new File("D:/javaTestFile/1.txt");
FileInputStream fis = new FileInputStream(file);
int i;
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
while((i=isr.read())!=-1){
System.out.print((char)i);
}
isr.close();
fis.close();
}
}
直接采用文件输入输出流复制文件
package IOlearining;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyTest {
public static void main(String[] args) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\zycjj\\Pictures\\1.jpg");
FileOutputStream fos = new FileOutputStream("D:/javaTestFile/1.jpg");
byte b[] = new byte[1024];
int len;
while((len=fis.read())!=-1){
fos.write(b,0,len);
}
fis.close();
fos.close();
}
}
字符流
字符流不同于字节流的地方就是,流中的数据是以字符形式传递,所以流数据是中文也不会乱码
Reader——字符输入流
Reader是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法:
- void close(); ///关闭此流并释放与此流相关联的任何系统资源。
- int read(); //从输入流读取一个字符。
- int read(char[] c); //从输入流中读取一些字符,并将它们存储到字符数组中 。
字符输入流Reader的使用完全类似于字节输入流,如下:
public class ReaderTest {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("D:/javaTestFile/1.txt");
int len ;
char[] c= new char[2];
while ((len = fr.read(c))!=-1) {
System.out.println(new String(c,0,len));
}
fr.close();
}
}
Writer——字符输出流
Writer是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法:
- void write(int c) // 写入单个字符。
- void write(char[] c) //写入字符数组。
- void write(char[] c, int off, int len) //写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
- void write(String str) //写入字符串。
- void write(String str, int off, int len) //写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
- void flush() //刷新该流的缓冲。
- void close() //关闭此流,但要先刷新它。
package IOlearining;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterTest {
public static void main(String[] args) throws FileNotFoundException, IOException {
FileWriter fw =new FileWriter("D:/javaTestFile/1.txt");
fw.write("字符串"); //写字符串
fw.write("\n"); //写字符串
fw.write('c'); //写字符
fw.write('\n'); //写字符
fw.write(97); //写字节
char c[] = "字符数组".toCharArray();
fw.write(c); //写字符数组
fw.close();
}
}
采用缓存输入输出流,使用Writer和reader复制文件
package Test_03;
import java.io.*;
public class FileTest {
public static void main(String[] args) {
//获取目录下的所有文件
File file = new File("D:/javaTestFile");
File files[] = file.listFiles();
try {
//创建新文件夹
File newDir = new File("D:/tmp");
if (!newDir.exists()) {
newDir.mkdir();
}
for (int i = 0; i < files.length; i++) {
if (files[i].isFile() && files[i].getName().endsWith("txt")) { //筛选txt文件
System.out.println(files[i].getName());
//复制txt文件
File objFile = new File("D:/tmp",files[i].getName());
if(!objFile.exists()) {
objFile.createNewFile();
}
//读取源文件内容
Reader fr = new FileReader(files[i]);
BufferedReader br = new BufferedReader(fr);
String str;
//复制源文件内容
FileWriter fw = new FileWriter(objFile);
BufferedWriter bw = new BufferedWriter(fw);
while ((str = br.readLine()) != null){
try {
bw.write(str);
bw.newLine();
}catch (IOException e){
System.out.println("写文件失败");
}
}
bw.close();
}
}
}catch (FileNotFoundException e) {
System.out.println("文件未找到");
}catch (IOException e){
System.out.println("读写错误");
}
}
}
Properties类
Properties类,主要用于配置读取Java的配置文,原理类似于Map,是以键值对的形式进行参数配置的。
它有几个常用方法:
- getProperty ( String key) //用指定的键在此属性列表中搜索属性
- list(PrintStream out) //将此属性列表打印到指定的输出流
- load ( InputStream inStream) //从输入流中读取属性列表(键和元素对)
- setProperty ( String key, String value) //同put方法
- store ( OutputStream out, String comments) //将此 Properties 表中的属性列表(键和元素对)写入输出流
- Set stringPropertyNames() ` :所有键的名称的集合。
- void clear () // 清除所有装载的 键 - 值对。
package IOlearining;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
public class ProportyTest {
public static void main(String[] args) throws IOException {
File file = new File("D:/javaTestFile/1.proporties");
//配置
Properties pro = new Properties();
pro.setProperty("font-size","15px");
pro.setProperty("font-color","black");
System.out.println(pro.getProperty("font-size")); //15px
System.out.println(pro.getProperty("font-color")); //black
Set<String> setPro = pro.stringPropertyNames();
for(String key : setPro){
System.out.println(key + " : " + pro.getProperty(key));
//依次输出:font-color : black font-size : 15px
}
//将配置存储到文件中
pro.store(new FileOutputStream(file),"文件注释");
pro.clear();
}
}