• 流(41)


    节点流

    类型字符流字节流
    File文件FileReader、FileWriterFileInputStream、FileOutputStream
    内存数组CharArrayReader、 CharArrayWriterByteArrayInputStream、 ByteArrayOutputStream
    内存字串StringReader、 StringWriter
    管道PipedReader、 PipedWriterPipedInputStream、 PipedOutputStream

    文件节点流

    FileInputStream和FileOutputStream是文件字节流,是一种节点流

    文件字节输入流的构造方法:

    • FileInputStream(“文件名称”),如果文件不存在则FileNotFoundException

    • FileInputStream(File)

    文件字节输出流的构造方法:

    • FileOutputStream(“文件名称”) 如果文件不存在则新建文件,如果文件存在则覆盖文件内容

    • FileOutputStream(String name文件名称, boolean append是否采用追加方式

    FileReader和FileWriter类似

    FileInputStream和FileOutputStream两个类属于结点流,第一个类的源端和第二个类的目的端都是磁

    盘文件,它们的构造方法允许通过文件的路径名来构造相应的流。

    如:

    FileInputStream infile = new FileInputStream(“myfile.dat”);

    FileOutputStream outfile = new FileOutputStream(“results.dat”);

    要注意的是,构造FileInputStream, 对应的文件必须存在并且是可读的,而构造FileOutputStream时,

    如输出文件已存在,则必须是可覆盖的。

    内存数组节点

    如果文本则使用char[],如果二进制则使用byte[]

    构造器方法

    • CharArrayReader(char[] buf)其中char[]就是数据的来源,也就是说Reader就是从char[]中读取数据

    • CharArrayRead(char[] buf, int offset, int length)

    CharArrayWriter用于实现向一个字符数组中写入数据,这个数组可以自动调整大小

    ByteArrayInputStream、ByteArrayOutputStream和CharArrayReader以及CharArrayWriter类似,支持操作的内容不同而已,操作byte[]与char[]

    内存字串流

    StringReader用于从一个字串String中读取数据

    String str = "ta说:‘luv’"; 
    String Reader sr = new StringReader(str); 
    int cc; 
    while((cc=sr.read())!=-1) 
        System.out.print((char)cc); 
    sr.close();
    

    StringWriter用于给一个StringBuffer中写入数据,实现一个可边长的字串

    Scanner sc=new Scanner(System.in); 
    try(
        StringWriter sw=new StringWriter(); 
        Writer fw=new FileWriter("c:/console.txt") 
    ){ 
        String temp=sc.nextLine(); 
        while(!temp.equals("quit")){ 
            if(temp!=null && temp.trim().length()>0) 
                sw.write(temp+"\n"); 
            temp=sc.nextLine(); 
        }
        fw.write(sw.toString()); 
    }
    

    总结

    • 读写文件使用节点流FileInputStream/FileOutputStream和FileReader/FileWriter,如果操作文本文件,建议使用FileReader/FileWriter,如果操作二进制文件建议使用FileInputStream/FileOutputStream
    • 需要建立缓冲区(建立临时文件的方式效率低),可以考虑使用内存节点,例如CharArrayReader/CharArrayWriter、StringReader/StringWriter和ByteArrayInputStream/ByteArrayOutputStream
    • 如果需要一个二进制缓冲区可以使用ByteArrayInputStream/ByteArrayOutputStream,如果需要一个字符缓存可以使用CharArrayReader/CharArrayWriter、StringReader/StringWriter
    • 如果数据量不是特别大使用CharArrayReader/CharArrayWriter更为方便,如果数据量大而且可能需要直接操作缓冲区则使用StringReader/StringWriter
    • StringWriter中提供了方法getBuffer():StringBuffer

    过滤流类型

    过滤流就是在节点流的基础上附加功能

    处理类型字符流字节流
    缓存BufferedReader、BufferedWriterBufferedInputStream、BufferedOutputStream
    过滤处理FilterReader、FilterWriterFilterInputStream、FilterOutputStream
    桥接处理InputStreamReader、 OutputStreamWriter
    对象序列化处理ObjectInputStream、 ObjectOutputStream
    数据转换DataInputStream、DataOutputStream
    行数统计LineNumberReaderLineNumberInputStream
    回滚处理PushbackReaderPushbackInputStream
    打印功能PrintWriterPrintStream

    过滤流

    就是decorate模式中的抽象装饰角色

    FilterInputStream/FilterOutputStream和FilterReader/FilterWriter

    public class FilterInputStream extends InputStream { //典型的装饰模式 
        protected volatile InputStream in; //被装饰目标 
        protected FilterInputStream(InputStream in) { //通过构造器组装被装饰对象 
            this.in = in; 
        }
        public int read() throws IOException {//调用Filter中的read方法时实际操作是由 被装饰对象实现的 
            return in.read(); 
        } 
    }
    

    所谓的过滤流实际上就是类似上面的加密处理,在输入之后(后置处理,被装饰对象先执行)或者输出之前(前置处理,先处理然后被装饰对象执行)进行一下额外的处理,最终实际操作是调用被装饰对象的方法完成工作,依靠这种装饰模式实现在节点流的基础上附加额外功能.当然也允许多个过滤流嵌套从而达到功能累加的目的

    FilterInputStream实际上就是一个装饰抽象角色

    桥接转换流

    InputStreamReader和OutputStreamWriter是java.io包中用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介:从字节输入流读入字节,并按编码规范转换为字符;往字节输出流写字符时先将字符按编码规范转换为字节。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字节方式表示的流转换为特定平台上的字符表示。

    转换流可以在构造时指定其编码字符集

    • InputStreamReader用于将一个InputStream类型的输入流自动转换为Reader字符流

    • OutputStreamWriter用于将一个Writer字符输出流转换为OutputStream字节输出流

    InputStreamReader构造器

    • InputStreamReader(InputStream)

    • InputStreamReader(InputStream, String)

    • InputStreamReader(InputStream, Charset)

    • InputStreamReader(InputStream, CharsetDecorder)

    Reader r=new InputStreamReader(System.in); 
    int kk=r.read(); //例如输入的是“中国”,这里实际读取的是"中" 
    
    //因为这里读取的是一个字节,所以输入"中国",实际读取的是"中"的一个字节,输出显示为? 
    kk=System.in.read(); 
    System.out.println("输入的是:"+(char)kk);
    
    InputSteram is=new InputStreamReader(System.in,”iso8859-1);
    
    Reader r=new InputStreamReader(System.in, "gbk"); 
    int kk=r.read(); //例如输入的是"中国",实际读取的是"中" 
    System.out.println("输入的是:"+(char)kk);
    

    注意:一般不建议自行设置编码字符集,除非是必须的

    缓冲流

    缓冲流是套接在响应的节点流之上,对续写的数据提供缓冲的功能,提高读写的效率,同时增加了一些新方法

    以介质是硬盘为例,字节流和字符流的弊端:在每一次读写的时候,都会访问硬盘。 如果读写的频率比较高的时候,其性能表现不佳。为了解决以上弊端,采用缓存流。

    缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中读取。

    构造方法

    • BufferedReader(Reader)不定义缓存大小,默认8192
    • BufferedReader(Reader in, int size)size为自定义缓冲区的大小
    • BufferedWriter(Writer)
    • BufferedWriter(Writer out, int size)size为自定义缓冲区的大小
    • BufferedInputStream(InputStream)
    • BufferedInputStream(InputStream in, int size)size为自定义缓冲区的大小
    • BufferedOutputStream(OutputStream)
    • BufferedOutputStream(OuputStream out, int size)size为自定义缓冲区的大小

    缓冲输入流的方法

    BuffedReader提供了一个方法readLine():String,但是BufferedInputStream中并没有这个

    • BufferedReader提供了readLine方法用于读取一行字符串,以\r或\n分割(换行符)

      • 如果读取内容为null,则表示读取到了流的末尾
      • readLine方法会自动剔除本行内容末尾的换行符
    • BufferedWriter提供了newLine方法用于写入一个行分隔符

    对于输出的缓冲流,写入的数据会先在内存中缓存,使用flush方法会使内存中的数据立即写出

    键盘录入

    System.in:InputStream用于指代系统默认的输入设备—键盘

    方法read():int 可以实现代码执行到这里则会阻塞等待,只要输入数据为止

    强调

    使用缓存流并没有添加什么额外方法,只是它能够在执行过程中自动引入缓存,从而提高执行效

    过滤流使用必须有对应的节点流,因为过滤流是装饰节点流,不是有具体的操作目标

    new BufferedReader(new FileReader(…))或new BufferedWriter(new FileWriter())实际上使用的还是Reader/Writer那些方法,这里从编码的角度上说,没有任何区别,但是从执行性能上说,比FileReader/Writer效率高,可以减少磁盘的读写次数

    执行close方法会自动关闭被装饰的对象,所以不需要再关闭FileReader和FileWriter

    执行flush会自动刷新数据到节点流上,但是并没有执行关闭流。针对输出流关闭时会自动先flush缓存再执行关闭

    数据流

    DataInputStream和DataOutputStream两个类创建的对象分别被称为数据输入流和数据输出流。这是很有用的两个流,它们允许程序按与机器无关的风格读写Java数据。所以比较适合于网络上的数据传输。这两个流也是过滤器流,常以其它流如InputStream或OutputStream作为它们的输入或输出

    DataInputStram和DataOutputStream分别继承自InputStream和OuputStream,属于过滤流,需要分别套接在InputStream和OutputStream类型的节点流上

    • 只有字节流,没有对应的字符流

    DataInputStream和DataOutputStream提供了可以存取与机器无关的Java原始类型数据的方法

    DataInputSteram和DataOutputStream构造方法为

    • DataInputStream(InputStream)

    • DataOutputStream(OutputStream)

    打印流

    PrintStream和PrintWriter都属于输出流,分别针对字节和字符

    PrintWriter和PrintStream都提供了重载的print和println方法用于输出多种类型数据

    print(Object):void

    • 输出引用类型,实际上是调用对象的toString方法转换为String进行输出

    println表示输出后自动换行

    • PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息

    • PrintWriter和PrintStream有自动的flush功能 textOut.flushBuffer();

    PrintWriter(Writer)

    PrintWriter(Writer out, boolean autoFlush)自动刷新----println

    对象流

    使用DataInputStream或者DataOutputStream可以读写对象数据,但是操作比较繁琐

    SUN提供了ObjectInputStream/ObjectOutputStream可以直接将Object写入或读出

    这里实际上还有针对8种简单类型及其包装类的操作方法,以及针对String类型的操作方法

    • readObject():Object

    • writeObject(Object):void

    读写一个对象的前提是这个类型的对象是可以被序列化的;

    • NotSerializableException

    对象序列化【简单来说就是将对象可以直接转换为二进制数据流】/对象的反序列化【可以将二进制数据流转换为对象】,这一般依靠JVM实现,编程中只做声明对象序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象。对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,通过网络将这种二进制流传输到另一个网络节点,其他程序一旦获取到这种二进制流,都可以将这种二进制流恢复成原来的Java对象

  • 相关阅读:
    Pytorch中的广播机制
    函数栈简述
    STM32F407串口助手无法识别到串口
    FreeRTOS的学习(三)—— 信号量之二值信号量
    uvm中的config机制方法总结(二)
    剑指offer——JZ84 二叉树中和为某一值的路径(三) 解题思路与具体代码【C++】
    使用 Tesseract 在 C# 中进行光学字符识别(OCR)
    中断上下文和进程上下文
    DSPE-PEG-Thiol DSPE-PEG-SH 磷脂-聚乙二醇-巯基脂质体制备用
    量子计算:未来技术的变革与应用
  • 原文地址:https://blog.csdn.net/miao_6426/article/details/127053609