博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java IO
阅读量:2420 次
发布时间:2019-05-10

本文共 6014 字,大约阅读时间需要 20 分钟。

目录

 

File类

windows路径可以用\或/,linux路径用/,为跨平台一律使用/。

File即可以指文件,也可以指目录(文件夹)。

File类常用的方法

String getName()    //获取文件|文件夹名,文件名包括后缀boolean exists()   boolean isFile()    boolean isDirectory()long length()  //文件|文件夹的大小,字节long lastModified()  //最后修改时间,时间戳String[] list()  //返回所有的子文件、子文件夹,String[]File[] listFiles()  //返回所有的子文件、子文件夹,File[]File file;// 以上2个方法均可带FilenameFilter类型的参数,对结果进行过滤,只返回符合条件的文件夹、文件// FilenameFilter是一个函数式接口,只需实现 accept(File dir, String filename) 方法String[] arr = file.list((dir, filename) -> {
//dir是file对应的文件夹,filename是其下的子文件夹名、子文件名 return filename.endsWith(".txt"); //返回true才保留此filename}); boolean createNewFile() //新建文件,如果前面的路径不存在,会自动创建boolean mkdir() //新建文件夹,如果前面的路径不存在,不做任何操作boolean mkdirs() //新建文件夹,如果前面的路径不存在,会自动创建boolean delete() //删除文件|文件夹

 

RandomAccessFile类

支持随机访问,可在文件中的任意位置读写数据,常用于实现断点传输、断点下载。

 

IO流

流的分类

按流的方向分

  • 输入流:从磁盘、网络等读取到内存,只能读,不能写
  • 输出流:从内存写出到磁盘、网络,只能写,不能读
     

按操作的数据单元分

  • 字节流:以字节为基本操作单位
  • 字符流:以字符为基本操作单位
     

按流的角色分

  • 节点流:向某个IO设备/节点(磁盘文件、网络等)直接读写数据,也称为低级流。
  • 处理流:用于包装一个已存在的流,通过这个已存在的流来进行读写操作,并不直接操作IO节点,也称为高级流、包装流。

处理流是一种典型的装饰器设计模式,使用处理流包装不同的节点流,可以消除不同节点流的差异,以同样的操作方式来操作。

 

常见的IO流

分类 字节输入流 字节输出流 字符输入流 字符输出流
抽象基类 InputStream OutputStream Reader Writer
操作文件 FileInputStream FileOutputStream FileReader FileWriter
操作数组 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter
操作字符串 StringReader StringWriter
缓冲流 BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter
转换流 InputStreamReader OutputStreamWriter
对象流(用于序列化) ObjectInputStream ObjectOutputStream
打印流(输出功能十分强大) PrintStream(也可直接操作字符) PrintWriter
音频输入、输出 AudioInputStream AudioOutputStream
加密、解密 CipherInputStream CipherOutputStream
压缩、解压 ZipInputStream ZipOutputStream

 

读文件 示例

