欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java之文件输入输出流的使用

程序员文章站 2022-04-09 08:46:14
...

File 类

一个 File 类的对象可以代表一个文件或者一个目录的路径,可以是相对路径也可以是绝对路径.当创建了一个对象后,就可以使用这个对象对其指定的目录/文件进行各种各样的操作了.

构造方法

方法 说明
File(String pathname) 根据一个路径得到File对象
File(String parent, String child) 根据一个目录和一个子文件/目录得到File对象
File(File parent, String child) 根据一个父File对象和一个子文件/目录得到File对象

就拿我电脑里的 “D:\tme\tmp\FileDemo.txt” 举例,第一个构造方法来获取对象这么写就行: File file = new File("D:/tme/tmp/FileDemo.txt")

第二个构造方法这么写: File file = new File("D:/tme/tmp","FileDemo.txt")

第三个构造方法需要现有一个 File 对象作为父级目录,然后再获得父级目录下面的子目录或子文件:

//先得dě有一个父级目录的对象
File par = new File("D:/tme/tmp");
//从父级目录获得子级对象
File file = new File(par, "FileDemo.txt");

参数地址也可以用斜杠而不用反斜杠,记得使用双斜杠转义一下:

new File("D:\\tme\\tmp\\FileDemo.txt")

new File("D:\tme\tmp\FileDemo.txt")

比较常用的方法

目录/文件创建

方法 说明
boolean createNewFile() 创建文件,如果存在则不创建
boolean mkdir() 创建文件夹,如果存在则不创建
boolean mkdirs() 创建文件夹,如果父文件夹不存在,会帮你创建出来
createNewFile()

使用该方法创建一个新文件,新文件的父级目录必须是已经存在的,记得写异常处理(IDE 生成即可)

//在指定目录创建一个txt文档
File file = new File("D:/tmp/tmp/FileDemo.txt");
try {
    file.createNewFile();
} catch (IOException e) {
    e.printStackTrace();
}

如果父级目录不存在则会报错,最后一行指出错误的类名以及行数

java.io.IOException: 系统找不到指定的路径。

at java.io.WinNTFileSystem.createFileExclusively(Native Method)
at java.io.File.createNewFile(File.java:1012)
at File.FileCreateDemo.main(FileCreateDemo.java:10)

mkdir()

使用该方法创建一个新文件夹,新文件夹的父级目录必须是已经存在的

File file = new File("D:/tmp/tmp");
file.mkdir();

这里不需要异常捕捉,父级目录不存在不会报错但也不会创建新的目录

mkdirs()

使用该方法创建一个新文件夹,如果指定的父级目录不存在,照样给你创建出来

File file = new File("D:/tmp/tmp");
file.mkdirs();

不需要捕捉异常,我的电脑里 D 盘没有 tmp 这个文件夹,现在不仅有了而且还有一个 tmp 子文件夹

绝对地址/相对地址: 如果不写盘符或者根目录,则创建的文件/文件夹会产生于 IDE 的项目文件夹里


重命名和删除

方法 说明
boolean renameTo(File dest) 把文件重命名为指定的文件路径
boolean delete() 删除文件或者文件夹
renameTo(File dest)

使用该方法对 File 对象进行重命名或者移动/重命名操作

如果目标对象指定的路径和源对象的路径相同,则进行重命名操作:

File file = new File("D:/tme/tmp/FileDemo.txt");
file.renameTo(new File("D:/tme/tmp/FileRenameDemo.txt"));

renameTo() 方法中传入的是 File 类的对象这里简写直接 new 了一个,也可以老老实实的创建对象后再使用:

File dest = new File("D:/tme/tmp/FileRenameDemo.txt");
file.renameTo(dest);

这样一来,FileDemo.txt 就被重命名为 FileRenameDemo.txt 了

如果目标对象指定的路径和源对象的路径不同,则进行移动操作,也可以移动的同时重命名:

