File类概述和构造方法:
File类的概述
文件和目录路径名的抽象表示形式
构造方法
public File(String pathname)
public File(String parent,String child)
public File(File parent,String child)
创建功能
public boolean createNewFile()
public boolean mkdir()
public boolean mkdirs()
删除功能
public boolean delete()
重命名功能
public boolean renameTo(File dest)
判断功能
public boolean isDirectory()
public boolean isFile()
public boolean exists()
public boolean canRead()
public boolean canWrite()
public boolean isHidden()
基本获取功能
public String getAbsolutePath()
public String getPath()
public String getName()
public long length()
public long lastModified()
高级获取功能
public String[] list()
public File[] listFiles()
File类练习:
判断单级目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称
import java.io.File; import java.io.FilenameFilter; public class FileTest { public static void main(String[] args) { // 判断单级目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称 method2(); method2(); } private static void method2() { // 1.将指定的目录封装成File对象 File file = new File("E:/aa"); //2.使用过滤器过滤指定后缀名结尾的文件 File[] files = file.listFiles(new FilenameFilter() { /* * 当且仅当该名称应该包含在文件列表中时返回 true;否则返回 false(non-Javadoc) * dir - 被找到的文件所在的目录。 name - 文件的名称 */ @Override public boolean accept(File dir, String name) {//文件夹中有多少个文件,这个方法就会执行多少次 //判断当前的文件是否是一个标准文件且后缀名是否是以.jpg结尾 return new File(dir,name).isFile()?name.endsWith(".jpg"):false; } }); //3.遍历数组 for (File f : files) { System.out.println(f); } } private static void method1() { // 1.将指定的目录封装成File对象 File file = new File("E:/aa"); // 2.获取该文件夹底下所有的子文件数组 File[] files = file.listFiles(); // 3.遍历每一个子文件,判断后缀名是否以.jpg结尾 for (File f : files) { if (f.getName().endsWith(".jpg")) { System.out.println(f); } } } }
IO流概述:
IO流用来处理设备之间的数据传输 上传文件和下载文件
Java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中
IO流分类
按照数据流向
输入流 读入数据
输出流 写出数据
按照数据类型
字节流 字符流
什么情况下使用哪种流呢?
如果数据所在的文件通过windows自带的记事本打开并能读懂里面的内容,就用字符流。
其他用字节流。 如果你什么都不知道,就用字节流
IO流常用基类
字节流的抽象基类:
InputStream ,OutputStream。
字符流的抽象基类:
Reader , Writer。
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
如:InputStream的子类FileInputStream。 如:Reader的子类FileReader。
FileOutputStream的构造方法
FileOutputStream(File file)
FileOutputStream(String name)
字节流写数据的方式
public void write(int b)
public void write(byte[] b)
public void write(byte[] b,int off,int len)
数据写成功后,为什么要close()?
A:让流对象变成垃圾,这样就可以被垃圾回收器回收了
B:通知系统去释放跟该文件相关的资源
如何实现数据的换行?
不同的系统针对不同的换行符号识别是不一样的?
windows:\r\n
linux:\n
Mac:\r
而一些常见的个高级记事本,是可以识别任意换行符号的
如何实现数据的追加写入?
用构造方法带第二个参数是true的情况即可
字节流读取数据
inputStream
FileInputStream 把刚才写的数据读取出来显示在控制台
FileInputStream的构造方法
FileInputStream(File file)
FileInputStream(String name)
FileInputStream的成员方法
public int read()
public int read(byte[] b)
import java.io.FileInputStream; import java.io.FileOutputStream; public class CopyFileTest { public static void main(String[] args) { String srcPath=""; String destPath=""; copyFile(srcPath,destPath); } /** * 使用普通字节流拷贝任何标准文件 * * @param srcPath * 原文件路径 * @param destPath * 目标文件路径 */ private static void copyFile(String srcPath, String destPath) { try ( // 先读 FileInputStream fis = new FileInputStream(srcPath); // 后写 FileOutputStream fos = new FileOutputStream(destPath);) { // 自定义一个容器用于存放读取的字节数据 byte[] buf = new byte[1024]; // 定义一个变量用于保存每次读取的实际字节个数 int len; /* * 循环读写 把读取到的内容放到buf中,把实际读取的字节个数赋值给len;如果len不等于-1说明还有数据就继续读取 */ while ((len = fis.read(buf)) != -1) { // 读多少就写出多少 fos.write(buf, 0, len); } System.out.println("拷贝文件成功"); } catch (Exception e) { e.printStackTrace(); } } // 新特性关流 private static void method2() { try ( // 先读 FileInputStream fis = new FileInputStream("E:/a.txt"); // 后写 FileOutputStream fos = new FileOutputStream("D:/b.txt");) { // 自定义一个容器用于存放读取的字节数据 byte[] buf = new byte[1024]; // 定义一个变量用于保存每次读取的实际字节个数 int len; /* * 循环读写 把读取到的内容放到buf中,把实际读取的字节个数赋值给len;如果len不等于-1说明还有数据就继续读取 */ while ((len = fis.read(buf)) != -1) { // 读多少就写出多少 fos.write(buf, 0, len); } System.out.println("拷贝文件成功"); } catch (Exception e) { e.printStackTrace(); } } // 传统方式关流 private static void method1() { FileInputStream fis = null; FileOutputStream fos = null; try { // 先读 fis = new FileInputStream("E:/a.txt"); // 后写 fos = new FileOutputStream("D:/b.txt"); // 自定义一个容器用于存放读取的字节数据 byte[] buf = new byte[1024]; // 定义一个变量用于保存每次读取的实际字节个数 int len; /* * 循环读写 把读取到的内容放到buf中,把实际读取的字节个数赋值给len;如果len不等于-1说明还有数据就继续读取 */ while ((len = fis.read(buf)) != -1) { // 读多少就写出多少 fos.write(buf, 0, len); } System.out.println("拷贝文件成功"); } catch (Exception e) { e.printStackTrace(); } finally { // 先创建的流后关闭 IOUtils.closeOut(fos); IOUtils.closeIn(fis); } } }
字节缓冲流
字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果
java本身在设计的时候,也考虑到了这样的设计思想(装饰设计)
所以提供了字节缓冲区流 字节缓冲输出流 BufferedOutputStream 字节缓冲输入流 BufferedInputStream
字节流操作要注意的问题 flush()的作用 flush()和close()的区别
字节流 和字符缓冲流 拷贝文件、音频、图像等性能比较
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; /* * 写出的数据是写入到了缓冲区中,如何将缓冲区中的数据刷新到硬盘文件中? * 1.主动调用flush将数据强制刷新到硬盘文件中 * 2.调用输出流的close方法,close方法内部会调用flush方法 * 3.当缓冲区满了,数据溢出,会将数据被动的刷新到硬盘文件中 * * 什么时候主动调用flush方法将数据刷新到指定文件中呢? * 当有一部分数据需要立马刷新出去的时候,可以主动的调用flush;如果数据不是特别着急刷新出去,那么可以等到最后关流的时候统一刷新出去 */ public class CopyFileTest3 { public static void main(String[] args) { //开始时间 long start = System.currentTimeMillis(); String srcPath=""; String destPath=""; copyFile(srcPath,destPath); //结束时间 long end = System.currentTimeMillis(); //时间差 System.out.println(end-start);//字节流 和字符缓冲流 性能比较 } /** * 使用字节缓冲流拷贝标准文件的方法 * * @param srcPath * 原文件路径 * @param destPath * 目标文件路径 */ private static void copyFile(String srcPath, String destPath) { try ( // 先读 // public BufferedInputStream(InputStream in)创建一个 // BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。创建一个内部缓冲区数组并将其存储在 // buf 中 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcPath)); // 后写 // public BufferedOutputStream(OutputStream // out)创建一个新的缓冲输出流,以将数据写入指定的底层输出流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destPath));) { // 自定义一个容器用于存放每次读取的字节数据 byte[] buf = new byte[1024]; // 定义一个变量用于保存实际读取的字节个数 int len; // 循环的读写 while ((len = bis.read(buf)) != -1) { // 读多少就写出多少 bos.write(buf, 0, len); } System.out.println("拷贝文件成功"); } catch (Exception e) { e.printStackTrace(); } } }
编码表概述和常见的编码表简单介绍:
编码表 :由字符及其对应的数值组成的一张表
Charset.defaultCharset().displayName() 计算机只能识别二进制数据,早期由来是电信号。 为了方便应用计算机,让它可以识别各个国家的文字。
就将各个国家的文字用数字来表示,并一一对应,形成一张表。
ASCII:美国标准信息交换码。 用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表 用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
GB18030:GBK的取代版本 BIG-5码 :通行于台湾、香港地区的一个繁体字编码方案,俗称“大五码”。
Unicode:国际标准码,融合了多种文字。 所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符。 UTF-8不同,
它定义了一种“区间规则”,这种规则可以和ASCII编码保持最大程度的兼容:
它将Unicode编码为00000000-0000007F的字符,用单个字节来表示它将Unicode编码为00000080-000007FF的字符用两个字节表示
它将Unicode编码为00000800-0000FFFF的字符用3字节表示
转换流构造方法:
OutputStreamWriter 字符输出流
public OutputStreamWriter(OutputStream out)
public OutputStreamWriter(OutputStream out,String charsetName)
InputStreamReader 字符输入流
public InputStreamReader(InputStream in)
public InputStreamReader(InputStream in,String charsetName)
OutputStreamWriter写数据
public void write(int c)
public void write(char[] cbuf)
public void write(char[] cbuf,int off,int len)
public void write(String str)
public void write(String str,int off,int len)
InputStreamReader读数据
public int read()
public int read(char[] cbuf)
转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类。
FileWriter
FileReader
FileWriter和FileReader实现文本文件的复制
import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; /* * 转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类。 * InputStreamReader对应简化写法:FileReader * OutputStreamWriter对应简化写法:FileWriter * * FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。 * 要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。 * * FileWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。 * 要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter */ public class CopyTextFileTest { public static void main(String[] args) { // 把E:/a.txt内容复制到D:/b.txt中 String srcPath = "E:/a.txt"; String destPath = "D:/b.txt"; copyTextFile(srcPath, destPath); } /** * 使用普通字符流拷贝文本文件 * * @param srcPath * 原文件路径 * @param destPath * 目标文件路径 */ private static void copyTextFile(String srcPath, String destPath) { try ( // 先读 FileReader fr = new FileReader(srcPath); // 后写 FileWriter fw = new FileWriter(destPath);) { // 定义一个字符数组容器用于存放每次读取的字符数据 char[] cbuf = new char[1024]; // 定义一个变量用于保存每次读取的字符个数 int len; // 循环读写 while ((len = fr.read(cbuf)) != -1) { // 读多少就写出多少 fw.write(cbuf, 0, len); } System.out.println("拷贝文件成功"); } catch (Exception e) { e.printStackTrace(); } } }
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; /* * BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了 BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了 BufferedReader有一个特殊的方法:readLine直接读取一行数据 BufferedWriter有一个特殊的方法:newLine直接输出一个换行分隔符 Alt+Shift+Z:封装代码的快捷键 */ public class CopyTextFileTest2 { public static void main(String[] args) { // 把E:/a.txt内容复制到D:/b.txt中 String srcPath = "E:/a.txt"; String destPath = "D:/b.txt"; // 使用字符缓冲流拷贝文件的效率不是很高,缓冲字符流想单独读取数据,或者单独的写出数据时推荐使用 copyTextFile(srcPath, destPath); } /** * 使用字符缓冲流的readLine和write方法直接操作一行数据拷贝,会多出一个换行分隔符 * * @param srcPath * 原文件路径 * @param destPath * 目标文件路径 */ private static void copyTextFile(String srcPath, String destPath) { try ( // 先读 // public BufferedReader(Reader in)创建一个使用默认大小输入缓冲区的缓冲字符输入流 BufferedReader br = new BufferedReader(new FileReader(srcPath)); // 后写 // public BufferedWriter(Writer out)创建一个使用默认大小输出缓冲区的缓冲字符输出流 BufferedWriter bw = new BufferedWriter(new FileWriter(destPath));) { // 声明一个变量用于保存每次读取的行的内容 String line; // 循环的读取 // public String readLine()读取一个文本行,包含该行内容的字符串,不包含任何行终止符;如果已到达流末尾,则返回 // null while ((line = br.readLine()) != null) { // 读取一行就写出一行 bw.write(line); // 写出一个换行分隔符 // public void newLine()写入一个行分隔符 bw.newLine(); } System.out.println("拷贝文件成功"); } catch (Exception e) { e.printStackTrace(); } } }
//复制单极文件夹中指定文件并修改文件名称
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.util.Scanner; import java.util.UUID; //复制单极文件夹中指定文件并修改文件名称 public class CopySingleFolder { public static void main(String[] args) { // 1.将原文件夹路径封装成File对象 File srcFolder = new File("E:/tt"); // 2.要在指定的文件夹中创建一个一模一样名字的文件夹 File destFolder = new File("D:/",srcFolder.getName()); destFolder.mkdirs(); // 3.过滤指定的文件 Scanner sc = new Scanner(System.in); System.out.println("请输入要拷贝的文件的后缀名:"); String suffix = sc.nextLine(); File[] files = srcFolder.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return new File(dir, name).isFile() ? name.endsWith(suffix) : false; } }); // 4.遍历文件数组,将指定的子文件拷贝到目标文件夹中并修改名字 for (File srcFile : files) { // 要保证拷贝到目标文件夹的文件的名称不能一样 // 要在目标文件夹中创建一个目标文件对象 File destFile = new File(destFolder, getUUID() + suffix); copyFile(srcFile, destFile); } System.out.println("拷贝单级文件夹成功"); } /** * 拷贝标准文件 * * @param srcFile * 原文件对象 * @param destFile * 目标文件对象 */ private static void copyFile(File srcFile, File destFile) { try ( // 先读 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile)); // 后写 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));) { // 自定义容器用于保存每次读取的内容 byte[] buf = new byte[1024]; // 自定义变量用于保存每次读取的字节个数 int len; // 循环读写 while ((len = bis.read(buf)) != -1) { // 读多少就写多少 bos.write(buf, 0, len); } System.out.println("拷贝文件成功"); } catch (Exception e) { e.printStackTrace(); } } /** * 获取随机字符串,保证不重复 * * @return */ public static String getUUID() { return UUID.randomUUID().toString().replace("-", ""); } }
import java.io.File; public class CopyMultiFolder { public static void main(String[] args) { // 1.将原文件夹封装成成File对象 File srcFolder = new File("E:/aa"); // 2.将目标文件夹封装成File对象 File destFolder = new File("D:/"); // 3.调用拷贝多级文件夹的方法 copyMuiltFolder(srcFolder, destFolder); System.out.println("拷贝多级文件夹成功"); } /** * 拷贝多级文件夹 * * @param srcFolder * 原文件夹对象 * @param destFolder * 目标文件夹对象 */ private static void copyMuiltFolder(File srcFolder, File destFolder) { // 4.规律:如果当前文件对象是一个文件夹 if (srcFolder.isDirectory()) { // 那么就在目标文件夹中创建一个一模一样名字的文件夹 destFolder = new File(destFolder, srcFolder.getName()); destFolder.mkdirs(); // 将原有的文件夹底下所有子文件都拷贝到目标文件夹中 File[] files = srcFolder.listFiles(); // 遍历所有的子文件,然后进行拷贝 for (File f : files) { copyMuiltFolder(f, destFolder); } } else { // 5.出口:当前文件对象是一个标准文件时,就直接进行拷贝 // 在目标文件夹中创建一个一模一样名字的文件 File destFile = new File(destFolder, srcFolder.getName()); // 6.调用文件拷贝的方法 IOUtils.copyFile(srcFolder, destFile); } } }