FileInputStream fis=new FileInputStream("./1.txt");byte[] buff=new byte[1024];int length=0;while ((length=fis.read(buff))!=-1){
//已读完返回-1 System.out.println(new String(buff,0,length)); //读写文件使用数组时都应该使用length,不然最后一次数组读写时会读写到数组中空的部分}fis.close();
FileReader fr=new FileReader("./1.txt");char[] buff=new char[1024];int length=0;while ((length=fr.read(buff))!=-1){
System.out.println(new String(buff,0,length));}fr.close();

 

写文件 示例

//默认是覆盖FileOutputStream fos=new FileOutputStream("./2.txt");fos.write("hello\n".getBytes());fos.close();//可指定是否是追加模式,true——是追加模式,false——不是追加模式(即覆盖)fos=new FileOutputStream("./2.txt",true);fos.write("hello\n".getBytes());fos.close();
//默认是覆盖FileWriter fw=new FileWriter("./2.txt");fw.write("hello\n");fw.close();//追加fw=new FileWriter("./2.txt",true);fw.write("world!");fw.close();

文件可以分为文本文件、二进制文件,从底层来看,所有的文件都基于字节,都是二进制文件。

字节流可以操作所有的文件,字符流只能操作文本文件,字符流操作文本文件更简单,一般使用字符流操作文本文件,使用字节流操作二进制文件。

 

内置的流对象

  • System.in 标准输入流对象(键盘输入),是InputStream的对象
  • System.out 标准输出流对象(控制台),是OutputStream的对象

 

包装流之PrintStream

FileInputStream、FileWriter、FileOutputStream、FileWriter都是直接操作IO节点(文件),是节点流,包装流用来包装一个已存在的流,不直接操作IO节点,消除了节点流之间的差异,可以用同样的方式操作不同的节点流。

FileOutputStream fos=new FileOutputStream("./1.txt");//以一个已存在的流对象作为参数PrintStream ps=new PrintStream(fos);//可以字节为单位操作ps.write("你好!".getBytes());//可以字符为单位操作ps.print("很高兴认识你!");//println()输出后直接换行,不用我们在写\n,更加简便ps.println("xxxxxxxxxx");//可输出各种类型的数据ps.write(12);ps.print(12);ps.print(12.34);//关闭处理流时,会自动关闭其包装的节点流,代码更简洁。ps.close();

PrintStream使用简单、输出功能十分强大。

 

包装流之缓冲流

之前我们手动创建数组,用byte[ ]、char[ ]做缓冲区,提高读写效率。

java提供了缓冲流,效果相同,但自带缓冲区(数组),不用我们手动创建、操作数组,更加简便

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("./1.txt"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("./2.txt"));//文件复制int i;while ((i = bis.read()) != -1){
//i是读取的内容的码值 bos.write(i); //将读取的数据写到输出流,会自动将码值转换为相应的内容}//关闭包装流,会自动关闭对应的节点流bis.close();bos.close();

 

包装流之转换流

java提供了2个转化流,可以将字节流转换为字符流

// InputStreamReaderInputStreamReader  isr=new  InputStreamReader(InputStream is);// OutputStreamWriterOutputStreamWriter  isr=new  OutputStreamWriter(OutputStream os);

字符流本身操作就很方便,没有提供将字符流转换为字节流的类

 

对象的序列化、反序列化

序列化(Serialize):将内存中的对象转换为二进制数据(字节序列),通过输出流存储到文件中,或传输到网络节点上。

反序列化(Deserialize):将输入流中的二进制数据恢复为内存中的对象。

 

实现序列化的2种方式

  • 实现Serializable接口:只是表明该类是可序列化的,不用实现任何方法。jdk自带的类基本都已implement Serializable,我们只需关注自定义的类。
  • 实现Externalizable接口:用于实现自定义序列化。
     

序列化

String filePath = "/xxx/xxx.txt";User user1 = new User(1, "张三", 20);User user2 = new User(2, "李四", 20);User user3 = new User(3, "王五", 20);//获取输出流,参数是输出流OSObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));//输出到文件|网络节点。writeObject()一次只能写出一个对象oos.writeObject(user1);oos.writeObject(user2);oos.writeObject(user3);

 

反序列化

String filePath = "/xxx/xxx.txt";//获取输入流,参数是输入流ISObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));//返回的是Object,需要强转//readObject()只能读一个对象,读取一个对象后,指针自动后移,指向下一个对象,读的顺序和写的顺序一一对应User user1 = (User) ois.readObject();User user2 = (User) ois.readObject();User user3 = (User) ois.readObject();

 

注意点

public class Student extends User implements Serializable {
private Float score; //不想序列化的成员变量,比如密码等私密字段,使用transient修饰 private transient String password; //如果持有自定义类的引用,该类要是可序列化的,当前类才能序列化 private Teacher teacher; //.......}

如果当前类实现了序列化接口,且有父类,当前类要是可序列化的,还需要保证以下任意一点

  • 父类是可序列化的
  • 父类不可序列化,但父类提供了无参构造器

 

对象的拷贝

浅拷贝

  • 引用类型的成员只拷贝引用(地址),引用类型的字段和原对象的完全一致,都是指向同一个对象。
  • 优点是速度快,开销小,性能好。
  • Object自带的clone()方法就是浅拷贝,且是native方法,效率很高。

深拷贝

  • 引用类型的成员都是重新创建实例。
  • 速度慢,开销大,但更安全,可以避免共用成员对象导致的问题。
  • 需要自己实现,实现略麻烦。
     

深拷贝的常见实现方式

  • 对应引用型的成员,直接new创建新的实例;
  • 对于引用类型,再次调用Object的clone()方法进行拷贝;
  • 使用序列化、反序列化实现对象的拷贝。

第一、二种方式,如果存在引用类型的字段内部多级嵌套引用类型,则很麻烦,推荐使用第三种方式,简单。

 

使用序列化、反序列化实现深拷贝

@Overridepublic User clone() {
User user = null; try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(this); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); //强转为目标类型 user = (User) ois.readObject(); } catch (IOException | ClassNotFoundException e) {
System.out.println("深拷贝失败!"); e.printStackTrace(); } return user;}

序列化时,会拷贝对象到IO流中,这个拷贝是深拷贝,所以直接从IO流中读取对象即可。

转载地址:http://wwhlb.baihongyu.com/

你可能感兴趣的文章
【Python系列之】Python Django 框架初次体验-CSDN公开课-专题视频课程
查看>>
Hadoop 3.0 新特性原理及架构分析-CSDN公开课-专题视频课程
查看>>
3小时掌握数据挖掘-CSDN公开课-专题视频课程
查看>>
Web 全栈全端技术体系与软件四层结构-CSDN公开课-专题视频课程
查看>>
AI学习挑战直播课:成功案例分享及行业趋势分析-CSDN公开课-专题视频课程
查看>>
【UI/UE设计师】banner设计原则-CSDN公开课-专题视频课程
查看>>
大数据智能:金融行业用户画像实践教程-CSDN公开课-专题视频课程
查看>>
自然语言处理实战——LSTM情感分析-CSDN公开课-专题视频课程
查看>>
Gin使用的json包
查看>>
Gin的路由
查看>>
golang函数传参中可变参数和切片相互转化
查看>>
如何安全地退出goroutine
查看>>
context.Context
查看>>
优先队列
查看>>
redis深度历险学习笔记--基础与应用篇
查看>>
单链表翻转
查看>>
检查表达式中的括号是否匹配
查看>>
一道关于 goroutine 的面试题
查看>>
信号量的使用方法
查看>>
Redis 缓存穿透、击穿、雪崩
查看>>