File file = new File("D:/tme/tmp/FileRenameDemo.txt");
file.renameTo(new File("D:/tme/FileDemo.txt"));

D:/tme/tmp 文件夹下的 FileRenameDemo.txt 被移动到 D:/tme 文件夹并且重命名为 FileDemo.txt

delete()

使用该方法将会直接删除文件或文件夹,连回收站都找不到(不会走系统回收站)

File file = new File("D:/tme/tmp/FileRenameDemo.txt");
file.delete();

文件/文件夹属性判断

方法 说明
boolean isDirectory() 判断是否是目录
boolean isFile() 判断是否是文件
boolean exists() 判断文件(夹)是否存在
boolean canRead() 判断文件(夹)是否可读
boolean canWrite() 判断文件(夹)是否可写
boolean isHidden() 判断文件(夹)是否隐藏

文件/文件夹属性获取

方法 说明
String getAbsolutePath() 获取文件(夹)绝对路径
String getPath() 获取文件(夹)路径
String getName() 获取文件(夹)名称
long length() 获取文件(夹)长度(字节数)
long lastModified() 获取文件(夹)最后一次的修改时间(毫秒)
String[] list(); 获取文件夹下的所有文件或者文件夹的名称并存为数组
File[] listFiles() 获取文件夹下的所有文件或者文件夹生成 File 对象并存为数组
File file = new File("D:/tme/tmp/FileDemo.txt");
File file2 = new File("D:/tme/tmp");
System.out.println("getAbsolutePath()获取文件绝对路径 " + file.getAbsolutePath());
System.out.println("getAbsolutePath()获取文件夹绝对路径 " + file2.getAbsolutePath());
System.out.println("getPath()获取文件路径 " + file.getPath());
System.out.println("getPath()获取文件夹路径 " + file2.getPath());
System.out.println("getName()获取文件名 " + file.getName());
System.out.println("getName()获取文件夹名 " + file2.getName());
System.out.println("length()获取文件长度 " + file.length());
System.out.println("length()获取文件夹长度 " + file2.length());
System.out.println("lastModified()获取文件最后修改时间 " + new Date(file.lastModified()));
System.out.println("lastModified()获取文件夹最后修改时间 " + new Date(file.lastModified()));
System.out.println("list()获取所有文件和文件夹的名称 " + Arrays.toString(file2.list()));
System.out.println("listFiles()获取所有文件和文件夹的File数组 "
 + Arrays.toString(file2.listFiles()));

输出结果:

getAbsolutePath()获取文件绝对路径 D:\tme\tmp\FileDemo.txt
getAbsolutePath()获取文件夹绝对路径 D:\tme\tmp
getPath()获取文件路径 D:\tme\tmp\FileDemo.txt
getPath()获取文件夹路径 D:\tme\tmp
getName()获取文件名 FileDemo.txt
getName()获取文件夹名 tmp
length()获取文件长度 6
length()获取文件夹长度 0
lastModified()获取文件最后修改时间 Mon Dec 24 20:49:13 CST 2018
lastModified()获取文件夹最后修改时间 Mon Dec 24 20:49:13 CST 2018
list()获取所有文件和文件夹的名称 [FileDemo.txt, 子文件夹]
listFiles()获取所有文件和文件夹的File数组 [D:\tme\tmp\FileDemo.txt, D:\tme\tmp\子文件夹]

大多数应用程序都需要和外部的设备进行数据交换,在 Java 中所有的 I/O 机制都是基于数据流的方式进行输入和输出的

流的分类

根据流动方向和传输格式的不同分为以下四种:

  • 字节输入流 InputStream
  • 字节输出流 OutputStream
  • 字符输入流 Reader
  • 字符输出流 Writer

字节流和字符流的区别

字节流是指 8 位的通用字节流,以字节为基本单位,能处理所有类型的数据

字符流是指 16 位的 Unicode 字符流,以字符(两个字节)为基本单位,仅能处理纯文本数据

