1 大纲:
一、节点流 1、字节数组 字节 节点流 输入流:ByteArrayInputStream read(byte[] b, int off, int len) + close() 输出流:ByteArrayOutputStream write(byte[] b, int off, int len) +toByteArray() 不要使用多态 二、处理流 1、基本类型+String 保留数据+类型 输入流:DataInputStream readXxx 输出流:DataOutputStream writeXxx 2、引用类型 (对象) 保留数据+类型 反序列化 输入流:ObjectInputStream readObject() 序列化 输出流:ObjectOutputStream writeObject() 注意: 1)、先序列化后反序列化;反序列化顺序必须与序列化一致 2)、不是所有的对象都可以序列化, java.io.Serializable 不是所有的属性都需要序列化,transient 3、打印流 PrintStream println() print() 4、三个常量 : System.in /out/err System.setIn() setOut() setErr()
2 代码
2.1 字节流使用: 用的不多吧,不知道为何设计出这个api来,操作和 fileinputstream fileoutputsteam一样
/** * 字节数组 节点流 * 数组的长度有限 ,数据量不会很大 * * 文件内容不用太大 * 1、文件 --程序->字节数组 * 2、字节数组 --程序->文件 * * * * @author Administrator * */ public class ByteArrayDemo01 { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { read(write()); } /** * 输出流 操作与文件输出流 有些不同, 有新增方法,不能使用多态 * @throws IOException */ public static byte[] write() throws IOException{ //目的地 byte[] dest; //选择流 不同点 ByteArrayOutputStream bos =new ByteArrayOutputStream(); //操作 写出 String msg ="操作与 文件输入流操作一致"; byte[] info =msg.getBytes(); bos.write(info, 0, info.length); //获取数据 , 创建一个新分配的 byte 数组 dest =bos.toByteArray(); //释放资源 bos.close(); return dest; } /** * 输入流 操作与 文件输入流操作一致 * 读取字节数组 * @throws IOException */ public static void read(byte[] src) throws IOException{ //数据源传入 //选择流 InputStream is =new BufferedInputStream( new ByteArrayInputStream( src ) ); //操作 byte[] flush =new byte[1024]; int len =0; while(-1!=(len=is.read(flush))){ System.out.println(new String(flush,0,len)); } //释放资源 is.close(); } }
/** *1、文件 --程序->字节数组 *1)、文件输入流 * 字节数组输出流 * * * 2、字节数组 --程序->文件 * 1)、字节数组输入流 * 文件输出流 * @author Administrator * */ public class ByteArrayDemo02 { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { byte[] data =getBytesFromFile("e:/xp/test/1.jpg"); toFileFromByteArray(data,"e:/xp/test/arr.jpg"); } /** * 2、字节数组 --程序->文件 */ public static void toFileFromByteArray(byte[] src,String destPath) throws IOException{ //创建源 //目的地 File dest=new File(destPath); //选择流 //字节数组输入流 InputStream is =new BufferedInputStream(new ByteArrayInputStream(src)); //文件输出流 OutputStream os =new BufferedOutputStream(new FileOutputStream(dest)); //操作 不断读取字节数组 byte[] flush =new byte[1]; int len =0; while(-1!=(len =is.read(flush))){ //写出到文件中 os.write(flush, 0, len); } os.flush(); //释放资源 os.close(); is.close(); } /** * 1、文件 --程序->字节数组 * @return * @throws IOException */ public static byte[] getBytesFromFile(String srcPath) throws IOException{ //创建文件源 File src =new File(srcPath); //创建字节数组目的地 byte[] dest =null; //选择流 //文件输入流 InputStream is =new BufferedInputStream(new FileInputStream(src)); //字节数组输出流 不能使用多态 ByteArrayOutputStream bos =new ByteArrayOutputStream(); //操作 不断读取文件 写出到字节数组流中 byte[] flush =new byte[1024]; int len =0; while(-1!=(len =is.read(flush))){ //写出到字节数组流中 bos.write(flush, 0, len); } bos.flush(); //获取数据 dest =bos.toByteArray(); bos.close(); is.close(); return dest; } }
2.2 DataInputStream DataOutputStream 将数据和类型都写出去
官网解释:
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据
注意看代码中的注释, 写出去的数据顺序必须要和读取的数据类型顺序保持一致, 这点和
hadoop中 自定义 javabean在跨机器传输时, 写出和写入严格按照顺序一致,我想hadoop在设计的时候就是用javase的这两个类来实现的。
/** * 数据类型(基本+String)处理流 * 1、输入流 DataInputStream readXxx() * 2、输出流 DataOutputStream writeXxx() * 新增方法不能使用多态 * * java.io.EOFException :没有读取到相关的内容 * @author Administrator * */ public class DataDemo01 { /** * @param args */ public static void main(String[] args) { try { //write("e:/xp/test/data.txt"); // 将字符和字符格式都写到磁盘中,此时双击磁盘文件会是乱码 因为这种文件是给计算机看的 不是给人来看的 read("e:/xp/test/data.txt"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 从文件读取数据+类型 * @throws IOException */ public static void read(String destPath) throws IOException{ //创建源 File src =new File(destPath); //选择流 DataInputStream dis =new DataInputStream( new BufferedInputStream( new FileInputStream(src) ) ); //操作 读取的顺序与写出一致 必须存在才能读取 //不一致,数据存在问题 long num2 =dis.readLong(); double num1 =dis.readDouble(); String str =dis.readUTF(); dis.close(); System.out.println(num2+"-->"+str); } /** * 数据+类型输出到文件 将 数据类型和数据值写到磁盘中 * @throws IOException */ public static void write(String destPath) throws IOException{ double point =2.5; long num=100L; String str ="数据类型"; //创建源 File dest =new File(destPath); //选择流 DataOutputStream DataOutputStream dos =new DataOutputStream( new BufferedOutputStream( new FileOutputStream(dest) ) ); //操作 写出的顺序 为读取准备 dos.writeDouble(point); dos.writeLong(num); dos.writeUTF(str); dos.flush(); //释放资源 dos.close(); } }
/** * 数据类型(基本+String)处理流 * 1、输入流 DataInputStream readXxx() * 2、输出流 DataOutputStream writeXxx() * 新增方法不能使用多态 * * java.io.EOFException :没有读取到相关的内容 * @author Administrator * */ public class DataDemo02 { /** * @param args */ public static void main(String[] args) { try { byte[] data=write(); read(data); System.out.println(data.length); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 从字节数组读取数据+类型 * @throws IOException */ public static void read(byte[] src) throws IOException{ //选择流 DataInputStream dis =new DataInputStream( new BufferedInputStream( new ByteArrayInputStream(src) ) ); //操作 读取的顺序与写出一致 必须存在才能读取 double num1 =dis.readDouble(); long num2 =dis.readLong(); String str =dis.readUTF(); dis.close(); System.out.println(num1+"-->"+num2+"-->"+str); } /** * 数据+类型输出到字节数组中 * @throws IOException */ public static byte[] write() throws IOException{ //目标数组 byte[] dest =null; double point =2.5; long num=100L; String str ="数据类型"; //选择流 ByteArrayOutputStream DataOutputStream ByteArrayOutputStream bos =new ByteArrayOutputStream(); DataOutputStream dos =new DataOutputStream( new BufferedOutputStream( bos ) ); //操作 写出的顺序 为读取准备 dos.writeDouble(point); dos.writeLong(num); dos.writeUTF(str); dos.flush(); dest =bos.toByteArray(); //释放资源 dos.close(); return dest; } }
2.3 序列化和反序列化 ObjectOutputStream ObjectInputStream
public class Employee implements java.io.Serializable { //不需要序列化 private transient String name; private double salary; public Employee() { } public Employee(String name, double salary) { super(); this.name = name; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } } /** * 不是所有的對象都可以序列化 java.io.NotSerializableException * 不是所有的屬性都需要序列化 transient * @author Administrator * */ public class ObjectDemo01 { /** * @param args * @throws ClassNotFoundException */ public static void main(String[] args) throws ClassNotFoundException { try { seri("e:/xp/test/ser.txt"); read("e:/xp/test/ser.txt"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //反序列化 将计算机世界中的数字影射到人类世界中 public static void read(String destPath) throws IOException, ClassNotFoundException{ //创建源 File src =new File(destPath); //选择流 ObjectInputStream dis =new ObjectInputStream( new BufferedInputStream( new FileInputStream(src) ) ); //操作 读取的顺序与写出一致 必须存在才能读取 //不一致,数据存在问题 Object obj =dis.readObject(); if(obj instanceof Employee){ Employee emp=(Employee)obj; System.out.println(emp.getName()); System.out.println(emp.getSalary()); } obj =dis.readObject(); int[] arr=(int[])obj; System.out.println(Arrays.toString(arr)); dis.close(); } //序列化 人类识别的字符写到磁盘中 public static void seri(String destPath) throws IOException{ Employee emp =new Employee("bjsxt",1000000); int[] arr ={1,2,3,45}; //创建源 File dest =new File(destPath); //选择流 ObjectOutputStream ObjectOutputStream dos =new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream(dest) ) ); //操作 写出的顺序 为读取准备 dos.writeObject(emp); dos.writeObject(arr); //释放资源 dos.close(); } }
2.4 打印流: 请仔细阅读注释部分的总结,精华都在这 PrintStream
/** * PrintStream 打印流 -->处理流 PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式 重定向输出 可以用两个方式: 1 ps = new PrintStream(dest) ; ps.print(xxx) 2 System.setOut(PrintStream out) ; System.out.println("a"); 其中System.out System.in System.erro返回的对象都是PrintStream, System.out.println 等同于上面1的 ps.print(xxx) * @author Administrator * */ public class PrintStreamDemo01 { /** * @param args * @throws FileNotFoundException */ public static void main(String[] args) throws FileNotFoundException { System.out.println("test"); PrintStream ps =System.out; // ps.println(false); //输出到文件 File src = new File("e:/xp/test/print.txt"); ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(src))); // 创建新的打印流 将打印的数据输出到目标文件中 ps.println("io is so easy...."); ps.close(); } } ** * 三个常量 * 1、System.in 输入流 键盘输入 * 2、System.out 输出流 控制台输出 * System.err * * ==>重定向 * setIn() * setOut() * setErr() * FileDescriptor.in 控制台的输入流 可以在System.class中找到 * FileDescriptor.out 控制台的输入流 可以在System.class中找到 * @author Administrator * */ public class SystemDemo01 { /** * @param args * @throws FileNotFoundException 打印流改变输出方式 答应到文件 然后在切换回来打印到控制台 */ public static void main(String[] args) throws FileNotFoundException { //test1(); //test2(); //重定向 // 如果为 true,则每当写入 byte 数组、调用其中一个 println 方法或写入换行符或字节 ('\n') 时都会刷新输出缓冲区 System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream("e:/xp/test/print.txt")),true)); System.out.println("a"); //控制台 -->文件 System.out.println("test"); //回控制台 System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)),true)); // FileDescriptor.in是控制台使用的标准输入流 System.out.println("back...."); } public static void test2() throws FileNotFoundException{ InputStream is =System.in; //键盘输入 is = new BufferedInputStream(new FileInputStream("e:/xp/test/print.txt")); Scanner sc = new Scanner(is); //System.out.println("请输入:"); System.out.println(sc.nextLine()); } public static void test1(){ System.out.println("test"); System.err.println("err"); } }