深入IO 想学必看!受益匪浅哦~
一:IO流概述
IO流简单来说就是Input和Output流,IO流主要是用来处理设备之间的数据传输,Java对于数据的操作都是通过流实现,而Java用于操作流的对象都在IO包中。
分类:
按操作数据分为:字节流和字符流。如:Reader和InputStream
按流向分:输入流和输出流。如:InputStream和OutputStream
字节流的基类:
InputStream , OutputStream
字符流的抽象基类:
Reader , Writer
缓冲流的基类:
BufferReader,BufferWriter (必须依赖于 Reader和Writer)
二进制流的基类:
DataInputStream,DataOutputStream (必须依赖于InputStream 和 OutputStream)
序列化:
ObjectInputStream,ObjectOutputStream (必须依赖于InputStream 和 OutputStream )
我们的程序需要通过InputStream或Reader从数据源读取数据,然后用OutputStream或者Writer将数据写入到目标媒介中。其中,InputStream和Reader与数据源相关联,OutputStream和writer与目标媒介相关联。 以下的图说明了这一点:

二:字符流
1.字符流简介:
01.字符流中的对象融合了编码表,也就是系统默认的编码表。我们的系统一般都是GBK编码。
02.字符流 只用来处理文本数据,字节流用来处理媒体数据。
03.数据最常见的表现方式是文件,字符流用来操作文件的子类一般是FileReader和FileWriter
2.字符流读写:
注意事项:
01.写入文件后必须要用flush()刷新
02.用完流后记得要关闭流
03.使用流对象要抛出IO异常
04.定义文件路径时,可以用"/"或者"\\"
05.在创建一个文件时,如果目录下有同名文件将被覆盖
06.在读取文件时,必须保证该文件已存在,否则出异常
示例:
public class CharDemo { public static void main( String[] args ) { //创建输入和输出流 Reader reader = null; Writer writer = null; try { //目的是明确数据要存放的目的地。 reader = new FileReader("e:/a.txt"); writer = new FileWriter("e:/a.txt",true); //在文件中写入 writer.write("啦啦啦"); writer.write("啦啦啦"); writer.write("我是卖报的小行家"); //清空缓冲区 writer.flush(); writer.write("啦啦啦"); writer.write("啦啦啦"); writer.write("啦啦啦"); writer.close(); //读取 //创建一次性读取多少个字符 char[] data = new char[1024]; int num = 0; StringBuffer sb = new StringBuffer(); //判断如果文件中有数据,则在后面追加数据 while ((num = reader.read(data))!=-1){ sb.append(data); } System.out.println(sb.toString()); } catch (Exception e) { e.printStackTrace(); } finally { try { // writer.close();应该放到添加数据完之后 reader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
三:字节流
在Java中,字节流一般适用于处理字节数据(诸如图片、视频),字符流适用于处理字符数据(诸如文本文件),但二者并没有严格的功能划分,因为有转换流的存在,使得对于数据的处理变得更加灵活。InputStream和OutputStream分别是字节输入流与字节输出流的基类,它们的子类都是字节流,主要用在按字节来处理二进制数据。废话不多说,上示例!
public class ByteDemo { public static void main( String[] args ) { //创建输入流和输出流对象 InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = new FileInputStream("e:/a.txt"); //true 代表是否向文件中拼接,不删除之前的内容 outputStream = new FileOutputStream("e:/a.txt",true); //先向文件写入内容 outputStream.write("54321".getBytes());//outputStream.flush();自己没有实现 //read方法将返回0-255之间的数字 如果流读到了最后,将返回-1 int num = 0; while ((num=inputStream.read())!=1){ System.out.println((char) num); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { inputStream.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
四:二进制流
二进制流有两个顶级类:InputStream和OutputStream, 下面的两个类是各种附属类。作为对比,二进制流的关系比字符流的更加多样化和复杂。关于二进制流,LineNumberInputStream和StringBufferInputStream两个类在JDK1.5中,尽量不要使用,因为它们已被弃用。
给你们看一个简单的小示例,来了解一下吧!
public class DataDemo { public static void main(String[] args) { //创建输入流和输出流对象 InputStream inputStream = null; OutputStream outputStream=null; DataInputStream dis = null; DataOutputStream dos=null; try { //获取了输入流 txt进入内存 inputStream=new FileInputStream("e:/a.txt"); dis=new DataInputStream(inputStream); //获取输出流 outputStream=new FileOutputStream("e:/public/a.txt"); dos=new DataOutputStream(outputStream); //先读取 int num=0; while ((num=dis.read())!=-1){ dos.write(num); //复制 } } catch (Exception e) { e.printStackTrace(); }finally { //释放资源 try { dos.close(); dis.close(); outputStream.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
五:缓冲流
定义:在内存与硬盘之间创建一个大小合适的缓冲区,当内存和硬盘进行数据访问时,能提高访问硬盘的次数,提高效率。
分类:缓冲分为字节缓冲流(BufferedInputStream和BufferedOutputStream)和字符缓冲流(BufferedReader和BufferedWrite)。
小小的案例,大大的了解~
public class BufferDemo { public static void main(String[] args) { //创建输出流 Reader reader = null; Writer writer = null; BufferedReader br = null; BufferedWriter bw = null; try { writer = new FileWriter("e:/a.txt",true); bw = new BufferedWriter(writer); bw.write("你好!");
//换行 bw.newLine(); bw.write("llll");
//清空缓冲区 bw.flush(); bw.write("222"); bw.write("333"); bw.write("444"); bw.close(); writer.close(); //如果不关闭 后续两句话没法获取 //读取 reader=new FileReader("e:/a.txt"); br=new BufferedReader(reader);//封装 String line=null; StringBuffer sb=new StringBuffer(); while ((line=br.readLine())!=null){ sb.append(line); } System.out.println(sb.toString()); } catch (IOException e) { e.printStackTrace(); }finally { try { br.close(); reader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
六:序列化和反序列化
序列化:把对象转换为字节序列的过程称为对象的序列化。(持续化)
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
比如说登陆注册,注册就是序列化,登陆就是反序列化!!!为什么呢?注册,就是把用户的信息存储到硬盘中,就是持久化!登陆就是把信息再返回来,意思就是,从硬盘中读取出来,称之为反序列化!
来个栗子更直观一些!
首先来一个实体类
package com.ftx; import java.io.Serializable; /** * @author 岔气的猫 * @create 2018-07-03 15:49 * @博客地址:https://home.cnblogs.com/u/fl72/ * 必须实现Serializable接口,否则在执行过程中,会报错!实现不了序列化 **/ public class User implements Serializable { private String userName; private String userPassword; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserPassword() { return userPassword; } public void setUserPassword(String userPassword) { this.userPassword = userPassword; } public User(String userName, String userPassword) { this.userName = userName; this.userPassword = userPassword; } public User() { } @Override public String toString() { return "User{" + "userName='" + userName + '\'' + ", userPassword='" + userPassword + '\'' + '}'; } }
接下来,好戏就要开始喽!
public class ObjectDemo { static Scanner input = new Scanner(System.in); //创建需要的输入和输出流对象 static InputStream inputStream = null; static OutputStream outputStream = null; static ObjectInputStream objectInputStream = null; static ObjectOutputStream objectOutputStream = null; public static void main(String[] args) { //注册 序列化 //register(); //登录 反序列化 login(); } //注册 private static void register() { User user = new User(); System.out.println("请输入您的用户名:"); user.setUserName(input.next()); System.out.println("请输入您的密码:"); user.setUserPassword(input.next()); try { outputStream = new FileOutputStream("e:/user.txt"); objectOutputStream = new ObjectOutputStream(outputStream); //把对象输出到文件中 objectOutputStream.writeObject(user); } catch (Exception e) { e.printStackTrace(); } finally { try { objectOutputStream.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } //登录 private static void login() { try { inputStream = new FileInputStream("e:/user.txt"); objectInputStream = new ObjectInputStream(inputStream); //读取对象 User user = (User) objectInputStream.readObject(); System.out.println(user); } catch (Exception e) { e.printStackTrace(); } finally { try { objectInputStream.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
怎么样,明白了吗?
七:字节流转字符流
public static void convertByteToChar() throws IOException{ File file= new File( "d:/test.txt"); //获得一个字节流 InputStream is= new FileInputStream( file); //把字节流转换为字符流,其实就是把字符流和字节流组合的结果。 Reader reader= new InputStreamReader( is); char [] byteArray= new char[( int) file.length()]; int size= reader.read( byteArray); System. out.println( "大小:"+size +";内容:" +new String(byteArray)); is.close(); reader.close(); }
八:File的使用
public class FileDemo { static Scanner input=new Scanner(System.in); public static void main( String[] args ) { System.out.println( "*************欢迎进入文件操作系统*************" ); System.out.println( "*************1.创建文件*************" ); System.out.println( "*************2.删除文件*************" ); System.out.println( "*************3.修改文件*************" ); System.out.println( "*************4.创建文件夹*************" ); System.out.println( "*************5.查询文件夹下所有的文件列表*************" ); System.out.println( "*************请选择:*************" ); //获取用户的输入 int choose = input.nextInt(); switch (choose){ case 1://创建文件 createNewFile(); break; case 2://删除文件 deleteFile(); break; case 3://修改文件 updateFile(); break; case 4://创建文件夹 mkdirs(); break; case 5://查询文件夹下所有的文件列表 findFileList(); break; } } //查询文件夹下所有的文件列表 private static void findFileList() { System.out.println("请您输入需要查询的文件夹的名称:(默认是E:/)"); String fileName = input.next(); //创建File对象 File file=new File("E:/"+fileName); File[] files = file.listFiles(); int driNums = 0; int fileNums = 0; System.out.println("此文件夹下包含了:"); for (File f:files) { if (f.isDirectory()){ driNums++; System.out.println(f.getName()); } if (f.isFile()){ fileNums++; System.out.println(f.getName()); } } System.out.println("此文件夹下的文件夹有"+driNums); System.out.println("此文件夹下的文件有"+fileNums); } //创建文件夹 private static void mkdirs() { System.out.println("请您输入创建的文件的名称:(默认是E:/)"); String fileName = input.next(); //创建File对象 File file=new File("E:/"+fileName); if(file.mkdirs()){ System.out.println("创建成功!"); }else{ System.out.println("创建失败!"); } } //修改文件 private static void updateFile() { System.out.println("请您输入需要修改的文件的名称:(默认是E:/)"); String oldFileName = input.next(); System.out.println("请您输入修改后的文件的名称:(默认是E:/)"); String newFileName = input.next(); //创建File对象 File oldFile=new File("E:/"+oldFileName); File newFile=new File("E:/"+newFileName); if (oldFile.renameTo(newFile)){ System.out.println("修改成功!"); }else { System.out.println("修改失败!"); } } //删除文件 private static void deleteFile() { System.out.println("请您输入需要删除的文件的名称:(默认是E:/)"); String fileName = input.next(); //创建File对象 File file=new File("E:/"+fileName); if(file.exists()){ boolean falg = file.delete(); if (falg){ System.out.println("删除成功!"); }else { System.out.println("删除失败!"); } }else { System.out.println("您输入的文件不存在!"); } } //创建文件 private static void createNewFile() { System.out.println("请您输入文件的名称:(默认是E:/)"); String fileName = input.next(); //创建File对象 File file=new File("E:/"+fileName); if (file.exists()){ //文件已经存在 System.out.println("该文件已经存在!"); }else{ try { boolean flag= file.createNewFile(); if (flag){ System.out.println("文件创建成功!"); }else{ System.out.println("文件创建失败!"); } } catch (IOException e) { e.printStackTrace(); } } } }

浙公网安备 33010602011771号