字节流

InputStream

InputStream 是字节输入流,InputStream 类是一个抽象类,所有继承了该类的类都是 字节输入流

FileInputStream

FileInputStream 类是 InputStream 类的一个实现类,它是 文件输入流

方法 说明
int read() 读取一个字节并以整数的形式返回,到达文件末尾时则会返回-1
int read(byte[] buffer) 读取很多个字节并存储到数组中,返回实际读取的字节数,读取前已到输入流的末尾则返回-1
int read(byte[] buffer, int offset, int length) 读取 length 个字节存到数组,读取到输入流的末尾时返回-1
void close() 关闭输入流,释放内存对象
例子:读取文本中的文字内容
try {
    FileInputStream fileInputStream = new FileInputStream("D:/tme/tmp/FileDemo.txt");
    byte[] input = new byte[12];
    //读取12个字节存储到input数组里
    fileInputStream.read(input);
    String inputString = new String(input, "GBK");
    System.out.println(inputString);
    fileInputStream.close();
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}

使用文件流必须要做好异常处理,这里使用的是 FileInputStream 类的 read(byte[] buffer) 方法,String(input,“GBK”) 限定了读取时的字符编码为 GBK,防止乱码产生,得到输出结果

成功了哇咔咔

顺便,之所以这里用 GBK 是因为我的那个文本文件用的是 GBK 编码,只要编码格式一致就不会出现乱码.输入流在使用完成后记得关闭: close()

OutputStream

OutputStream 是字节出流,OutputStream 类是一个抽象类,所有继承了该类的类都是 字节输出流

FileOutputStream

FileOutputStream 类是 OutputStream 类的一个实现类,它是 文件输出流

方法 说明
void write(int b) 往文件中写数据,一次写一个字节
void write(byte[] b) 往文件中写数据,将byte数组中的数据全部写入到文件中
void write(byte[] b,int off ,int length) 将指定byte数组中的数据从偏移量off开始的length个字节写入此输入流
void close() 关闭流对象
例子:向磁盘中写入文件
File file = new File("fosd.txt");
String string = "尝试着写入文件";
try {
    FileOutputStream fosd = new FileOutputStream(file);
    byte[] bytes = string.getBytes();
    fosd.write(bytes);
    fosd.close();
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

异常处理还是不能少.本例中,我并没有写 file.createNewFile() ,但是输出流会自动帮忙创建这个文件.输出流用完后记得关闭. getBytes() 方法可以指定读取特定的编码方式,比如 getBytes("utf-8")

FileOutputStream 构造方法中如果只写一个 File 对象,运行时会覆盖掉文件内容,多次运行上面这段代码,文本内容也只有一句「尝试着写入文件」

使用 FileOutputStream(File file,boolean append) 方法即可指定是否是在原文本内容上追加内容

使用字节流实现文件拷贝
//源文件
File file1 = new File("D:/0.mp4");
//目标地址,需要具体到文件名
File file2 = new File("D:/tme/1.mp4");
try {
    FileInputStream inputStream = new FileInputStream(file1);
    FileOutputStream outputStream = new FileOutputStream(file2);
    byte[] bytes = new byte[1024];
    int tmp = 0;
    while ((tmp = inputStream.read(bytes)) != -1) {
        outputStream.write(bytes, 0, tmp);
    }
    outputStream.close();
    inputStream.close();
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

理一下细节:这里使用 tmp 来存储每次 read(bytes) 返回的值,其实前面每次返回的都是读取到的字节数量 1024,直到最后一次读取(最后一次读时读到的数量就是文件大小-n 个 1024),只要 tmp != -1,输出流就输出一次,从第 0 个字节开始输出 1024 个字节.

Created with Raphaël 2.2.0开始复制创建源文件对象创建目标对象创建输入流创建输出流输入流读取源文件输出流写入文件输入流返回值==-1关闭输入输出流复制完毕yesno
相关标签: IO流