JavaEE|文件操作和IO

文件

包含数据内容本身+metadata(文件头信息:文件名,修改信息,文件大小等等);
文件系统结构:树型结构 JavaEE|文件操作和IO
文章图片

目录(文件夹):专门用来存放管理信息(关于文件的元信息)的特殊文件
文件路径
  • 绝对路径:从根节点到相应节点的整个路径(Windows是从各个磁盘开始)
JavaEE|文件操作和IO
文章图片

  • 相对路径:从任意一个节点出发,到目的节点,经过的路径
../:上一级目录
./:当前目录

文件划分 文本类型
本质也是基于二进制保存数据,使用一种编码格式保存文本
打开文本,需要制定编码格式——保存和打开的编码格式需要一致,否则乱码
java中,文本就是String,通过字符串.getBytes("编码格式") 返回 byte[]
二进制类型
图片,音乐,视频等
java中二进制数据byte[],可以转文本(String)
new String(byte数组); new String(byte[],"编码格式");

文件后缀
Windows 操作系统上,会按照文件名中的后缀来确定文件类型以及该类型文件的默认打开程序。但这个习俗并不是通用的,在 OSX、Unix、Linux 等操作系统上,就没有这样的习惯,一般不对文件类型做如此精确地分类。
文件权限
文件由于被操作系统进行了管理,所以根据不同的用户,会赋予用户不同的权限;
可读,可写,可执行;
很多操作系统为了实现接口的统一性,将所有的 I/O 设备都抽象成了文件的概念,使用这一理念最为知名的就是 Unix、Linux 操作系统 —— 万物皆文件
Java中操作文件(metadata操作) File
Java中通过java.io.File类 对一个文件(包括目录)进行抽象的描述。
属性:
修饰符及类型
属性
说明
static String
pathSeparator
依赖于系统的路径分隔符,
String 类型的表示
static char
pathSeparator
依赖于系统的路径分隔符,
char 类型的表示
构造方法:
签名
说明
File(String pathname)
根据文件路径(绝对路径或相对路径)创建一个新的
File 实例,路径可以是绝对路径或者相对路径
注意:有File 对象,并不代表真是存在该文件(new File不受影响)
File f = new File("E:/xxx") 该路径不存在,但File对象正常实例化,只是不存在(可以通过方法判断)
方法:
修饰符及返回值类型
方法签名
说明
boolean
createNewFile()
创建一个文件(路径中不存在才可以创建,即为新文件)
boolean
delete()
删除文件或目录:目录下为空,才可删除;非空目录,需要依次遍历删除
boolean
exists()
判断文件或目录是否存在
Stirng
getName()
获取文件或目录名称
String
getPath()
获取文件或目录路径
boolean
isDirectory()
是否为目录
boolean
isFile()
是否为文件
long
lastModified()
返回文件的上次修改时间(long)=>转换为Date
long
length()
返回文件大小(字节数)
File[]
listFiles
返回目录的下一级子目录或子文件
boolean
mkdir()
创建一个目录
boolean
mkdirs()
创建多级目录
boolean
renameTo(File dest)
重命名文件:传入目标文件路径(可以在原有位置重命名,也可做移动操作)
//创建文件 File f = new File("E:\\file\\创建文件.txt"); if(!f.exists()) { f.createNewFile(); } File f = new File("E:/file/单级目录"); if(!f.exists()){ f.mkdir(); } //多级目录 File f2 = new File("E:/file/多级目录/1/2"); f2.mkdirs(); //获取文件信息 File f = new File("E:/file/创建文件.txt"); System.out.println("path: "+f.getPath()); System.out.println("name: "+f.getName()); //返回文件的大小(字节数) System.out.println("length: "+f.length()); //返回上次修改时间:返回一个Long,可以转换为时间 System.out.println("last modified: "+f.lastModified()); System.out.println("last modified => Date: "+new Date(f.lastModified())); System.out.println("isFile: "+f.isFile()); System.out.println("isDirectory: "+f.isDirectory()); //重命名 File f1 = new File("E:/file/创建文件.txt"); f1.renameTo(new File("E:/file/创建文件_rename.txt")); //移动 File f2 = new File("E:/TMP/1_rename.txt"); f2.renameTo(new File("E:/TMP/1/1_rename.txt")); //删除文件 //File f = new File("E:/TMP/1/1_rename.txt"); //f.delete(); //删除目录:目录下没有东西才可以删 //所以:如果删除有东西的目录:要一个一个遍历,依次删除 File f = new File("E:/TMP/1"); f.delete();

