Java学习笔记-IO
IO
IO流概述
可以将数据传输操作,看作一种数据的流动,按照流动的方向分为输入(Input)和输出(Output) java中的IO操作主要指的是java.io包下的一些常用类的使用,通过这些常用类对数据进行读取(输入Input)和写出(输出Output)
IO流的分类
按照流的方向来分,可以分为:输入流和输出流 按照流动的数据类型来分,可以分为:字节流和字符流 计算机中的任何数据(文本、图片、视频、音乐等等)都是以二进制的形式存储的 在数据传输时也都是以二进制的形式存储的 后续的任何流,在传输时底层都是二进制 流在写完以后一定要关闭
字节流:一切皆字节
输入流:InputStream
常用方法:int read (byte[] b): 从输入流中读取一些字节数并将它们存储到缓冲区数组 b 。 int read (byte[] b, int off, int len): 从输入流 len最多 len字节的数据读入一个字节数组。 abstract int read():从输入流中读取下一个数据字节。 byte[] readAllBytes(): 从输入流中读取所有剩余字节。 int readNBytes (byte[] b, int off, int len): 从输入流中读取请求的字节数到给定的字节数组中。 byte[] readNBytes (int len): 从输入流中读取指定的字节数。 void mark (int readlimit) 标记此输入流中的当前位置。 void reset(): 将此流重新定位到上次在此输入流上调用 mark方法时的位置。 long transferTo (OutputStream out) 从该输入流中读取所有字节,并按读取顺序将字节写入给定的输出流。 void close(): 关闭此输入流并释放与该流关联的所有系统资源。
常用子类:FileInputStream(实体类)文件输入流
构造方法:FileInputStream(File file): 通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的 File对象 file命名。 FileInputStream (String name): 通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的路径名 name命名。 常用方法:int available(): 返回可以从此输入流中读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。 void close(): 关闭此文件输入流并释放与该流关联的所有系统资源。 FileChannel getChannel(): 返回与此文件输入流关联的唯一FileChannel对象。 FileDescriptor getFD(): 返回 FileDescriptor对象,该对象表示与此 FileInputStream正在使用的文件系统中的实际文件的连接。 int read(): 从此输入流中读取一个字节的数据。 int read (byte[] b): 从此输入流 b.length最多 b.length字节的数据读 b.length字节数组。 int read (byte[] b, int off, int len): 从此输入流 len最多 len字节的数据读入一个字节数组。 long skip (long n): 跳过并从输入流中丢弃 n字节的数据。 注意:通过while (inputStream.read() != -1)这种方式来循环输出文件内容是不可行的,隔一个输出一个 通过一组字节数组来获取文件内容,文件内容是进行覆盖操作,abcdefg,用一个长度为三的字节数组输出,输出结果为 abc def gef 最后一个是因为只有一个元素g了,覆盖了上一数组 def 就变成了 gef解决方案:byte[] bytes = new byte[3];int len = fis.read(bytes);sout(new String(bytes,0,len));使用重复输出时,数据读完后len == -1常用一组获得的方法
输出流:OutputStream(抽象类)
常用方法:void close():关闭此输出流并释放与此流关系的所有系统资源void flush():刷新此输出流并强制写出任何缓冲的输出字节static OutputStream nullOutputStream():返回一个新的OutputStream,它丢弃所有字节void write(byte[] b):将b.length字节从指定的字节数组写入此输出流void write(byte[] b,int off ,int len):将从偏移量off开始的指定字节数组汇总的len字节写入此输出流abstract void write(int b):将指定的字节写入此输出流
常用子类:FileOutputStream(实体类)文件输出流
构造方法:FileOutputStream (File file): 创建文件输出流以写入由指定的 File对象表示的文件。 FileOutputStream (File file, boolean append): 创建文件输出流以写入由指定的 File对象表示的文件。 FileOutputStream (String name): 创建文件输出流以写入具有指定名称的文件。 FileOutputStream (String name, boolean append): 创建文件输出流以写入具有指定名称的文件。 append参数表示是否是续写 新建对象时参数写的是true\false常用方法:void close():关闭此文件输出流并释放与此流关联的所有系统资源。 void write (byte[] b):将指定字节数组中的 b.length字节写入此文件输出流。 void write (byte[] b, int off, int len):将从偏移量 off开始的指定字节数组中的 len字节写入此文件输出流。 off是开始的下标。len是写出的长度void write (int b):将指定的字节写入此文件输出流。注意:流的所有操作都要在关闭(close())之前执行,在关闭后执行会报异常,而且关闭要尽可能早的关闭使用字节流输出一串字符串时,要先将字符串转换成byte,xx.getBytes();
字符流:
以字符为单位,解决了字节流字符乱码的问题
输入流:Reader
构造方法:protected Reader(): 创建一个新的字符流阅读器,其关键部分将在阅读器本身上同步。 protected Reader (Object lock): 创建一个新的字符流阅读器,其关键部分将在给定对象上同步。 常用方法:abstract void close(): 关闭流并释放与其关联的所有系统资源。 void mark (int readAheadLimit): 标记流中的当前位置。 boolean markSupported(): 判断此流是否支持mark()操作。 static Reader nullReader(): 返回不读取任何字符的新 Reader 。 int read(): 读一个字符。 int read (char[] cbuf): 将字符读入数组。 abstract int read (char[] cbuf, int off, int len): 将字符读入数组的一部分。 int read (CharBuffer target): 尝试将字符读入指定的字符缓冲区。 boolean ready(): 判断此流是否可以读取。 void reset(): 重置流。 long skip (long n): 跳过字符。 long transferTo (Writer out): 读取此阅读器中的所有字符,并按照读取的顺序将字符写入给定的编写器。
输出流:Writer
构造方法:protected Writer(): 创建一个新的字符流编写器,其关键部分将在编写器本身上同步。 protected Writer (Object lock): 创建一个新的字符流编写器,其关键部分将在给定对象上同步。 常用方法:Writer append (char c): 将指定的字符追加到此writer。 Writer append (CharSequence csq): 将指定的字符序列追加到此writer。 Writer append (CharSequence csq, int start, int end): 将指定字符序列的子序列追加到此writer。 abstract void close(): 关闭流,先冲洗它。 abstract void flush(): 刷新流。 static Writer nullWriter(): 返回一个新的 Writer ,它丢弃所有字符。 void write (char[] cbuf): 写一个字符数组。 abstract void write (char[] cbuf, int off, int len): 写一个字符数组的一部分。 void write (int c): 写一个字符。 void write (String str): 写一个字符串。 void write (String str, int off, int len): 写一个字符串的一部分。 append()方法返回的是调用append()方法的对象,所以append()方法可以套娃,xx.append().append()....;
转换流
将字节流 转换(装饰)为 字符流:使用了装饰者设计模式
InputStreamReader
构造方法:InputStreamReader(InputStream(要转换的字节输入流))
OutputStreamWriter
构造方法:OutputStreamWriter(OutputStream(要转换的字节输出流))
###
Print与BufferedReader
一种更好的字节流转换成字符流的方法
PrintStream:字节流 PrintWriter:字符流 记得最后要刷新流(flush) 或者 关闭(close) 操作方法:new PrintStream("地址")new PrintWriter("地址")FileOutputStream fos = new FileOutputStream("地址")new PrintStream(fos)FileWriter fw = new FileWriter("地址")new PrintWriter(fw)
BufferReader
缓存读取流,将字符输入流,转换为带有缓存 可以一次读取一行的缓存字符读取流 操作方法:FileReader fr = new FileReader("地址")new BufferReader(fr);
收集异常日志
try{String s =null;s.toString(); }catch(Exception e){e.printStackTrace(); }try{String s =null;s.toString(); }catch(Exception e){PrintWriter pw = new PrintWriter("地址");SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")pw.println(sdf);e.printStackTrace(pw);pw.close(); }
Properties
是使用键值对方式进行存储的 构造方法:Properties(): 创建一个没有默认值的空属性列表。常用方法:String getProperty (String key): 在此属性列表中搜索具有指定键的属性。 String getProperty (String key, String defaultValue): 在此属性列表中搜索具有指定键的属性。 void list (PrintStream out): 将此属性列表打印到指定的输出流。 void list (PrintWriter out): 将此属性列表打印到指定的输出流。 void load (InputStream inStream): 从输入字节流中读取属性列表(键和元素对)。 void load (Reader reader): 以简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 void loadFromXML (InputStream in): 将指定输入流上的XML文档表示的所有属性加载到此属性表中。 Object setProperty (String key, String value): 调用 Hashtable方法 put 。void store (OutputStream out, String comments): 将此 Properties表中的此属性列表(键和元素对)以适合使用 load(InputStream)方法加载到 Properties表的格式写入输出流。 void store (Writer writer, String comments): 将此 Properties表中的此属性列表(键和元素对)以适合使用 load(Reader)方法的格式写入输出字符流。 void storeToXML (OutputStream os, String comment): 发出表示此表中包含的所有属性的XML文档。 void storeToXML (OutputStream os, String comment, String encoding): 使用指定的编码发出表示此表中包含的所有属性的XML文档。 void storeToXML (OutputStream os, String comment, Charset charset): 使用指定的编码发出表示此表中包含的所有属性的XML文档。 comment:输出到文件时的备注Set<String> stringPropertyNames(): 从此属性列表返回一组不可修改的键,其中键及其对应的值是字符串,如果尚未从主属性列表中找到相同名称的键,则包括默认属性列表中的不同键。
序列化与反序列化
能用,但不建议用,因为java官方说近几个版本会删除 使用序列化时,类和属性都必须实现序列化接口 存进去的一个ArrayList取出来也得是要个集合,不能
对象的序列化和反序列化实现
public class Student implements Serializable {private String stuNum;private String stuName;private List<String> teacherList; }定义序列化和反序列化工具类 public class MySerializeUtil {//序列化public static void mySerialize(Object obj , String fileName) throws IOException {FileOutputStream ops = new FileOutputStream(fileName);ObjectOutputStream oos = new ObjectOutputStream(ops);oos.writeObject(obj);oos.close();}//反序列化public static Object myDeserialize (String fileName) throws IOException, ClassNotFoundException {FileInputStream fis = new FileInputStream(fileName);ObjectInputStream ois = new ObjectInputStream(fis);Object object = ois.readObject();return object;}}main方法测试 public static void main( String[] args ) throws IOException {ArrayList<String> teacher = new ArrayList<>();teacher.add("bdyjy");teacher.add("ssyy");Student student = new Student("20181271","szh",teacher);System.out.println("原始对象:" + student);String fileName = "stu.txt";try {MySerializeUtil.mySerialize(student,fileName);System.out.println("对象序列化完成");Object obj = MySerializeUtil.myDeserialize(fileName);System.out.println("对象反序列化完成");if (obj instanceof Student){Student NewStu = (Student) obj;System.out.println("反序列化后的对象:" + NewStu);}} catch (ClassNotFoundException e) {e.printStackTrace();}}执行结果:原始对象:Student{stuNum='20181271', stuName='szh', teacherList=[bdyjy, ssyy]}对象序列化完成对象反序列化完成反序列化后的对象:Student{stuNum='20181271', stuName='szh', teacherList=[bdyjy, ssyy]}同时 stu.txt 文件里面也有内容写入
部分属性的序列化
1.使用transient修饰符 : 使用该修饰符修饰的属性将不会被序列化 2.使用static修饰符 :static修饰符修饰的属性也不会参与序列化和反序列化。修改实体类,将实体类中不想序列化的属性添加static修饰词。 3.默认方法writeObject和readObject。private void writeObject(ObjectOutputStream objOut) throws IOException {System.out.println("writeObject-----------");objOut.writeObject(stuNum); objOut.writeObject(stuName); }private void readObject(ObjectInputStream objIn)throws IOException,ClassNotFoundException { System.out.println("readObject-----------"); stuNum= (String) objIn.readObject(); stuName= (String) objIn.readObject(); }我们在添加的方法中只对stuNum和stuName属性做了序列化和反序列化的操作,因此只有这个两个属性可以被序列化和反序列化。注意:添加的两个方法必须是private void,否则不生效。
Externalizable实现Java序列化
刚刚我们说实现部分属性序列化的方式有多种,最后一种来啦!就是通过实现Eexternalizable接口。 Externalizable继承自Serializable,使用Externalizable接口需要实现readExternal方法和 writeExternal方法来实现序列化和反序列化。需要实现序列化和反序列化的类实现Externalizable接口,并重写里面的两个方法 @Override public void writeExternal(ObjectOutput out) throws IOException {out.writeObject(stuNum);out.writeObject(stuName);//out.writeObject(teacherList);} @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { stuNum= (String) in.readObject();stuName= (String) in.readObject();//teacherList= (List<String>) in.readObject();}Externalizable接口继承了Serializable接口,所以实现Externalizable接口也能实现序列化和反序列化。 Externalizable接口中定义了writeExternal和readExternal两个抽象方法,这两个方法其实对应 Serializable接口的writeObject和readObject方法。可以这样理解:Externalizable接口被设计出来的 目的就是为了抽象出writeObject和readObject这两个方法,但是目前这个接口使用的并不多。
序列化
Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复成Java对象的过程。通过序列化和反序列化实现网络传输、本地存储的目的。
Serializable实现Java序列化
要实现Java对象的序列化,只要将类实现标识接口--Serializable接口即可,不需要我们重写任何方法就可以实现序列化
Serializable VS Externalizable
区别 | Serializable | Externalizable |
---|---|---|
实现复杂度 | 实现简单,Java对其有内建支持 | 实现复杂,由开发人员自己完成 |
执行效率 | 所有对象由Java统一保存,性能较低 | 开发人员决定哪个对象保存,可能造成速度提升 |
保存信息 | 保存时占用空间大 | 部分存储,可能造成空间减少 |
使用频率 | 高 | 偏低 |
try-with-resources
JDK1.7之前 : 太麻烦,为了获取一个字符,写了一大段代码 FileReader fr = null; try{fr = new FileReader("地址");int c = fr.read();sout((char)c); }catch(IOExceprion e){e.printStackTrace(); }finally{try{fr.close();}catch(IOException e){e.printStackTrace();} }JDK1.7时 : 耦合性太强,假如fr在前面就已经被定义,或者在后面还需调用的话,无法使用此方法 try(FileReader fr = new FileReader("地址")){int c = fr.read();sout((char)c); }catch(IOException e){e.printStackTrace(); }JDK9进行优化 可自动关闭流。也不妨碍前后调用。需要关闭多个流,各个流之间用;隔开 FileReader fr = new FileREader("地址"); FileWriter fw = new FileWriter("地址"); try(fr;fw){int c = fr.read();sout((char)c); }catch(IOException e){e.printStackTrace(); }
Java学习笔记-IO相关推荐
- JAVA学习笔记—IO流
I/O 框架 流的概念 内存与存储设备之间传输数据的通道 水(相当于数据)-> 传输水的管道(相当于流)-> 脸盆(相当于内存) 生活用水 -> 流入 家庭废水 -> 流出 流 ...
- 【java学习笔记-io流 文件读写和键盘读写】带缓存的输入/输出流和数据输入/输出流
文章目录 字节流类 带缓存的输入/输出流 BufferedReader与BufferedWriter类 下面的例子程序演示了read()方法,从控制台读取字符直到用户键入"q": ...
- Java学习笔记---IO操作
一.文件的创建 ------------------------------------------------------- File类,表示磁盘上的文件或目录,可对文件或目录进行操作. * ...
- java学习笔记IO之字节输入输出流
IO字节输入输出流 OutputStream:字节输出流 该抽象类是所有字节输出流的超类: 定义了一些共性的成员方法: 1.写入一个字节 void write(int b);//b表示字节 2.写入字 ...
- 小陈java学习笔记IO
文件拷贝 重点: 1.文件在读取的时候,就写到输出流的对象里,达到一边读一边写的效果 2.使用write()的时候,一定要规范使用方法,否则可能会输出无效 节点流和处理流 1.节点流可以从一个特定的数 ...
- Java学习笔记(7)——Java基础之IO多线程网络思维导图
Java面向对象学习笔记之:包括IO(字节流,字符流,节点流,处理流).线程(线程创建,线程控制,线程同步).网络(TCP Scoket, UDP Scoket)(全屏观看Java学习笔记(7)-- ...
- Java学习笔记(十)--控制台输入输出
输入输出 一.控制台输入 在程序运行中要获取用户的输入数据来控制程序,我们要使用到 java.util 包中的 Scanner 类.当然 Java 中还可以使用其他的输入方式,但这里主要讲解 Scan ...
- java学习笔记16--I/O流和文件
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note16.html,转载请注明源地址. IO(Input Output)流 IO流用来处理 ...
- java学习笔记8--接口总结
接着前面的学习: java学习笔记7--抽象类与抽象方法 java学习笔记6--类的继承.Object类 java学习笔记5--类的方法 java学习笔记4--对象的初始化与回收 java学习笔记3- ...
最新文章
- 什么时候需要在外壳变量周围花括号?
- Hibernate(一)__简介
- [云炬python3玩转机器学习] 5-9 scikit-learn中的回归问题
- php导出csv数据在浏览器中输出提供下载或保存到文件的示例
- tomcat配置多站点
- 零宽断言 python_正则表达式-零宽断言
- Elasticsearch性能监控(二)
- python爬虫结果是字节_入门爬虫?一文搞定!
- linux 切换pip路径_【Python基础】PIP 镜像源配置轻松搞定
- k8s-controller manager原理分析
- vmware windows linux udp通信,windows 下 udp socket
- Win10验证USB Audio MIC(三)
- python中while true的用法_python入门:while循环里面True和False的作用,真和假
- 【OFDM通信】基于块状导频的信道估计算法仿真含Matlab源码
- JVM-垃圾回收机制
- java继承和接口的区别_java中的接口与继承的区别
- 那些活在浪里的创业者最终被拍成了电影
- C++ delete指针需置空
- 阿里云服务器租用费用
- 阿里云的esc服务器介绍
热门文章
- 【计算机科学基础】元宇宙的最新技术、应用和挑战
- 《科研伦理与学术规范》 期末考试,题目文档汇总(免费分享 )
- 数据管理能力成熟度模型(DMM)
- 19 Three.js实现雾化效果
- 51单片机实现简易闹钟(包含闹钟功能)
- excel学习-数据透视图(插入+设置样式+加公司logo+设置logo大小+删除表中多余东西)
- JSP 和 JavaBean 来实现一个简易计算器
- 乔治亚大学招收计算机视觉/深度学习/机器人/自动驾驶博士生from 2023 spring
- Facebook加密项目Libra浮出水面,Visa和万事达卡「入伙」
- Python数据可视化 Pyecharts 制作 PictorialBar 象形柱状图