zoukankan      html  css  js  c++  java
  • 02 IO 干货

    基本内容

    Process

    1) 确定源

    2) 选择流

    3) 操作(读,写)

    4) 释放资源.

    分隔符

    建议采用 "C:/JavaWork/asdf/xxx.java"   这种 /

    无论是字节处理,还是字符处理, 都要套一层 buffer 来提升性能. (默认是 8k 做一次 I/O 的交互)

    文件

    File 类 用来定义源, 一般是本地文件

    File src = new File("stanford.txt")
    也可以直接用FileInputStream("stanford.txt") 这种来导入文件
    字节码 处理 (文件copy)

    字节可以处理一切文件, 无论是 视频,音频,文本.

    InputStream & OutputStream -> BufferedInputStream & BufferedOutputStream,  FileInputStream & FileOutputStream(直接字节流作用于文件)

    package com.pratice.java300;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    public class MyByteCopy {
    
        public static void main(String[] args) {
            copyByte("stanford.txt", "xxx.txt");
        }
        
        public static void copyByte(String src, String dest) {
            try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest));){
                byte[] temp = new byte[1024];
                int len = -1;
                while ((len = bis.read(temp)) != -1) {
                    bos.write(temp, 0, len);
                    // 字节copy, 不用考虑换行符问题, 因为换行符包含在字节copy中
                }
            }catch(IOException e) {
                e.printStackTrace();
            }
        }
    }

    把文件流封装在 try 的括号里边, 就不用释放资源了, 自动释放了.

    字符处理 (文件copy)

    只能处理文本

    Reader & Writer -> BufferedReader & BufferedWriter,    FileReader & FileWriter(直接字符流作用于文件)

    package com.pratice.java300;
    
    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    
    public class MyCharCopy {
    
        public static void main(String[] args) {
            copyChar("stanford.txt", "xxx.txt");
        }
        
        public static void copyChar(String src, String dest) {
            try(BufferedReader br = new BufferedReader(new FileReader(src));
            BufferedWriter bw = new BufferedWriter(new FileWriter(dest));){
                String msg = null;
                int line = 0;
                while ((msg = br.readLine()) != null) {
                    if (0 == line) {
                        line++;
                    } else {
                        bw.newLine();
                    }
                    bw.write(msg, 0, msg.length());
                }
            }catch(IOException e) {
                e.printStackTrace();
            }
        }
    }
    源并非文件实体, 而是内存, 例子中输出也是内存

    字节数组流 ByteArrayInputStream 和 ByteArrayOutputStream, 因为这里不设计到 IO, 所以就没有 buffered。

    ByteArrayInputStream 实际上是内存的一个内部缓冲区, 可以接受来自字节流的数据. 相当于读取到内存,转化成流处理,

      我们都知道, 这里的文件处理都是 I/O 之间流的转换, 所以可以先通过 ByteArrayInputStream 将输入转换成流,缓存到内存中, 以备使用.

    ByteArrayOutputStream 该类实现了将数据写入字节数组的输出流, 写出内存, 但是你想获得写出的数据, 需要使用 dest = baos.toByteArray()

      可以将内存区缓存的内容读出到输出流来进行实际的处理, 比如 BytemArrayOutputStream -> OutputStream -> file

    String -> ByteArrayInputStream(加工, 比如转换成大写字母) -> ByteArrayOutputStream -> byte[] array -> dest file 的例子:

    package com.pratice.java300;
    
    import java.io.BufferedOutputStream;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    
    public class MyMemoryCopy {
    
        public static void main(String[] args) {
            copyMemoryToFile("asdfxxxjjjgggqqq111", "xxx.txt");
        }
        
        public static void copyMemoryToFile(String src, String dest) {
            try(ByteArrayInputStream bais = new ByteArrayInputStream(src.getBytes());
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest))
                    ){
                // 1.读取缓冲区的内容, 转换成大写字母
                int ch = -1;
                byte[] out;
                while ((ch = bais.read()) != -1) {
                    int upperCh = Character.toUpperCase((char)ch);
                    baos.write(upperCh);
                }
                baos.flush();
                // 2. 将缓冲区的文件输出为字节数组
                out = baos.toByteArray();
                // 3. 将字节数组写出到文件
                bos.write(out);
            }catch(IOException e) {
                e.printStackTrace();
            }
        }
    }
    字节流 转字符流 (文件copy)

     InputStreamReader : 读取字节流并帮助转换成字符流

    OutputStreamWriter: 读取的是字符流并帮助转换成字节流

    package com.pratice.java300;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.URL;
    
    public class MyByte2Char {
    
        public static void main(String[] args) {
            byte2Char();
        }
        
        public static void byte2Char() {
            try(
                // 从字节到字符
                BufferedReader reader = 
                    new BufferedReader(
                        new InputStreamReader(
                            new URL("http://www.baidu.com").openStream(), "UTF-8"));
                // 从字符到字节
                BufferedWriter writer = 
                    new BufferedWriter(
                        new OutputStreamWriter(
                            new FileOutputStream("baidu2.html"), "UTF-8"));){
                String msg = null;
                while ((msg = reader.readLine()) != null) {
                    writer.write(msg);
                    writer.newLine();
                }
                writer.flush();
    
            }catch(IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    数据流处理(保留了数据类型)

    DataInputStream & DataOutputStream

    处理的方式与下边的对象流一样. 在类似 socket 编程, 等需要传递时, 很常用

    注意, 进入数据流的顺序, 必须和出数据流的顺序一致.

    所以, 你可以这么写:

    String msg = dis.readWTF();   //这也不是把所有在流里的的 string 类型数据都读取出来, 而是通过顺序(进入数据流流), 顺序到这是String类型的.

    int salary = dis.readInt();    // 这里的 dis 就是数据流, readInt() 并不是把所有的 int 型的数据都读取出来, 而是根据顺序的.

    对象流(序列化 & 反序列化)

    () ObjectInputStream : 将字节流转化为对象 (反序列化), 在你想要反序列化之前, 必须先使用 ObjectOutputStream 把对象序列化成字节流

    () ObjectOutputStream : 将对象转换为 字节流(序列化)不是所有的对象都可以序列化, 必须实现一个接口 Serializable 

    对象 -> ObjectOutputStream 封装成字节流 ->   ObjectInputStream  -> 对象

    package com.pratice.java300;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.sql.Date;
    
    public class MyObjectCopy {
    
        public static void main(String[] args) throws ClassNotFoundException {
            try(
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream dos = new ObjectOutputStream(baos);
                ){
                dos.writeObject("asdf");
                Employee employee = new Employee("张三", 10000);
                dos.writeObject(employee);
                dos.flush();
                byte[] datas = baos.toByteArray();
                
                ObjectInputStream dis = new ObjectInputStream(new ByteArrayInputStream(datas));
                // 调用顺序与写入一样
                Object msg = dis.readObject();
                Object emp = dis.readObject();
                if (msg instanceof String) {
                    String msgObj = (String)msg;
                    System.out.println(msgObj);
                }
                if (emp instanceof Employee) {
                    Employee empObj = (Employee)emp;
                    System.out.println(empObj);
                }
            }catch(IOException e) {
                e.printStackTrace();
            }    
        }
    }
    
    // javabean, 用来封装数据
    class Employee implements Serializable{
        private 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;
        }
        @Override
        public String toString() {
            return "Employee [name=" + name + ", salary=" + salary + "]";
        }
        
    }
    commonsIO 使用方法

    遍历文件夹等, 很多可以直接使用.

    工作中更多的使用这种成品工具, 像类似上边的自己实现, 不是很多机会.

  • 相关阅读:
    setMonth 疑问
    asp.net数据格式的Format DataFormatString (备忘录)
    在日常维护中,如何实现Microsoft Lync Server 2010自动启用和同步Active Directory 域服务中所有用户帐户的信息?
    关于聊天记录的管理与查询
    DBImpExp.exe工具
    用户的批量处理
    设计模式 学习笔记(3)装饰模式、代理模式
    设计模式 学习笔记(1)简单工厂模式、策略模式
    设计模式 学习笔记(5)迪米特法则、外观模式、建造者模式
    设计模式 学习笔记(2)单一职责原则、开放封闭原则、依赖倒转原则
  • 原文地址:https://www.cnblogs.com/moveofgod/p/12447138.html
Copyright © 2011-2022 走看看