一、IO流概要
1.概念
开发中经常要进行输入输出操作,掌握Java中的IO流显得非常必要。
流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。
一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。
流的方向是重要的,根据流的方向,流可分为两类:输入流和输出流。用户可以从输入流中读取信息,但不能写它。相反,对输出流,只能往输入流写,而不能读它。
实际上,流的源端和目的端可简单地看成是字节的生产者和消费者,对输入流,可不必关心它的源端是什么,只要简单地从流中读数据,而对输出流,也可不知道它的目的端,只是简单地往流中写数据。
形象的比喻——水流 ,文件======程序,文件和程序之间连接一个管道,水流就在之间形成了,自然也就出现了方向:可以流进,也可以流出。便于理解,这么定义流: 流就是一个管道里面有流水,这个管道连接了文件和程序。
Java流操作有关的类或接口:
Java IO流的结构图:
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
2.IO流的分类
根据处理数据类型的不同分为:字符流和字节流
根据数据流向不同分为:输入流和输出流
字符流和字节流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:
读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。
输入流和输出流
对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。
二、File类
1.简介
File类是io包中唯一代表磁盘文件本身的对象。File类定义了一些与平台无关的方法来操作文件,可以通过调用File类中的方法,实现创建、删除、重命名文件等。File类的对象主要用来获取文件本身的一些信息,如文件所在目录、文件的长度、文件读写权限等。数据流可以将数据写入到文件中,而文件也是数据流最常用的数据媒体。
提供定位本地文件系统、描述文件和目录的功能
是 java.io 包中引用实际磁盘文件的唯一对象
File类对象描述文件路径、名字、长度、可否读写等属性,可用来命名文件、查询文件属性和处理目录,但不读写文件。
解决程序与文件系统的沟通
各种文件系统提供的基本服务一样,但实现细节互不兼容
构造函数
File(String pathname);
File(String dir, String subpath);
File(File dir, String subpath);
File(String path)
文件(相对路径),移植性较好: File f1 = new File(“mydir\\myfile.txt”);
目录(绝对路径): File f2 = new File(“d:\\mydir\\dir1”);
File(String parent, String child )
文件路径以及文件名: File f3 = new File(“d:\\d1” , “a.java”)
File(File dir, String name)
文件对象与文件名:File f4 = new File(f2 , “myfile.txt”);
常用方法
canRead()、canWrite()、delete()、equals(object)、exists() getAbsolutePath() 和 length()
方法 | 描述 |
String getName() | 获取文件的名称 |
boolean canRead() | 判断文件是否是可读的 |
boolean canWrite() | 品判断文件是否可被写入 |
boolean exits() | 判断文件长度是否存在 |
int length() | 获取文件的长度(以字节为单位) |
String getAbsolutePath() | 获取文件的绝对路径 |
String getParent() | 获取文件的父路径 |
boolean isFile() | 判断此抽象路径名表示的文件是否为普通文件 |
boolean isDirectory() | 判断此抽象路径名表示的是否是一个目录 |
boolean isHidden | 判断文件是否是隐藏文件 |
long lastModified() | 获取文件最后修改时间 |
Boolean canExecute() |
测试应用程序是否可以执行此抽象路径名表示的文件。
|
boolean createNewFile() | 当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。 |
boolean delete() | 删除由此抽象路径名表示的文件或目录。 |
File[] listFiles() | 返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件。 |
String[] list() | 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。 |
boolean mkdirs() | 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。可创建多层文件包 |
boolean mkdir() | 创建由此抽象路径名命名的目录。只能创建一层文件包 |
boolean reNameTo(File dest) | 重命名由此抽象路径名表示的文件。 |
boolean setReadOnly() |
标记由此抽象路径名命名的文件或目录,以便只允许读取操作。
|
boolean setWritable(boolean writable) |
一种方便的方法来设置所有者对此抽象路径名的写入权限。
|
2.文件操作示例
创建与删除文件
public static void main(String[] args) throws IOException { File file = new File("e:"+File.separator,"file1.txt"); if(file.exists()) { file.delete(); System.out.println("删除成功"); }else { file.createNewFile(); System.out.println("创建成功"); } }
基本操作:
public static void main(String[] args) throws IOException { File file = new File("E:\\IOTestDemo.txt"); System.out.println("创建成功了吗?"+file.createNewFile()); System.out.println("单级文件夹创建成功了吗?"+file.mkdir()); System.out.println("多级文件夹创建成功了吗?"+file.mkdirs()); File dest = new File("F:\\电影\\c.txt"); System.out.println("重命名成功了吗?"+file.renameTo(dest)); System.out.println("********************"); System.out.println("文件或者文件夹存在吗?"+file.exists()); System.out.println("是一个文件吗?"+file.isFile()); System.out.println("是一个文件夹吗?"+file.isDirectory()); System.out.println("是隐藏文件吗?"+file.isHidden()); System.out.println("此路径是绝对路径名?"+file.isAbsolute()); System.out.println("********************"); System.out.println("文件或者文件夹的名称是:"+file.getName()); System.out.println("相对路径是:"+file.getPath()); System.out.println("绝对路径是是:"+file.getAbsolutePath()); System.out.println("文件大小是(以字节为单位):"+file.length()); System.out.println("文件父路径是:"+file.getParent()); //使用日期类与日期格式化类进行获取规定的时间 long lastModified = file.lastModified(); Date date = new Date(lastModified); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YY年MM月DD日 HH:mm:ss"); System.out.println("最后一次修改的时间是:"+simpleDateFormat.format(date)); System.out.println("***********************"); //文件或者文件夹的方法 File[] files = File.listRoots(); System.out.println("所有的盘符是:"); for (File item : files) { System.out.println("\t"+item); } File file2 = new File("F:\\mongoDB"); String[] list = file2.list(); System.out.println("指定文件夹下的文件或者文件夹有:"); for (String item : list) { System.out.println("\t"+item); } File[] f = file2.listFiles(); System.out.println("获得该路径下的文件或文件夹是:"); for(File item : f){ System.out.println("\t"+item.getName()); } } 打印输出: 创建成功了吗?false 单级文件夹创建成功了吗?false 多级文件夹创建成功了吗?false 重命名成功了吗?false ******************** 文件或者文件夹存在吗?true 是一个文件吗?true 是一个文件夹吗?false 是隐藏文件吗?false 此路径是绝对路径名?true ******************** 文件或者文件夹的名称是:IOTestDemo.txt 相对路径是:E:\IOTestDemo.txt 绝对路径是是:E:\IOTestDemo.txt 文件大小是(以字节为单位):0 文件父路径是:E:\ 最后一次修改的时间是:21年01月07日 14:51:43 *********************** 所有的盘符是: C:\ E:\ F:\ 指定文件夹下的文件或者文件夹有: data log mongodb.config 获得该路径下的文件或文件夹是: data log mongodb.config
递归获得所有文件与文件夹:
public static void main(String[] args) { File file = new File("E:\\360安全浏览器下载"); ListFile(file); } public static void ListFile(File f) { if(f.isDirectory()) { //获取当前文件夹下的所有的文件 File[] listFiles = f.listFiles(); System.out.println(f.getPath()+"下的文件是:"); for (File file : listFiles) { System.out.println("\t"+file.getName()); ListFile(file); } } } 打印输出: E:\360安全浏览器下载下的文件是: 200_m光纤氘气处理工艺的优化_刘晓玮.caj CAJViewer_7.2.113.0.exe CN107445470A.caj CN108793724A.caj CN108873156A.caj defrag.dat G.657光纤的弯曲损耗性能及机械可靠性1.pdf G652_D光纤在长波段的传输损耗研究_秦钰.caj G652光纤喇曼增益谱的实验研究.pdf pdf转word---点右边的(下载19.1M).zip SFF-03-J-生产科-814 NEXTROM筛选作业标准.doc
三、字节流操作
字节流和字符流的区别:
- 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
- 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。
1.字节输出流
输出字节流OutputStream
IO 中输出字节流的继承图可见上图,可以看出:
OutputStream 是所有的输出字节流的父类,它是一个抽象类。
ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
字节输出流的常用方法:
示例1:
public static void main(String[] args) throws IOException { File file = new File("E:\\streamTest.txt");//声明file对象 OutputStream out = null;//声明输出流的对象 out = new FileOutputStream(file);//实例化 String str = "hello world,my friends "; byte[] bytes = str.getBytes();//字符串转换成字节数组 out.write(bytes);//执行写操作 out.close();//关闭流对象 //创建html文件示例 File file2 = new File("E:\\streamTest.html");//声明file对象 OutputStream out2 = null;//声明输出流的对象 out2 = new FileOutputStream(file2);//实例化 String str2 = "<marquee><h1>Hello OutputStream!</h1></marquee>"; out2.write(str2.getBytes()); out2.close(); }
结果:
2.字节输入流
InputStream 是所有的输入字节流的父类,它是一个抽象类。
ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。
ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。
字节输入流的常用方法:
示例:
public static void main(String[] args) throws IOException { File file = new File("E:\\\\streamTest.txt"); InputStream in = null; in = new FileInputStream(file); //声明一个byte数组,将FileInputStream的流放入其中,类似于缓存作用 //byte数组可以自己指定大小,也可以根据文件大小指定,byte[1024] byte[] b = new byte[(int)file.length()]; in.read(b);//执行读的方法,将数据读到内存中 in.close();//关闭流 System.out.println("类容为:"+new String(b));//将byte数组转换成字符串输出 } 打印输出: 类容为:hello world,my friends hello world,my friends hello world,my friends hello world,my friends hello world,my friends hello world,my friends hello world,my friends hello world,my friends
四、字符流操作
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。
程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。
1、字符输出流
在Java中IO操作也是有相应步骤的,以文件操作为例,主要的操作流程如下:
1 使用File类打开一个文件
2 通过字节流或字符流的子类,指定输出的位置
3 进行读/写操作
4 关闭输入/输出
IO操作属于资源操作,一定要记得关闭
输出流: OutputStream 写出 就是将数据从程序写入到外部文件。
对应 Writer;
public static void main(String[] args) throws IOException { File file = new File("E:\\StringTest.txt"); Writer writer = null; writer = new FileWriter(file); String str = "hello world"; writer.write(str); writer.flush(); writer.close(); }
2、字符流输入
输入流:InputStream 读入 就是从外部文件中读取数据到程序。
对应 Reader;
public static void main(String[] args) throws IOException { File file = new File("E:\\StringTest.txt"); Reader reader = null; reader = new FileReader(file); char[] c = new char[(int)file.length()]; reader.read(c); System.out.println("内容为:"+new String(c)); }