本篇文章小编给大家分享一下Java中IO流代码实例解析,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
I/O简介
I/O是Input/output的缩写,在java中,对于数据的输入和输出以流的方式进行。java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。
输入输出都是基于内存的角度来说的。输入:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。 输出:输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中。
流的分类
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:节点流,处理流
节点流:直接从数据源或目的地读写数据。
处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。 相当于是二次包装。
Java的IO流共涉及40多个类,实际上非常规则,都是从这4个抽象基类派生的。由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。
字节流和字符流常用API
InputStream
int read():从输入流中读取数据的下一个字节。返回0到255范围内的int字节值。如果读到流的末尾,则返回 -1。 此方法一次只读一个字节,效率太低,一般不用
int read(byte[] b):从此输入流中将最多b.length个字节的数据保存到一个byte数组中。返回实际读取字节长度,如果读到流的末尾,也返回 -1。
int read(byte[] b,int off,int len):将输入流中最多len个数据字节读入byte数组。尝试读取len个字节,但读取的字节也可能小于该值,实际读取个数以读取到的为准,比如长度为23个字节的内容,每次读取5个字节,则第五次读取流并没处于末尾,还剩长度是3,故返回3。第六次读取发现是末尾,则返回 -1 。一般都用此方法。
public void close() throws IOException:关闭此输入流并释放与该流关联的所有系统资源,一定要关闭。
Reader
Reader和InputStream类似,就是将字节数组换成了字符数组
int read(); 效果与字节流一致
int read(char[] cbuf); 效果与字节流一致
int read(char[] cbuf,int off,int len); 效果与字节流一致
public void close() throws IOException;关闭此输入流并释放与该流关联的所有系统资源,字符流的必须要关闭,不然会出问题
OutputStream
void write(int b) :将指定的字节写入此输出流。
void write( byte[] b) :将b.length个字节从指定的byte数组写入此输出流。
void write(byte[] b,int off,int len):将指定byte数组中从偏移量off开始的len个字节写入此输出流。
public void flush() throws IOException:刷新此输出流并强制写出所有缓冲的输出字节,调用此方法指示应将这些字节立即写入它们预期的目标。就是将缓冲的字节全部写出到字节或字符数组中。
public void close() throws IOException:关闭此输入流并释放与该流关联的所有系统资源
Writer
void write(int c):写入单个字符。
void write(char[] cbuf):写入字符数组。
void write(char[] cbuf,int off,int len) : 写入字符数组的某一部分。从off开始,写入len个字符
void write(String str):写入字符串。
void write(String str,int off,int len):写入字符串的某一部分。
void flush():刷新该流的缓冲,则立即将它们写入预期目标。
public void close() throws IOException:关闭此输入流并释放与该流关联的所有系统资源
字节字符流相关操作
字节流读取文本内容
// 读取文本文件内容,用字节流去读,可能会乱码 public void test1() { InputStream inputStream = null; try { inputStream = new FileInputStream("hello.txt");//相对路径是工程路径下 int len; byte[] bytes = new byte[5];// 定义5字节长度的byte数组 while ((len = inputStream.read(bytes)) != -1) {// 将数据读到byte数组中 System.out.println(new String(bytes, 0, len)); //打印到控制台 } } catch (Exception e) { e.printStackTrace(); } finally { try { if (inputStream != null) { inputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } }
字符流读取文本内容
// 读取文本文件内容,用字符流去读,不会乱码,最多重复 public void test2() { Reader reader = null; try { reader = new FileReader("hello.txt"); int len; char[] charBuff = new char[5]; while ((len = reader.read(charBuff)) != -1) { // System.out.println(new String(charBuff)); // 注意这两行的代码区别 System.out.println(new String(charBuff, 0, len)); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (reader != null) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } } }
字节流读取文件到输出到指定位置
public void test3() { InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = new FileInputStream("hello.txt"); // 读取文件 outputStream = new FileOutputStream("hello2.txt"); // 相对路径,默认是工程路径下 int len; byte[] bytes = new byte[5]; while ((len = inputStream.read(bytes)) != -1) { outputStream.write(bytes, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (inputStream != null) { inputStream.close(); } if (outputStream != null){ outputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } }
字符流读取文件到输出到指定位置
字符流读取文件到输出到指定位置时,如果没有手动关闭流,则不会输出到指定位置,需要手动flush。但是如果在finally块中关闭了流,则会自动flush。在close()操作中,会帮我们flush。
public void test4() { Reader reader = null; Writer writer = null; try { reader = new FileReader("hello2.txt"); writer = new FileWriter("hello3.txt"); int len; char[] charBuff = new char[5]; while ((len = reader.read(charBuff)) != -1) { writer.write(charBuff, 0, len); // writer.flush(); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (reader != null) { reader.close(); } if (writer != null) { // 一定要关闭字符流,否则要手动flush writer.close(); } } catch (IOException e) { e.printStackTrace(); } } }
注意,字符流用来处理字符串很便捷,并且只能操作普通的文本文件,例如:.txt,.java,.c,.cpp 等语言的源代码。尤其注意.doc,excel,ppt这些不是文本文件。字节流既可以操做文本文件,也可以操作字节文件,比如.mp3,.avi,.rmvb,mp4,.jpg,.doc,.ppt。如果用字符流来操作图片等字节文件,生成的文件是无法打开的!
缓冲流
为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用 8192个字节(8Kb) 的缓冲区。
缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为BufferedInputStream和ufferedOutputStream以及BufferedReader和BufferedWriter。分别对应字节缓冲流和字符缓冲流。相当于在字节和字符流上包装了一下。
BufferedInputStream和BufferedOutputStream
public void test() { InputStream inputStream ; OutputStream outputStream ; BufferedInputStream bis = null; BufferedOutputStream bos = null; try { inputStream = new FileInputStream("modify.txt"); //小于8KB outputStream = new FileOutputStream("modify2.txt"); bis = new BufferedInputStream(inputStream); bos = new BufferedOutputStream(outputStream); int len; byte[] bytes = new byte[5]; while ((len = bis.read(bytes)) != -1) { bos.write(bytes, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (bis != null) { bis.close(); } if (bos != null){ bos.close(); } } catch (IOException e) { e.printStackTrace(); } } }
BufferedReader和BufferedWriter
public void test2() { Reader reader ; Writer writer ; BufferedReader br = null; BufferedWriter bw = null; try { reader = new FileReader("modify.txt"); writer = new FileWriter("modify2.txt"); br = new BufferedReader(reader); bw = new BufferedWriter(writer); int len; char[] bytes = new char[5]; while ((len = br.read(bytes)) != -1) { bw.write(bytes, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (br != null) { br.close(); } if (bw != null){ bw.close(); } } catch (IOException e) { e.printStackTrace(); } } }
**缓冲流如果没有手动关闭流,且读取的文件小于底层缓存大小8KB,是不会自动写到目标中去的,需要手动flush。**在关闭流时,只需关闭缓冲流即可,它会自动关闭它包装的底层节点流。
数据流
为了方便地操作Java语言的基本数据类型和String的数据,可以使用数据流。数据流有两个类:DataInputStream和DataOutputStream, 别“套接”在InputStream和OutputStream子类的流上。
使用如下:
public void test() { DataOutputStream dos = null; try { OutputStream outputStream = new FileOutputStream("data.txt"); dos = new DataOutputStream(outputStream); dos.writeUTF("热烈庆祝中国共产党成立一百周年"); dos.writeInt(100); dos.writeBoolean(true); System.out.println("成功!"); } catch (IOException e) { e.printStackTrace(); } finally { try { if (dos != null) { dos.close(); } } catch (IOException e) { e.printStackTrace(); } } } public void test2(){ DataInputStream dis = null; try { InputStream inputStream = new FileInputStream("data.txt"); dis = new DataInputStream(inputStream); System.out.println(dis.readUTF()); //读取时要按照写入顺序读取 System.out.println(dis.readInt()); System.out.println(dis.readBoolean()); System.out.println("成功!"); } catch (IOException e) { e.printStackTrace(); } finally { try { if (dis != null) { dis.close(); } } catch (IOException e) { e.printStackTrace(); } } }
对象流
用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
序列化与反序列化的演示
先定义一个Person类,该类必须实现Serializable接口,否则序列化时会报java.io.NotSerializableException 的错误
package day07; import java.io.Serializable; import java.util.Date; public class Person implements Serializable { private static final long serialVersionUID = -5858950242987134591L; private String name; private Integer age; private Date date; public Person(){} public Person(String name, Integer age, Date date) { this.name = name; this.age = age; this.date = date; } // getter、setter略 @Override public String toString() { return "Person{" + "name='" + name + ''' + ", age=" + age + ", date=" + date + '}'; } }
序列化
public void test() { ObjectOutputStream oos = null; try { OutputStream outputStream = new FileOutputStream("person.txt"); // 创建输出流对象,指定输出位置 oos = new ObjectOutputStream(outputStream); // 包装输出流 oos.writeObject(new Person("张三",22,new Date())); // 序列化对象 System.out.println("序列化成功!"); } catch (Exception e) { e.printStackTrace(); } finally { if (oos!=null){ try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
反序列化
public void test2() { ObjectInputStream ois = null; try { InputStream inputStream = new FileInputStream("person.txt"); ois = new ObjectInputStream(inputStream); Person person = (Person) ois.readObject(); System.out.println("person姓名为:" + person.getName()); System.out.println("person年龄为:" + person.getAge()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh时mm分ss秒"); System.out.println("创建时间为:" + sdf.format(person.getDate())); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { if (ois != null) { try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } } }
无论如何反序列化,时间都是不变的。
忍者必须死34399账号登录版 最新版v1.0.138v2.0.72
下载勇者秘境oppo版 安卓版v1.0.5
下载忍者必须死3一加版 最新版v1.0.138v2.0.72
下载绝世仙王官方正版 最新安卓版v1.0.49
下载Goat Simulator 3手机版 安卓版v1.0.8.2
Goat Simulator 3手机版是一个非常有趣的模拟游
Goat Simulator 3国际服 安卓版v1.0.8.2
Goat Simulator 3国际版是一个非常有趣的山羊模
烟花燃放模拟器中文版 2025最新版v1.0
烟花燃放模拟器是款仿真的烟花绽放模拟器类型单机小游戏,全方位
我的世界动漫世界 手机版v友y整合
我的世界动漫世界模组整合包是一款加入了动漫元素的素材整合包,
我的世界贝爷生存整合包 最新版v隔壁老王
我的世界MITE贝爷生存整合包是一款根据原版MC制作的魔改整