Java IO 流 InputStream 和 OutputStream 与 File 类
Java IO 流 InputStream 和 OutputStream
字节流
1、读写字节流:InputStream 输入流(读)和 OutputStream 输出流(写)是抽象类,是所有字节输入流和输出流的父类。
1.1、FileInputStream 通过字节的方式读取文件,适合读取所有类型的文件(图像、视频、文本文件等)。Java也提供了FileReader专门读取文本文件。
FileInputStream的构造方法:
- FileInputStream(File file)------------从File对象的文件读入数据。
- FileInputStream(String name)-------------从指定文件读入数据,这里要写具体文件路径。
- public int available(); 返回可以从输入流中读取的字节数目。
- public void close(); 关闭输入流。
1.2、FileOutputStream 通过字节的方式写数据到文件中,适合所有类型的文件。
FileOutputStream的构造方法:
- FileOutputStream(File file)-------------向File对象的文件写入数据
- FileOutputStream(File file, boolean append);------向File对象的文件追加写入数据,当append的值为true时,向文件中写入的数据会追加到原数据的后面,否则会重写该文件的数据。默认为false。
- FileOutputStream(String path)-------------向指定文件写入数据
- FileOutputStream(String path, boolean append);--------向指定文件追加写入数据。
常用方法:
- public void write(int b); 向文件中写入一个字节大小的数据
- public void write(byte[] b); 将 b.length 个字节从指定 byte 数组写入此文件输出流中。
- public void write(byte[] b, int off, int len); 指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
- public void close(); 关闭输出流。
- public void flush(); 强制将缓冲区的数据写入到输出流中。
1.3、ByteArrayInputStream
字节数组输入流在内存中创建一个字节数组缓冲区,从内存中的字节数组中读取数据。
创建字节数组输入流对象有以下几种方式。
接收字节数组作为参数创建:
ByteArrayInputStream bArray = new ByteArrayInputStream(byte [] a);
ByteArrayInputStream bArray = new ByteArrayInputStream(byte []a,
int off,
int len)
1.4、ByteArrayOutputStream类
字节数组输出流在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组缓冲区中。创建字节数组输出流对象有以下几种方式。
// 下面的构造方法创建一个32字节(默认大小)的缓冲区。
OutputStream bOut = new ByteArrayOutputStream();
// 另一个构造方法创建一个大小为 a 字节的缓冲区。
OutputStream bOut = new ByteArrayOutputStream(int a)
1.5、BufferedInputStream
BufferedInputStream 继承于FilterInputStream,提供缓冲输入流功能。缓冲输入流相对于普通输入流的优势是,它提供了一个缓冲数组,每次调用read方法的时候,它首先尝试从缓冲区里读取数据,若读取失败(缓冲区无可读数据),则选择从物理数据源(譬如文件)读取新数据(这里会尝试尽可能读取多的字节)放入到缓冲区中,最后再将缓冲区中的内容部分或全部返回给用户.由于从缓冲区里读取数据远比直接从物理数据源(譬如文件)读取速度快。
//构造方法
BufferedInputStream(InputStream in)
// 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。创建一个长度为 size 的内部缓冲区数组并将其存储在 buf 中。
BufferedInputStream(InputStream in, int size)
//下一字节是否可读
synchronized int available()
//关闭
void close()
//标记, readlimit为mark后最多可读取的字节数
synchronized void mark(int readlimit)
//是否支持mark, true
boolean markSupported()
//读取一个字节
synchronized int read()
//读取多个字节到b
synchronized int read(byte[] b, int off, int len)
//重置会mark位置
synchronized void reset()
//跳过n个字节
synchronized long skip(long n)
使用:
public static void main(String[] args) throws Exception { // 指定要读取文件的缓冲输入字节流 BufferedInputStream in = new BufferedInputStream(new FileInputStream("F:\\test.jpg")); File file = new File("E:\\test.jpg"); if (file != null) { file.createNewFile(); } // 指定要写入文件的缓冲输出字节流 BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)); byte[] bb = new byte[1024];// 用来存储每次读取到的字节数组 int n;// 每次读取到的字节数组的长度 while ((n = in.read(bb)) != -1) { out.write(bb, 0, n);// 写入到输出流 } out.close();// 关闭流 in.close(); }
1.6、BufferedOutputStream
//创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 public BufferedOutputStream(OutputStream out); //创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。 public BufferedOutputStream(OutputStream out,int size);
//向输出流中输出一个字节 public void write(int b); //将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流。 public void write(byte[] b,int off,int len); //刷新此缓冲的输出流。这迫使所有缓冲的输出字节被写出到底层输出流中。 public void flush();
3: File类操作文件的常用方法:
3-1: 文件夹或文件的创建:
1 //获取File对象
2 File file = new File("E:\\file");
3 //创建单个文件夹
4 boolean mkdir = file.mkdir();
5 System.out.println(mkdir);
6 //创建多层级的文件夹的:
7 File file1 = new File("e:\\file\\demo1\\demo2\\demo3");
8 boolean mkdirs = file1.mkdirs();
9 System.out.println(mkdirs);
//创建文件:
boolean newFile = file.createNewFile();
删除文件或者文件夹:
2 File file = new File("test2.txt");
4 boolean delete = file.delete();
6 System.out.println(delete);
文件或文件夹的重命名:
File file = new File("OnlyFileTest/test.txt");
//路径相同为重命名,路径不同为剪切并重命名:
File file1 = new File("OnlyFileTest/Demo2.txt");
boolean demo2 = file.renameTo(file1);
System.out.println(demo2);
File类的判断功能:
File file = new File("OnlyFileTest/test.txt");
//判断是否是文件夹:
boolean directory = file.isDirectory();
//判断是否是文件:
boolean file2 = file.isFile();
//判断是否存在:
boolean exists = file.exists();
File类的获取功能:
File file = new File("OnlyFileTest/test.txt");
//获取文件的名字:
String name = file.getName();
//获取文件的绝对路径:
String absolutePath = file.getAbsolutePath();
//获取文件的相对路径:
String path = file.getPath();
//获取文件的长度,字节数;
long length = file.length();
//获取文件最后一次修改的毫秒值:
long l = file.lastModified();
高级获取功能:
File file = new File("OnlyFileTest/test.txt");
//获取指定目录下所有文件或者文件夹名称的数组:
String[] list = file.list();
//获取指定目录下所有文件或则文件夹的File数组:
File[] files = file.listFiles();
案例:输出指定目录下以 .jpg 结尾的所有文件:
方式一:
/* * 判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称 * * 分析: * A:封装e判断目录 * B:获取该目录下所有文件或者文件夹的File数组 * C:遍历该File数组,得到每一个File对象,然后判断 * D:是否是文件 * 是:继续判断是否以.jpg结尾 * 是:就输出该文件名称 * 否:不搭理它 * 否:不搭理它 */ public class FileDemo { public static void main(String[] args) { // 封装e判断目录 File file = new File("e:\\"); // 获取该目录下所有文件或者文件夹的File数组 File[] fileArray = file.listFiles(); // 遍历该File数组,得到每一个File对象,然后判断 for (File f : fileArray) { // 是否是文件 if (f.isFile()) { // 继续判断是否以.jpg结尾 if (f.getName().endsWith(".jpg")) { // 就输出该文件名称 System.out.println(f.getName()); } } } } }
方式二:
/* * 判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称 * A:先获取所有的,然后遍历的时候,依次判断,如果满足条件就输出。 * B:获取的时候就已经是满足条件的了,然后输出即可。 * * 要想实现这个效果,就必须学习一个接口:文件名称过滤器 * public String[] list(FilenameFilter filter) * public File[] listFiles(FilenameFilter filter) */ public class FileDemo2 { public static void main(String[] args) { // 封装e判断目录 File file = new File("e:\\"); // 获取该目录下所有文件或者文件夹的String数组 // public String[] list(FilenameFilter filter) String[] strArray = file.list(new FilenameFilter() { @Override public boolean accept(File dir, String name) { // return false; // return true; // 通过这个测试,我们就知道了,到底把这个文件或者文件夹的名称加不加到数组中,取决于这里的返回值是true还是false // 所以,这个的true或者false应该是我们通过某种判断得到的 // System.out.println(dir + "---" + name); // File file = new File(dir, name); // // System.out.println(file); // boolean flag = file.isFile(); // boolean flag2 = name.endsWith(".jpg"); // return flag && flag2; return new File(dir, name).isFile() && name.endsWith(".jpg"); } }); // 遍历 for (String s : strArray) { System.out.println(s); } } }
案例二:
递归遍历出所有以 .java 结尾的文件:
/* * 需求:请大家把E:\JavaSE目录下所有的java结尾的文件的绝对路径给输出在控制台。 * * 分析: * A:封装目录 * B:获取该目录下所有的文件或者文件夹的File数组 * C:遍历该File数组,得到每一个File对象 * D:判断该File对象是否是文件夹 * 是:回到B * 否:继续判断是否以.java结尾 * 是:就输出该文件的绝对路径 * 否:不搭理它 */ public class FilePathDemo { public static void main(String[] args) { // 封装目录 File srcFolder = new File("E:\\JavaSE"); // 递归功能实现 getAllJavaFilePaths(srcFolder); } private static void getAllJavaFilePaths(File srcFolder) { // 获取该目录下所有的文件或者文件夹的File数组 File[] fileArray = srcFolder.listFiles(); // 遍历该File数组,得到每一个File对象 for (File file : fileArray) { // 判断该File对象是否是文件夹 if (file.isDirectory()) { getAllJavaFilePaths(file); } else { // 继续判断是否以.java结尾 if (file.getName().endsWith(".java")) { // 就输出该文件的绝对路径 System.out.println(file.getAbsolutePath()); } } } } }