文件内容读写(IO) 概念
将数据从一个设备传输到另一个设备,就是IO操作
i : input 输入
o: output 输出
输入输出相对自身而言
IO的不同类型(从不同层面) 来源:文件IO,网络IO
方向:
输入流(读取数据),输出流(写数据)
System.in:标准输入流
System.out:标准输出流
System.err:错误输出流
操作流注意事项:
  • 对读取操作来说(输入流):已读取的部分,不能再次读
  • io的输入流可以在此嵌套输入流,输出流可以在此嵌套输出流(理解:字节输出转字符输出
  • 使用完io流,要关闭流

IO流—输入流(java) 1.InputStream 输入流的顶级抽象类,所有真实使用的io流,都其子类
方法
修饰符及返回值类型
方法签名
说明
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()
关闭字节流
2.FileInputStream 文件的输入流
  • 读入文件内容
  • 读取文本,二进制文件,都是读取至byte数组中
构造方法
签名
说明
FileInputStream(File file)
利用 File 构造文件输入流
FileInputStream(String name)
利用文件路径构造文件输入流

//单个字节读取 public static void read1() throws IOException{ FileInputStream fis = new FileInputStream("E:/file/创建文件.txt"); //available()文件中可用的字节数 byte[] bytes = new byte[fis.available()]; int b; //不停的读,一直读到输入流结束(文件结束) for(int i=0; (b=fis.read())!=-1; i++) bytes[i]=(byte) b; System.out.println(new String(bytes)); fis.close(); } //字节数组读取 public static void read2() throws IOException{ FileInputStream fis = new FileInputStream("E:/file/创建文件.txt"); //先准备一个字节数组,用来保存每次读取的数据 byte[] bytes = new byte[1024]; //每次读取的长度 int len; //不停的读,一直读到输入流结束(文件结束) while((len=fis.read(bytes))!=-1){ //此时,字节数组中,0~len范围,就是读取的数据 //二进制数据转为字符串,需要和保存时的编码格式一致 //String的构造方法,把字节数组,从offset(偏移量)的位置,读取len个长度 //也就是,将 offset 到 offset+len 范围的字节数据,转为字符串 String s = new String(bytes,0,len,"UTF-8"); System.out.println(s); } fis.close(); }

3.字符输入流 使用InputStreamReader字节字符转换流
使用BufferedReader => 读文本文件,且效率较高
使用了缓冲区:
单个字节或字节数组读取,效率比较低;
内存速度远高于硬盘,但这种读取操作,进程read,都需要等待硬盘传输完,这个过程中进程是阻塞等待的;
通过缓冲区,当读取到达一定数量再进行读取

public static void main(String[] args) throws IOException { //使用的比较多的是BufferedReader => 读文本文件,且效率比较高 //先获取一个字节流 FileInputStream fis = new FileInputStream("E:/TMP/1.txt"); //在包装为一个字节字符转换流 InputStreamReader isr = new InputStreamReader(fis, "GBK"); //再包装为字符流 BufferedReader br = new BufferedReader(isr); String line; //读取一行,如果没结束,就一直读 while((line=br.readLine()) != null){ System.out.println(line); } }

IO流—输出流 1.OutputStream 输出流的顶级抽象类,使用的输出流都是其子类
修饰符及返回值类型
方法签名
说明
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(刷新)操作,将数据刷到设备中
2.FileOutputStream 文件字节输出流
构造方法:
方法签名
说明
FileOutputStream(File file)
FileOutputStream(String name)
FileOutputStream(File file,boolean appead)
appead:是否追加文件内容
true:追加
false:覆盖原内容
通过继承OutStream的三个write方法,写字节数据(文本,二进制数据)
结合实际代码通过循环语句多组写入
//单字节写入 public static void write1() throws IOException { FileOutputStream fos = new FileOutputStream("E:/file/创建文件.txt"); //写入的字节数据 int n = 2; fos.write(n); fos.flush(); } //多字节写入 public static void write2() throws IOException { FileOutputStream fos = new FileOutputStream("E:/file/创建文件.txt"); //写入的字节数据 byte[] bytes = new byte[1024]; //写入数据的长度 int len = 1023; fos.write(bytes,0,len); fos.flush(); }

3.字符输出流 使用OutputStreamWriter字节字符转换流
//先获取字节输出流 FileOutputStream fos = new FileOutputStream("E:/file/创建文件.txt"); //包装为字节字符转换流 OutputStreamWriter osw = new OutputStreamWriter(fos,"编码格式");

使用BufferedWriter
//包装为字符输出流 BufferedWriter bw = new BufferedWriter(osw);

【JavaEE|文件操作和IO】

    推荐阅读