I:Input
O:Output
通过IO可以完成硬盘文件的读和写
1.IO流的分类
(1)按流的方向分类(以内存作为参照物)
往内存中去,叫输入(Input)或叫做读(Read);
从内存中出来,叫做输出(Output)或叫做写(Write)
(2)按照数据读取方式的不同进行分类
①有的流是按字节的方式读取数据,一次读取1个字节byte,等同于一次读取了8个二进制位,这种流是万能的,什么类型的文件都可以读取,包括:文本文件、图片、声音文件、视频文件等。
②有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取普通文本文件,连world文件都无法读取。
终上所述,IO流的分类有:输入流、输出流、字符流、字节流
2.Java中所有的流都在java.io.*
3.Java中IO流有4大类,分别是:
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
java.io.Reader 字符输入流
java.io.Writer 字符输出流
注意!在java中只要“类名”以Stream结尾的都是字节流,以“Reader/Writer”结尾的都是字符流
(1)所有的流都实现了:java.io.Closeable接口,都是可关闭的,都有close()方法
注意!流毕竟是一个管道,这是硬盘和内存之间的通道,用完之后需要关闭,不然会耗费很多资源,关闭流的前提是流不是空
(2)所有的输出流都实现了java.io.Flushable接口,都是可刷新的,都有flush()方法
注意!输出流在最终输出之后,一定要记得flush()刷新一下,这个刷新表示将通道/管道当中剩余未输出的数据强行输出完(清空管道),刷新的作用就是清空管道,如果没有flush()可能会导致丢失数据。
4.java.io包下需要掌握的流有16个
文件专属流:
- java.io.FileInputStream
- java.io.FileOutputStream
- java.io.FileReader
- java.io.FileWriter
转换流:(将字节流转换成字符流)
- java.io.InputStreamReader
- java.io.OuputStreamWriter
缓冲流:
- java.io.BufferedReader
- java.io.BufferedWriter
- java.io.BufferedInputStream
- java.io.BufferedOnputStream
数据流:
- java.io.DataInputStream
- java.io.DataOnputStream
对象流:
- java.io.ObjectInputStream
- java.io.ObjectOnputStream
标准输出流:
- java.io.PrintWriter
- java.io.PrintStream
1.文件字节输入流,万能的,任何类型的文件都可以采用这个流来读
2.字节的方式完成输入的 *** 作,完成读的 *** 作(硬盘----->内存)
在IDEA中默认的当前路径是Project的根
3.FileInputStream类的其他常用方法:
int available() //返回流当中剩余的没有读到的字节数量
long skip(long n) //跳过几个字节不读
1.使用FileInputStream+FileOutputStream完成文件的拷贝的过程应该是一边读一边写,使用以上的字节流拷贝文件时,文件类型随意,万能的。什么样的文件都能拷贝。
2.输入输出流的异常分开try,不要一起try,一起try的时候,其中一个出现异常可能会影响到另一个流的关闭
代码示例: package cn.itcast_01; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class 字节流复制文本文件案例 { public static void main(String[] args) throws IOException { //封装数据源 FileInputStream fis = new FileInputStream("a.txt"); //封目的地 FileOutputStream fos = new FileOutputStream("b.x.txt"); int by = 0; while((by = fis.read()) != -1) { fos.write(by); } //释放资源(先关谁都可以) fos.close(); fis.close(); } }BufferedReader
1.带有缓冲区的字符输入流,使用这个流时不需要自定义char数组,或者说不需要定义byte数组,自带缓冲。
2.当一个流的构造方法中需要一个流时,这个被传进来的流叫做节点流;负责外部包装的流叫做包装流。
例:
FileReader reader = new FileReader(“文件名”);
BufferedReader br = new BufferedReader(reader);
//像上述两个语句中,FileReader就是一个节点流,BufferedReader就是一个包装流/处理流
//对于包装流来说,只需要关闭最外层流即可,里面的节点流会自动关闭
BufferedWriter:带有缓冲的字节输出流
OutputStreamWriter:转换流
数据专属的流
这个流可以将数据连同数据的类型一起写入文件,但是要注意这个文件不是普通文本文档,使用记事本是打不开的
数据字节输入流
DataOutput写的文件只能使用DataInputStream去读,并且读的时候还需要提前知道写入的顺序,读的顺序和写的顺序一致才可以正常取出数据
标准的字节输出流,默认输出到控制台
1.标准输出流不需要手动close()关闭
2.可以改变标准输出流动的输出方向
代码示例: PrintStream printStream = new PrintStream(new FiledOutputStream("文件名"));//标准输出流不再指向控制台,指向“log”文件 System.out.println(printStream);//再输出 System.out.println("......");//再输出java.io.File
1.File类和IO的四大类没有关系,所以File类不能完成文件的读和写
2.File类文件代表文件和目录路径名的抽象表现形式,一个File对象有可能对应的是目录,也有可能对应的是文件。File只是一个路径名的抽象表现形式
3.File类中常用方法
(1)创建一个File对象
File f1 = new File(“文件路径”);
(2)判断是否存在
代码示例: System.out.println(f1.exit()); //如果文件不存在,则以文件的形式创建出来 if(!f1.exit()){ f1.createNewFile();//以文件形式新建 } //如果文件不存在,则以目录的形式创建出来 if(!f1.exit()){ f1.mkdir();//以目录形式新建 } //可以创建多重目录 File f2 = new File("D:/a/b/c/d/e/f"); if(!f2.exit()){ f2.mkdirs();//以多重目录的形式新建 }
(3)获取文件的父路径
代码示例: File f3 = new File("文件路径"); String parentPath = f3.getParent(); System.out.println("parentPath");//输出文件的父路径 File parentFile = f3.getParentFile(); System.out.println("获取绝对路径" + parentFile.getAbsoluPath());//获取文件的绝对路径
(4)获取文件名
File f1 = new File(“文件路径”);
System.out.println(“文件名:” + f1.getName());//获取文件名
(5)判断是否是一个目录
System.out.println(f1.isDirectory());
//判断是否是一个文件
System.out.println(f1.isFile());
(6)获取文件最后一次修改时间
long haoMiao = f1.lastModifies();//这个毫秒数是从1970年到现在的总毫秒数,将总毫秒数转换成日期 Date time = new Date(haoMiao); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); String strTime = sdf.format(time); System.out.println(strFime);
(7)获取文件大小
System.out.println(f1.length());
(8)ListFile方法
//获取当前目录下所有的子文件
File f = new File(“文件路径”);
File[] files = f.listFiles();
目录拷贝
import java.io.*; public class CopyCouse { public static void main(String[] args) { //可以继续降低耦合度 File f = new File("E:\Java笔记"); CopyOperation.CopyCouse(f,"D:\"); } //封装成内部类的形式也是极好的 static class CopyOperation{ public static void CopyCouse(File A, String B){ //这段代码使得 “路径仅为盘符” 的时候,去除路径末尾的斜杠 boolean flag = true; if(flag && B.endsWith("\")){ B.substring(0,B.length()-2); flag = false; } flag = false; //如果是文件 if(A.isFile()){ Copy(A,B + "\" + A.getName()); return; } //如果是目录 else{ File f = new File(B + "\" + A.getName()); if(!f.exists()){ f.mkdirs(); } File[] files = A.listFiles(); for(File file : files){ CopyCouse(file,B + "\" + A.getName()); } return; } } //封装 文件拷贝代码 public static void Copy(File A, String B){ FileOutputStream fos = null; FileInputStream fis = null; try { fis = new FileInputStream(A); fos = new FileOutputStream(B); byte[] bytes = new byte[1024 * 1024]; int readCound = 0; while((readCound = fis.read(bytes)) != -1){ fos.write(bytes,0,readCound); } fos.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } }序列化和反序列化
1.序列化:Serialize
java对象存储到文件中,将java对象的状态保存下来的过程
反序列化:Deserialize
将硬盘上的数据重新恢复到内存当中,恢复成java对象
2.序列化的实现(序列化之前要有java对象)
代码示例: ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("文件名")); //序列化对象 oos.writeObject(s); //刷新 oos.flush(); //关闭 oos.close();
注意!
参与序列化和反序列化的对象必须实现Serializable接口
3.通过源码发现,Serializable接口只是一个标志接口,该接口什么代码都没有,起到的作用:
起到标识的作用,标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇,Serializable这个标志接口是给java虚拟机参考的,java虚拟机看到这个接口之后,会为该类自动生成一个序列化版本号。
4.反序列化
代码示例: ObjectInputSream ois = new ObjectInputStream(new FileInputStream("文件名")); //开始反序列化读 Object obj = ois.readObject(); //反序列化回来是一个学生对象,所以想会调用学生对象的toString方法 System.out.println(obj); ois.close();
5.可以一次序列化多个对象,将对象放到集合当中序列化集合。
代码示例: ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("文件名")); oos.writeObjcet(userList); //序列化一个集合,这个集合对象中放了很多其他对象 oos.flush(); oos.close();
6.transient关键字表示游离的,不参与序列化
7.序列化版本号有什么用?
Java虚拟机看到Serializable接口之后会自动生成一个序列化版本号,便于Java虚拟机区分类,但是建议手动写出序列化版本号,给予一个固定值,这样即使代码修改了,但是序列化版本号不变,Java虚拟机会认为是同一个类。
8.IO+Properties联合使用
IO流:文字的读和写
Properties:是一个Map集合,key和value都是String类型,以后经常修改的数据可以单独写到一个数据文件中,使用程序动态读取,将来只需要修改这个文件的内容,java代码不需要改动不用重新编译。服务器也不需要重启就可以拿到动态的消息。类似于以上机制的这种文件被称为配置文件,并且当配置文件中的内容格式是:
key1 = value
key2 = value
时,我们把这种配置文件叫做属性配置文件。java规范中有要求:属性配置文件以“.properties”结尾。这种以.properties的文件在java中被称为:属性配置文件。Properties是专门存放属性配置文件内容的一个类。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)