1、IO(Input Output)流的概述
1、io的概念及其特点
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流.
宏观上io有以下特点。
· IO流用来处理设备之间的数据传输。
· Java对数据的操作是通过流(系统资源)的方式。
· Java用于操作流的对象都在java.io包中。
· 流按操作数据分为两种:字节流与字符流。
· 流按流向分为:输入流,输出流。
2、io的体系结构
2、IO中常用的类
1. File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。
2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
3.OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。
4.Reader(文件格式操作):抽象类,基于字符的输入操作。
5. Writer(文件格式操作):抽象类,基于字符的输出操作。
6. RandomAccessFile(随机文件操作):一个独立的类,直接继承至Object.它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。
3、File详解
1、File(文件特征与管理)
用来将文件或者文件夹封装成对象。
方便对文件与文件夹的属性信息进行操作。
File对象可以作为参数传递给流的构造函数。
2、File API
package com.xyq.file; import java.io.File; import java.io.FileFilter; import java.io.IOException; public class FileTest { public static void main(String[] args) throws IOException { // method_1(); // method_2(); // method_3(); // method_4(); // method_5(); // method_6(); // method_7(); File file = new File("E:\\test"); FilesFilter(file); } /* * file类的四个静态常量 * public static String separator 与系统有关的目录分隔符 Windows中 :\ * public static char separatorChar Linux中: / * public static String pathSeparator 与系统有关的路径分隔符 Windows中 ; 分号 * public static char pathSeparatorChar Linux中 : 冒号 */ public static void method_1(){ File file = new File("E:\\"); String s = file.separator; System.out.println(s); s = file.pathSeparator; System.out.println(s); } /* * file 类的构造方法 * 1. File(String pathName) * 2. File(String parent, String child) * 3. File(File parent, String child) */ public static void method_2(){ File file = new File("E:\\KeCheng"); File file2 = new File("E:\\","KeCheng"); File file3 = new File(file, ""); System.out.println(file); System.out.println(file2); System.out.println(file3); } /* File类的创建方法 ,目标文件或者路径存在时,均会返回false * 1. boolean createNewFile() 创建文件,成功返回true * 2. boolean mkdir() 创建文件夹,成功返回true,只能创建一级目录 * 3. boolean mkdirs() 创建多级文件夹 */ public static void method_3()throws IOException{ File file = new File("E:\\text.txt"); System.out.println(file.createNewFile()); File file2 = new File("E:\\test\\test\\test"); System.out.println(file2.mkdirs()); } /* File类的删除方法 * 1. boolean delete() 删除指定目录或者文件,成功返回true,注意此删除不走回收站,文件夹不为空时没有办法删除 * 2. void deleteOnExit() jvm退出前删除, */ public static void method_4()throws IOException{ File file = new File("E:\\test.txt"); System.out.println(file.createNewFile()); System.out.println(file.delete()); } /* File类的判断方法 * boolean exists() 判断构造方法中封装的路径或者文件是否存在 * boolean isAbsolute() 判断构造方法中封装的路径是不是绝对路径,是返回真 * boolean isDirectory() 判断是不是路径,是返回true * boolean isFile() 判断是不是文件,是返回true * boolean isHidden() 判断封装的路径(包括文件)是不是隐藏属性是返回true */ public static void method_5(){ File file = new File("E:\\abcde"); System.out.println(file.exists()); System.out.println(file.isAbsolute()); } /* * File类的获取方法 * 1.String getName() 获取封装路径最后部分的名字,此方法不会判断路径是否存在,使用之前最好判断 * 2.String getParent() 返回封装路径的父路径 * 3.File getParentFile() 返回封装路径的父路径的File对象 * 4.String getAbsolutePath() 返回封装路径的绝对路径 * 5.File getAbsoluteFile() 返回封装路径的绝对路径的File对象 */ public static void method_6(){ File file = new File("scr"); System.out.println(file.getAbsoluteFile().getParent()); } /* * File的list方法 * 1. static File[] listRoots() 静态的方法,列出系统所以的根,光驱和移动设备存储也会算进去 * 2. String[] list()返回File构造方法封装的路径下的所有文件和文件夹 * 3. File[] listFiles()返回File构造方法封装的路径下的所有文件和文件夹,返回的Filed对象,带全路径 */ public static void method_7(){ File []roots = File.listRoots(); for(File file:roots){ System.out.println(file); } } //递归过滤方法的实现,选出目录下的*.java文件 //直接使用匿名内部内实现了FileFilter接口 public static void FilesFilter(File file){ File []files = file.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { if (pathname.getName().endsWith(".java") || pathname.isDirectory()) { return true; } else { return false; } } }); if(files != null){ for(File file2:files){ if(file2.isFile()){ System.out.println(file2); }else { FilesFilter(file2); } } } } }
4、IO流常用基类
- 字节流的抽象基类:
- InputStream 读取一个文本文件中的数据
- OutputStream 向一个文本文件中写入数据
- 用输出流还是输入流 参考标准是内存
字符流的抽象基类:
- Reader
- Writer
比较常用的字节流
- FileInputStream
- FileOutputStream
- BufferedInputStream
- BufferedOutputStream
4.1字节输出流——FileOutputStream
注意 在创建字节输出流对象用于操作文件,在对象初始化时必须明确数据存储的目的地,输出流所关联的目的地,如果不存在,则会自动创建;如果存在,则会覆盖。
具体用法 例 向一个文本文件中写入数据
package com.xyq.outputstream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class FileOutputStreamTest { /* * 将数据写入到文件中。 * 使用字节输出流。FileOutputStream。 */ public static void main(String[] args) throws IOException{ //1、创建文件夹 File dir = new File("tempFile"); if(!dir.exists()){ dir.mkdir(); } //显示创建文件的路径 System.out.println(dir.getAbsoluteFile().getParent()); // 2、创建字节输出流对象,用于操作文件,在对象初始化时必须明确数据存储的目的地。 // 输出流所关联的目的地,如果不存在,会自动创建。如果存在,则覆盖。 FileOutputStream fos = new FileOutputStream("tempFile\\test.txt"); // 3、调用输出流的写功能。 fos.write("abcd".getBytes()); //4、释放资源 fos.close(); } }
4.2字节输入流——FileInputStream
具体用法 例 读取一个文本文件中的数据
4.2.1 read():一个一个字节的读
package com.xyq.outputstream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class FileInputStreamTest { public static void main(String[] args) throws IOException{ //1、为了确保文件一定在读之前是存在的,将字符串路径封装成File对象。 File file = new File("tempFile\\test.txt"); //2、判断文件是否存在 if(!file.exists()){ throw new RuntimeException("要读取的文件不存在"); } //3、创建文件字节读取流对象时,必须明确与之关联的数据源。 FileInputStream fis = new FileInputStream(file); //4、调用读方法 int by = 0; while ((by = fis.read()) != -1) { System.out.println(by); } //5、关闭资源 fis.close(); } }
4.2.2read(byte[] buf):先把字节存入到缓冲区字节数组中,一下读一个数组(常用)
package com.xyq.outputstream; import java.io.FileInputStream; import java.io.IOException; public class FileInputStreamTest2 { //1、定义缓冲区的大小可以是1024的整数倍 private static final int SIZE = 1024; public static void main(String[] args) { //2、创建文件字节读取流对象。 FileInputStream fis = null; try { fis = new FileInputStream("tempFile\\test.txt"); //3、创建一个字节数组。 byte [] buf = new byte[SIZE]; //4、调用读方法 int len = 0;// len记录的是往字节数组里存储的字节个数。 while((len = fis.read(buf)) != -1){ // 将字节数组转成字符串,打印并看一下效果。 System.out.println(new String(buf, 0, len)); } } catch (IOException e) { // 将异常信息写入到日志文件中以进行记录。 }finally { //5、关闭资源 if(fis != null){ try { fis.close(); } catch (IOException e) { // 一般可以throw RuntimeException异常,或者将异常信息写入到日志文件中以进行记录。 e.printStackTrace(); } } } } }
4.3缓冲流-BufferedInputStream、BufferedOutputStream
4.3.1有了InputStream和OutputStream为什么还要有BufferedInputStream和BufferedOutputStream?
因为不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多!
同时正因为它们实现了缓冲功能,所以要注意在使用BufferedOutputStream写完数据后,要调用flush()方法或close()方法,强行将缓冲区中的数据写出。否则可能无法写出数据。
4.3.2 BufferedInputStream和BufferedOutputStream的具体用法
例 图片的复制package com.xyq.outputstream; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class CopyPicBufferTest { //1、定义缓冲区的大小可以是1024的整数倍 private static final int SIZE = 1024; public static void main(String[] args) { File oldFile = new File("tempFile\\1.jpg"); File newFile = new File("tempFile\\abc.jpg"); copyFile(oldFile, newFile); } public static void copyFile(File oldFile, File newFile){ //2、创建流 FileInputStream fis = null; BufferedInputStream bis = null; FileOutputStream fos = null; BufferedOutputStream bos = null; try { fis = new FileInputStream(oldFile); bis = new BufferedInputStream(fis); fos = new FileOutputStream(newFile); bos = new BufferedOutputStream(fos); //3、进行读写操作 byte []byf = new byte[SIZE]; int len = 0;// len记录的是往字节数组里存储的字节个数。 //先读后写 while((len = bis.read(byf)) != -1){ bos.write(byf, 0, len); } bos.flush();//冲刷没有达到缓存限度的数据,确保数据全部写完 System.out.println("复制完成。。。"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //4、关闭资源 if(fis != null){ try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(bis != null){ try { bis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(fos != null){ try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(bos != null){ try { bos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }