一、File类的使用File类的使用
java.io.File 类: 文件和文件目录路径 的抽象表示形式,与平台无关
File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。
如果需要访问文件内容本身,则需要使用输入 / 输出流。
想要在 Java 程序中表示一个真实存在的文件或目录,那么必须有一个 File 对
象,但是 Java 程序中的一个 File 对象,可能没有一个真实存在的文件或目录。
File 对象可以作为参数传递给流的构造器
File类常用构造器:
public File(String pathname)
以 pathname 为路径创建 File 对象,可以是 绝对路径或者相对路径 ,如果
pathname 是相对路径,则默认的当前路径在系统属性 user.dir 中存储。
绝对路径:是一个固定的路径 , 从盘符开始
相对路径:是相对于某个位置开始
public File(String parent,String child)
以 parent 为父路径, child 为子路径创建 File 对象。
public File(File parent,String child)
根据一个父 File 对象和子文件路径创建 File 对象
File类的获取功能
public String getAbsolutePath() : 获取绝对路径
public String getPath() :获取路径
public String getName() :获取名称
public String getParent() : 获取上层文件目录路径。若无,返回 null
public long length() :获取文件长度(即:字节数)。不能获取目录的长度。
public long lastModified() :获取最后一次的修改时间,毫秒值
public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组
public File[] listFiles() :获取指定目录下的所有文件或者文件目录的 File 数组
File类的重命名功能
public boolean renameTo(File dest): 把文件重命名为指定的文件路径
File类的判断功能
public boolean isDirectory() : 判断是否是文件目录
public boolean isFile() : 判断是否是文件
public boolean exists() :判断是否存在
public boolean canRead() :判断是否可读
public boolean canWrite() :判断是否可写
public boolean isHidden() :判断是否隐藏
File类的创建功能
public boolean createNewFile() : 创建文件。若文件存在,则不创建,返回 false
public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。
如果此文件目录的上层目录不存在,也不创建。
public boolean mkdirs() : 创建文件目录。如果上层文件目录不存在,一并创建
注意事项:如果你创建文件或者文件目录没有写盘符路径,那么,默认在项目
路径下。
File类的删除功能
public boolean delete() : 删除文件或者文件夹
删除注意事项:
Java 中的删除不走 回收站 。
要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录
练习
1. 利用 File 构造器, new 一个文件目录 file
1) 在其中创建多个文件和目录
2) 编写方法,实现删除 file 中指定文件的操作
@Test /** * 1. 利用File构造器,new 一个文件目录file * 1)在其中创建多个文件和目录 * 2)编写方法,实现删除file中指定文件的操作 */ public void test1() throws IOException { File file = new File("d:/File","file"); if(file.createNewFile()){ System.out.println("文件目录创建成功!"); } File file1 = new File("d:/file/Smile.txt"); if(file1.createNewFile()){ System.out.println("子文件创建成功!"); } File dir=new File("d:/file/dir"); if(dir.mkdir()){ System.out.println("子文件目录创建成功!"); } deleteFile(dir); deleteFile(file); deleteFile(file1); } public void deleteFile(File file){ if(file.delete()){ System.out.println("文件删除成功!"); } }
2. 判断指定目录下是否有后缀名为 .jpg 的文件,如果有,就输出该文件名称
public void test2(){ File file = new File("d:"); judgeJpg(file); } public void judgeJpg(File file){ String[] strings=file.list(); for (int i = 0; i <strings.length ; i++) { if(strings[i].endsWith(".jpg")){ System.out.println(strings[i]); } } }
3. 遍历指定目录所有文件名称,包括子文件目录中的文件。
@Test /** * 遍历指定目录所有文件名称,包括子文件目录中的文件。 */ public void test3(){ File file = new File("c:"); String[] strings=file.list(); for (String str:strings) { System.out.println(str); } }
拓展 1 :并计算指定目录占用空间的大小
@Test /** * 遍历指定目录所有文件名称,包括子文件目录中的文件。 * 并计算指定目录占用空间的大小 */ public void test3(){ File file = new File("c:"); String[] strings=file.list(); File[] files=file.listFiles(); int sum=0; for (String str:strings) { System.out.println(str); } for (File file1:files) { sum+=file1.length(); } System.out.println(sum); }
拓展 2 :删除指定文件目录及其下的所有文件
public void deleteAll(File file){ if(file==null||!file.exists()){ System.out.println("文件路径输入有误!"); }else{ File[] files = file.listFiles(); //遍历该目录下的文件对象 for (File f: files){ //打印文件名 String name = file.getName(); System.out.println(name); //判断子目录是否存在子目录,如果是文件则删除 if (f.isDirectory()){ deleteFile(f); }else { f.delete(); } } //删除空文件夹 for循环已经把上一层节点的目录清空。 file.delete(); } }
二、IIO流原理及流的分类
IO原理
I/O 是 Input/Output 的缩写, I/O 技术是非常实用的技术,用于 处理设备之间的数据传输 。如读 / 写文件,网络通讯等。
Java 程序中,对于数据的输入 / 输出操作以 “流 (stream) ” 的
方式进行。
java.io 包下提供了各种“流”类和接口,用以获取不同种类的
数据,并通过 标准的方法 输入或输出数据。
输入 input : 读取外部数据(磁盘、光盘等存储设备的数据)到 程序(内存)中。
输出 output : 将程序(内存)数据输出到磁盘、光盘等存储设 备中。
流的分类
按操作 数据单位 不同分为: 字节流 (8 bit) ,字符流 (16 bit)
按数据流的 流向 不同分为: 输入流,输出流
按流的 角色 的不同分为: 节点流,处理流
节点流:直接从数据源或目的地读写数据
处理流:不直接连接到数据源或目的地,而是“连接”在已存
在的流(节点流或处理流)之上,通过对数据的处理为程序提
供更为强大的读写功能。
InputStream & Reader
InputStream 和 Reader 是所有 输入流 的基类。
InputStream (典型实现: FileInputStream )
int read()
int read(byte[] b)
int read(byte[] b, int off, int len)
Reader (典型实现: FileReader )
int read()
int read(char [] c)
int read(char [] c, int off, int len)
程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资
源,所以应该 显式关闭文件 IO 资源 。
FileInputStream 从文件系统中的某个文件中获得输入字节。 FileInputStream
用于读取非文本数据之类的原始字节流。要读取字符流,需要使用 FileReader
OutputStream & Writer
OutputStream 和 Writer 也非常相似:
void write( int b / int c );
void write( byte[] b / char[] cbuf );
void write( byte[] b / char[] buff, int off, int len);
void flush();
void close(); 需要先刷新,再关闭此流
因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来替换字符数组,
即以 String 对象作为参数
void write(String str);
void write(String str, int off, int len);
FileOutputStream 从文件系统中的某个文件中获得输出字节。 FileOutputStream
用于写出非文本数据之类的原始字节流。要写出字符流,需要使用 FileWriter
三、节点流(或文件流)
读取文件
1.利用字符流
@Test /** * 读取文件 */ public void test1() { FileReader fr= null; try { //1.建立一个流文件,将已存在的文件加载进流 fr = new FileReader("Hello.txt"); //2.创建一个存放临时文件的char型数组 char[] buffer=new char[1024]; //3.调用对象流的方法将文件读到数组中 int len=0; while ((len=fr.read(buffer))!=-1) { System.out.println(new String(buffer, 0, len)); } } catch (IOException e) { e.printStackTrace(); } finally { //4.关闭文件流 if (fr!=null){ try { fr.close(); } catch (IOException e) { e.printStackTrace(); } } }
2.利用字节流
@Test /** * 2.利用字节流读取文件 */ public void test2() { FileInputStream fi= null; try { //1.建立一个流文件,将已存在的文件加载进流 fi = new FileInputStream("Hello.txt"); //2.创建一个存放临时文件的char型数组 byte[] buffer=new byte[1024]; //3.调用对象流的方法将文件读到数组中 int len=0; while ((len=fi.read(buffer))!=-1) { System.out.println(new String(buffer, 0, len)); } } catch (IOException e) { e.printStackTrace(); } finally { //4.关闭文件流 if (fi!=null){ try { fi.close(); } catch (IOException e) { e.printStackTrace(); } } } }
写入文件
1.利用字符流写文件
@Test /** * 1.利用字符流写文件 */ public void test1(){ FileWriter fw= null; try { //1.创建流文件,建立数据存放文件 fw = new FileWriter("Hello.txt"); //2.调用对象的写入方法,将数据存入文件 fw.write("加油!!!"); } catch (IOException e) { e.printStackTrace(); } finally { //3.关闭流文件 if(fw!=null){ try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } }
注意点:
定义文件路径时,注意:可以用“ /” 或者“\\”。
在 写入 一个文件时,如果使用构造器 FileOutputStream(file) ,则 目录下有同名文 件将被覆盖。
如果使用构造器 FileOutputStream(file,true) ,则目录下的同名文件不会被覆盖, 在文件内容末尾追加内容。
在 读取 文件时,必须保证该文件已存在,否则报异常。
字节流操作字节,比如: .mp3 , .avi , .rmvb , mp4 , .jpg , .doc , .ppt
字符流操作字符,只能操作普通文本文件。最常见的文本文 件:.txt , .java , .c , .cpp 等语言的源代码。尤其注意 .doc,excel,ppt 这些不是文本文件。
四、缓冲流
为了提高数据读写的速度 , Java API 提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用 8192 个字节 (8Kb) 的缓冲区 。
缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
BufferedInputStream 和 BufferedOutputStream
BufferedReader 和 BufferedWriter
当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区
当使用 BufferedInputStream 读取字节文件时, BufferedInputStream 会一次性从
文件中读取 8192 个 (8Kb) ,存在缓冲区中,直到缓冲区装满了,才重新从文件中
读取下一个 8192 个字节数组。
向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,
BufferedOutputStream 才会把缓冲区中的数据一次性写到文件里。使用方法
flush() 可以强制将缓冲区的内容全部写入输出流
关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也
会相应关闭内层节点流
flush() 方法的使用:手动将 buffer 中内容写入文件
如果是带缓冲区的流对象的 close() 方法,不但会关闭流,还会在关闭流之前刷
新缓冲区,关闭后不能再写出
练习: 实现图片加密操作。
@Test /** * 实现对图片的加密 */ public void encrypt() { BufferedInputStream bis= null; BufferedOutputStream bos= null; try { bis = new BufferedInputStream(new FileInputStream("20204.jpg")); bos = new BufferedOutputStream(new FileOutputStream("20206.jpg")); byte[] buffer=new byte[1024]; int len=0; while((len=bis.read())!=-1){ bos.write(len^5); } } catch (IOException e) { e.printStackTrace(); } finally { if(bis!=null){ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } if(bos!=null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test /** * 实现对图片的解密 */ public void decrypt() { BufferedInputStream bis= null; BufferedOutputStream bos= null; try { bis = new BufferedInputStream(new FileInputStream("20206.jpg")); bos = new BufferedOutputStream(new FileOutputStream("20208.jpg")); byte[] buffer=new byte[1024]; int len=0; while((len=bis.read())!=-1){ bos.write(len^5); } } catch (IOException e) { e.printStackTrace(); } finally { if(bis!=null){ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } if(bos!=null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
五、转换流
转换流提供了在字节流和字符流之间的转换
Java API 提供了两个转换流:
InputStreamReader :将 InputStream 转换为 Reader
OutputStreamWriter :将 Writer 转换为 OutputStream
字节流中的数据都是字符时,转成字符流操作更高效。
很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能
public static void main(String[] args) { BufferedReader br= null; BufferedWriter bw= null; try { FileInputStream fis = new FileInputStream("D:/IDEA/day01/Smile.txt"); InputStreamReader isr=new InputStreamReader(fis); br = new BufferedReader(isr); FileOutputStream fos=new FileOutputStream("new.txt"); OutputStreamWriter osw=new OutputStreamWriter(fos); bw = new BufferedWriter(osw); String str; while((str=br.readLine())!=null){ bw.write(str); } } catch (IOException e) { e.printStackTrace(); } finally { if(bw!=null){ try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } if(br!=null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void test() { FileReader fr= null; try { fr = new FileReader("Hello.txt"); char[] buffer=new char[1024]; int len=0; while((len=fr.read(buffer))!=-1){ System.out.println(new String(buffer, 0, len)); } } catch (IOException e) { e.printStackTrace(); } finally { if(fr!=null){ try { fr.close(); } catch (IOException e) { e.printStackTrace(); } } } }