IO
节点流 + 缓冲流(共8个)
IO流使用步骤、技巧
"IDEA中" JUnit单元测试中,相对路径为当前Module下。 如果是main方法,相对路径为当前Project下。 ======================================================================================================================== "IO流使用步骤" ①造文件/路径 //流的构造方法可以是 : 文件全路径 或者 File对象 ②造流(用缓冲流) ③读写(续写)数据 ④关闭资源:只需要关外层流 ⑤try catch finally ======================================================================================================================= "技巧" 字符流:文本文件(.txt、.java、.c、.cpp...)。 char[]、str.toCharArray() 字节流:二进制文件(图片、视频、声音、doc、ppt等)不会被损坏。 byte[]、str.getBytes() 熟悉之后写法:new BufferedInputStream(new FileInputStream(scrPath)); 输出流构造方法,设置是否续写(,true) ======================================================================================================================= //写文件时,文件不存在,自动创建文件,没设置续写则覆盖 System.out.println(new String(buf,0,len)); while((line = br.readLine())!=null){ System.out.println(line); } //设置续写 new BufferedWriter(new FileWriter(filePath,true)); bw.newLine(); //换行 //
IO 流体系
视频(非文本)加密
/** * 非文本:字节流 * 非文本文件加密:异或5 * */ public static void code(String scrPath,String destPath){ //为了提高效率,都用缓存流 BufferedInputStream bis = null; BufferedOutputStream bos = null; try { //造流:操作视频用字节流 bis = new BufferedInputStream(new FileInputStream(scrPath)); bos = new BufferedOutputStream(new FileOutputStream(destPath)); //读写操作 byte[] buff = new byte[1024]; int len; while((len=bis.read(buff))!=-1){ //加密操作,异或操作 for (int i = 0; i < len; i++) { buff[i] = (byte) (buff[i]^5); } //写入原文件 bos.write(buff,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { //关闭流 if (bos!=null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if (bis!=null){ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println("加密完成!"); } }
视频(非文本)解密
/** * 非文本文件解密:异或5 * */ public static void deCode(String scrPath,String destPath){ //为了提高效率,都用缓存流 BufferedInputStream bis = null; BufferedOutputStream bos = null; try { //造流:操作视频用字节流 bis = new BufferedInputStream(new FileInputStream(scrPath)); bos = new BufferedOutputStream(new FileOutputStream(destPath)); //读写操作 byte[] buff = new byte[1024]; int len; while((len=bis.read(buff))!=-1){ //加密操作,异或操作 for (int i = 0; i < len; i++) { buff[i] = (byte) (buff[i]^5); } //写入原文件 bos.write(buff,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { //关闭流 if (bos!=null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if (bis!=null){ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println("解密完成!"); } }
统计文本上每个字符出现的个数(Map)
/** * 文本:字符流 * 获取文本上每个字符出现的个数(Map实现) * 然后写进新文件 * */ public static void CountText(String scrPath,String destPath) { BufferedReader br = null; BufferedWriter bw = null; try { //1.造流 br = new BufferedReader(new FileReader(scrPath)); bw = new BufferedWriter(new FileWriter(destPath)); HashMap<Character,Integer> map = new HashMap<>(); //读写操作 char[] cbuff = new char[1024]; int len; while ((len=br.read(cbuff))!=-1){ //遍历cbuff,将数据更新进map for (int i = 0; i < len; i++) { //如果map存在当前字符,value++; if(map.containsKey(cbuff[i])){ map.put(cbuff[i],(map.get(cbuff[i])+1)); }else { map.put(cbuff[i],1); } } } //把map的数据写入destPath Set<Map.Entry<Character, Integer>> entries = map.entrySet(); for (Map.Entry<Character, Integer> entry : entries) { switch (entry.getKey()){ case ' ': bw.write("空格="+entry.getValue());break; case '\t': bw.write("tab建="+entry.getValue());break; case '\r': bw.write("回车="+entry.getValue());break; case '\n': bw.write("换行="+entry.getValue());break; default: bw.write(entry.getKey()+"="+entry.getValue());break; } bw.newLine(); } } catch (IOException e) { e.printStackTrace(); } finally { //关闭流 if(br!=null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if(br!=null){ try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println("文本统计完成!"); } }
其他处理流
字符集
ASCII:美国标准信息交换码 ISO8859-1:拉丁码表 GB2312:早期中文编码表 GBK:升级版中文编码表 Unicode:国际标准码 UTF-8:变长的编码格式
转换流:字符流
======================================================================================================================== InputStreamReader(InputStream,...) : 字节输入流 ==> 字符输入流----解码(提供解码字符集)(看不懂 ==> 看得懂) OutputStreamWriter(OutputStream,...) : 字符输出流 ==> 字节输出流----编码(设置编码字符集)(看得懂 ==> 看不懂) 作用:提供字节流与字符流之间的转换,解码以及编码 ======================================================================================================================== public static void Test01(String srcPath,String destPath) { //可以嵌套缓冲流,不过只能读取文本,因为是下面四个字符流 BufferedReader br = null; BufferedWriter bw = null; long start = System.currentTimeMillis(); long end=0; try { //转换流:字符流 InputStreamReader isr = new InputStreamReader(new FileInputStream(srcPath)); OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(destPath)); //缓冲流 br = new BufferedReader(isr); bw = new BufferedWriter(osw); //注意InputStreamReader 和 OutputStreamWriter 属于字符流 char[] cbuff = new char[1024]; int len; while((len=br.read(cbuff))!=-1){ //写入新文件 bw.write(cbuff,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { if(bw!=null) { try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } if(br!=null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } end = System.currentTimeMillis(); System.out.println("复制成功,共花了"+(end-start)+"毫秒"); } }
对象处理流(类要实现Serializable,并提供serialVersionUID)
要求
(1) 自定义类实现Serializable接口 (2) 自定义类提供一个全局常量 private static final long serialVersionUID = 263298232L; 防止版本不兼容:类内容发生改变,导致反序列化失败 (3) 自定义类中内部所有属性也必须是可序列化的
对象序列化处理流:ObjectOutputStream
对象反序列化处理流:ObjectInputStream
public class ObjectOutputStream_ { public static void main(String[] args) throws IOException { //序列化后,保存的文件格式是java自己定的格式,所以我们可以随便给后缀名 String filePath = "f:\\data.dat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath)); //序列化数据 oos.writeInt(100); //序列化int型数据 oos.writeBoolean(true); //序列化Boolean型数据 oos.writeChar('a'); //序列化Char型数据 oos.writeUTF("我是字符串"); //序列化String型数据 //当要序列化自定义对象时,对象实现Ser\ oos.writeObject(new Dog("金毛","绿色")); oos.close(); } } //实现序列化 Serializable static class Dog implements Serializable { private String name; private String color; //唯一标识号,实现这个之后,序列化之后改变类也能反序列化出来 private static final long serialVersionUID = 1L; public Dog(String name, String color) { this.name = name; this.color = color; } }
`
读取(反序列化)的顺序一定要和写入(序列化)顺序一致 如果要读取自定义类,输出信息,就必须在读取类下面定义这个类 static class Dog implements Serializable public class ObjectInputStream_ { public static void main(String[] args) throws IOException, ClassNotFoundException { String filePath = "f:\\data.dat"; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath)); //读取的顺序一定要和存入的顺序一致,不然报错 System.out.println(ois.readInt()); System.out.println(ois.readBoolean()); System.out.println(ois.readChar()); System.out.println(ois.readUTF()); Dog dog = (Dog)ois.readObject(); ois.close(); /* byte[] buf = new byte[1024]; ois.readFully(buf); System.out.println();*/ } static class Dog implements Serializable { private String name; private String color; //唯一标识号,实现这个之后,序列化之后改变类也能反序列化出来 private static final long serialVersionUID = 1L; @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", color='" + color + '\'' + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public Dog(String name, String color) { this.name = name; this.color = color; } } }
RandomAccessFile:直接父类Object,和四个抽象基类没关系,但是属于io
二维数组写入与读出
//写入内存 public static void write(int[][] sparseArr){ //写入内存 String filePath = "D:\\CODE\\算法\\DataStructes\\src\\reader.txt"; ObjectOutputStream bos = null; try { bos = new ObjectOutputStream(new FileOutputStream(filePath)); bos.writeObject(sparseArr); //一定要刷新或者关闭 bos.flush(); System.out.println("稀疏数组写入成功"); } catch (IOException e){ e.getCause(); } finally { try { if(bos!=null) bos.close(); } catch (IOException e) { e.printStackTrace(); } } }
//读取稀疏数组 public static int[][] ride(){ String filePath = "D:\\CODE\\算法\\DataStructes\\src\\reader.txt"; ObjectInputStream bis = null; int[][] sparseArr01 = null; try { bis = new ObjectInputStream(new FileInputStream(filePath)); sparseArr01 = (int[][]) bis.readObject(); System.out.println("========从内存中读取稀疏数组成功!=========="); }catch (IOException | ClassNotFoundException e){ e.getCause(); }finally { try { if(bis!=null) bis.close(); } catch (IOException e) { e.printStackTrace(); } } return sparseArr01; }
面试题
1、流的三种分类方式 流向:输入流、输出流 数据单位:字节流、字符流 流的角色:节点流、处理流#Java##学习路径#