精华内容
下载资源
问答
  • Java IO流详解

    2019-08-28 09:34:03
    Java IO流详解

    Java IO流详解

    展开全文
  • java IO流详解

    2016-08-15 13:41:23
    java IO流详解

    首先先看一张图简单了解一下:

    一、概念
     
    Java中对文件的操作是以流的方式进行的。流是Java内存中的一组有序数据序列。Java将数据从源(文件、内存、键盘、网络)读入到内存中,形成了流,然后将这些流还可以写到另外的目的地(文件、内存、控制台、网络),之所以称为流,是因为这个数据序列在不同时刻所操作的是源的不同部分。
     
    二、分类
     
    流的分类,Java的流分类比较丰富,刚接触的人看了后会感觉很晕。流分类的方式很多:
     
    1、按照输入的方向分,输入流和输出流,输入输出的参照对象是Java程序。
     
    2、按照处理数据的单位不同分,字节流和字符流,字节流读取的最小单位是一个字节(1byte=8bit),而字符流一次可以读取一个字符(1char = 2byte = 16bit)。
     
    3、按照功能的不同分,分节点流和处理流,节点流是直接从一个源读写数据的流(这个流没有经过包装和修饰),处理流是在对节点流封装的基础上的一种流,FileInputStream是一个接点流,可以直接从文件读取数据,但是BufferedInputStream可以包装FileInputStream,使得其有缓冲功能。
     
    其实除了以上三种分类外,还有一些常常听到的一些分类比如:对象流、缓冲流、压缩流、文件流等等。其实都是节点流和处理流的子分类。当然你也可以创建新的流类型,只要你需要。
     
    三、流分类的关系
     
    不管流的分类是多么的丰富和复杂,其根源来自于四个基本的类。这个四个类的关系如下:
     
    字节流
    字符流
    输入流
    InputStream
    Reader
    输出流
    OutputStream
    Writer
     
     
    四、字节流和字符流的相互转换
     
    1、从字节流到字符流:InputStreamReader、OutputStreamWriter类可以实现。
     
    2、从字符流到字节流:可以从字符流中获取char[]数组,转换为String,然后调用String的API函数getBytes() 获取到byte[],然后就可以通过ByteArrayInputStream、ByteArrayOutputStream来实现到字节流的转换。
     
     
    以上知识是学习Java流的根基,对流的操作非常的容易,Java API中提供了丰富的流处理类,API也大差不差,看看文档即可上手。

    展开全文
  • JAVAIO流详解

    千次阅读 2018-09-10 16:24:21
    JavaIO流根据数据传输特性将流抽象成为各种类,组成了JAVAIO类框架。  根据传输数据的类型,分为字节流和字符流,根据流向的不同分为输入流和输出流。  以下是JAVAIO流框架:    InputStream、OutSteam和 ...

       流的本质是一组有顺序,有起点有终点的数据的集合,是对数据传输的抽象 。JavaIO流根据数据传输特性将流抽象成为各种类,组成了JAVAIO类框架。

      根据传输数据的类型,分为字节流和字符流,根据流向的不同分为输入流和输出流。

      以下是JAVAIO流框架:

     

      InputStream、OutSteam和 Reader 和Writer是两组抽象接口,分别代表了输入字节流、输出字节流和输入字符流和输出字符流。

     字节流和字符流的区别:

          (1) 读写单位不同。字节流读写数据按字节为单位读取,字符流读写数据按字符为单位读取,根据码表映射字符,一次可以多去多个字节。

           (2)读写对象不同。字节流可以读取任意数据包含视频、图片。字符流只能读取文本数据。

            (3)字节流在读取时本身不会使用缓冲区,但字符流是会用到缓冲区的,通过缓冲区来操作文件。

    InputStream 是所有输入字节流的父类,ByteArrayInputSream、StringBufferInputStream、FileInputStream分别从内存,硬盘文件等不同数据源实现了对输入流的封装,FilterOutStream及其子类和ObjectInputStream是典型的装饰流,为输入流增加了 读取缓冲区、读取基本数据类型和对象反序列化等功能。OutStream是所有输出字节类的父类,对应的每一个字节输入流都会有一个字节输出流与之对应。

    PipedInputStream 和PipedOutStream用于线程间的管道通信。管道输入流PipedInputStream 和 管道输出流 PipedOutputStream 互相关联。可以通过构造连接也可以通过共有的connect()方法连接。支持同一个进程下两个线程间的通信,传递的是字节数据。

    PubshBackInputstream 运行用户将读取到的数据重新回退到缓存区中再次读取,其构造函数可以限定缓冲器的大小,即最大可以回退的数据长度

    Reader是所有输入字符流的父类,BufferedReader,StringReader和FileReader分别从内存,硬盘文件等不同数据源实现了对输入流的封装,FilterReader及其子类是典型的装饰流,为输入流增加回退的功能。同样每一个输入字符流都有一个输出字符流与之对应,PipedReader/PipedWriter用于线程间的通信。不同的,InputStreanReader和OutStreamWriter用于将字节流转换为字符流。

    常见的流的使用:

    FileReader / FileWriter 用于文件的读写

    RandomAccessFile 随机文件访问类,可以一定程度上随机读取写入文件数据,以字节的方式

    BufferedInputstream/BufferedOutputStream BufferedReader/BufferedWriter 内置缓存,可以一次性读取写入多个数据,提高读取写入效率

    sequenceInputstream 合并流 允许将多个输入流合并被一个输入流,合并后的流将从第一个流开始输入,直达最后一个合并的流结束输入。

    PrintWriter 打印流,用于输出文本信息到控制台或文件

    可使用System.setIn () System.setOut() System,setErr()替换系统标准输入输出为其他的流

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • JavaIO流详解

    万次阅读 多人点赞 2018-08-09 10:20:58
    转载:... Java输入、输入、IO流 类层次关系梳理 本文主要关注在Java编程中涉及到的IO相关的类库、方法。以及对各个层次(抽线、接口继承)的流之间的关系进行梳理   相关学习资料 ...h...

    转载:https://www.cnblogs.com/LittleHann/p/3678685.html

    Java输入、输入、IO流 类层次关系梳理

    本文主要关注在Java编程中涉及到的IO相关的类库、方法。以及对各个层次(抽线、接口继承)的流之间的关系进行梳理

     

    相关学习资料

    复制代码

    http://baike.baidu.com/view/1007958.htm?noadapt=1
    http://blog.csdn.net/hguisu/article/details/7418161
    https://www.ibm.com/developerworks/cn/java/j-lo-javaio/
    http://docs.oracle.com/javase/7/docs/api/
    http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/java/io/package-tree.html
    http://tutorials.jenkov.com/java-io/index.html

    复制代码

     

    目录

    1. Java中IO简介
    2. Java中的流
    3. Java中和IO相关的类库层次结构

     

    1. Java中IO简介

    IO(Input And Output)在编程中是一个很常见的需求,IO即意味着我们的java程序需要和"外部"进行通信,这个"外部"可以是很多介质

    1) 本地磁盘文件、远程磁盘文件
    2) 数据库连接
    3) TCP、UDP、HTTP网络通信
    4) 进程间通信
    5) 硬件设备(键盘、串口等)
    ...

    2. Java中的流

    IO是我们的目的,而要达到这一目的,我们需要一种机制来帮助我们完全,这种机制就是"流"、或者叫"数据流"。

    数据流是一串连续不断的数据的集合,就象水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流。数据写入程序可以是一段、一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。对数据读取程序来说,看不到数据流在写入时的分段情况,每次可以读取其中的任意长度的数据,但只能先读取前面的数据后,再读取后面的数据。不管写入时是将数据分多次写入,还是作为一个整体一次写入,读取时的效果都是完全一样的。

    Java的IO模型设计非常优秀,它使用Decorator模式,按功能划分Stream

    记住这句话对我们在编程中选择合适的类库很重要,Java中按照功能提供不同类别的流,我们接下来深入学习一下java中的各个流、以及它们的层次结构关系

     

    3. Java中和IO相关的类库层次结构

    首先,java中所有的对象(包括)流对象都从Object 超类继承而来,所以,所有的流类的父类都是Object类

    以下的缩进关闭表示的的类的继承关系

    复制代码

    Object(超类)
    1. 基于"字节"操作的 I/O 接口:
        1) InputStream
        InputStream类是一个abstract class(抽象父类),它不能被直接用于实例化进行流操作,我们在编程中使用的是它的子类
            1.1) ByteArrayInputStream: 从字节数组(byte[])中进行以字节为单位的读取
            1.2) FileInputStream: 从文件中进行以字节为单位的读取
                1.2.1) SocketInputStream
                org.apache.commons.net.io.SocketInputStream: 封装了对Socket的字节型流式读取
            1.3) FilterInputStream: 用来"封装其它的输入流,并为它们提供额外的功能"
                1.3.1) InflaterInputStream 
                java.util.zip.InflaterInputStream: 从压缩数据源(zip)中以字节为单位读取数据
                    1.3.1.1) ZipInputStream 
                    java.util.zip.ZipInputStream: 从zip文件中以字节为单位读取数据
                1.3.2) BufferedInputStream: 开辟"内部字节数组"对输入流进行缓存,函数的返回也是一个字节数组
                1.3.3) DataInputStream:
                DataInputStream 是用来装饰其它输入流,它"允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型"。应用程序可以使用DataOutputStream(数据输出流)
           写入由DataInputStream(数据输入流)读取的数据。
            1.4) ObjectInputStream: 从输入流中读取序列化后的数据,并进行反序列化(deserializes)
            1.5) PipedInputStream: 从管道中读取数据
        2) OutputStream
        OutputStream类是一个abstract class(抽象父类),它不能被直接用于实例化进行流操作,我们在编程中使用的是它的子类
            2.1) ByteArrayOutputStream: 以字节为单位将数据写入到从字节数组(byte[])中 
            2.2) FileOutputStream: 以字节为单位将数据写入到文件中
                2.2.1) SocketOutputStream
                org.apache.commons.net.io.SocketOutputStream: 封装了对Socket的字节型流式写入
            2.3) FilterOutputStream: 用来"封装其它的输出流,并为它们提供额外的功能"
                2.3.1) ZipOutputStream: java.util.zip.ZipOutputStream: 以字节为单位向zip文件写入数据
                2.3.2) PrintStream: 
                PrintStream 是用来装饰其它输出流。它能为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式
                2.3.3) DataOutputStream:
                DataOutputStream 是用来装饰其它输入流,它"允许应用程序以与机器无关方式向底层输出流中写入基本 Java 数据类型"。应用程序可以使用DataInputStream(数据输入流)
           写入由DataOutputStream(数据输出流)写入的数据()。有点类似管道、或者进程间通信的感觉
           2.3.4) BufferedInputStream: 
            2.4) ObjectOutputStream: 对数据进行序列化(serializes),并向输出流中写入序列化后的数据
            2.5) PipedOutputStream: 向管道中写入数据
    2. 基于"字符"操作的 I/O 接口
    不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符,所以 I/O 操作的都是字节而不是字符,为了操作方便,java封装了一个直接写字符的 I/O 接口,这里就涉及到java的流机制
    中的一个很重要的概念,包装(装饰)。即所有的流操作在底层实现都是字节流的形式,以这个底层字节流为基础,在其上封装了各种"附加功能"(缓存、字符、管道..)
        1) Reader
        Reader类是一个abstract class(抽象父类),它不能被直接用于实例化进行流操作,我们在编程中使用的是它的子类
            1.1) InputStreamReader:
            我们知道,字符型的流接口是在字节型的流接口基础之上进行了一次封装,提供了一些额外的功能。所以,从名字上也可以看出来,InputStreamReader是字节流通向字符流的桥梁,     
         封裝了InputStream在里头, 它以较高级的方式,一次读取一个一个字符,以文本格式输入/输出,可以指定编码格式。
                1.1.1) FileReader: 提供对文本文件(保存字符的文件)进行以字符为单位的读取
            1.2) BufferedReader:
            BufferedReader会一次性从物理流中读取8k(默认数值,可以设置)字节内容到内存,如果外界有请求,就会到这里存取,如果内存里没有才到物理流里再去读。即使读,也是再8k
         而直接读物理流,是按字节来读。对物理流的每次读取,都有IO操作。IO操作是最耗费时间的。BufferedReader就是减少了大量IO操作,节省了时间
            1.3) CharArrayReader:
            CharArrayReader 是字符数组输入流。它和ByteArrayInputStream类似,只不过ByteArrayInputStream是字节数组输入流,而CharArray是字符数组输入流。
         CharArrayReader 是用于读取字符数组,它继承于Reader。操作的数据是以字符为单位
            1.4) FilterReader: 用来"封装其它的字符输入流,并为它们提供额外的功能"
            1.5) PipedReader: PipedReader 是字符管道输入流,它继承于Reader。
            1.6) StringReader: 以String作为数据源,进行以字符为单位的读取
          2) Writer
          Writer类是一个abstract class(抽象父类),它不能被直接用于实例化进行流操作,我们在编程中使用的是它的子类
            2.1) OutputStreamWriter:
                2.1.1) FileWriter: 提供对文本文件(保存字符的文件)进行以字符为单位的写入
            2.2) BufferedWriter
            2.3) StringWriter
            2.4) PipedWriter
            2.5) PrintWriter 
            2.6) CharArrayWriter
    3. 基于"磁盘"操作的 I/O 接口:
        1) File: (文件特征与管理): 用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等,它不负责数据的输入输出,而专门用来管理磁盘文件与目录
            1) public boolean exists( )        判断文件或目录是否存在
            2) public boolean isFile( )        判断是文件还是目录 
            3) public boolean isDirectory( )    判断是文件还是目录
            4) public String getName( )        返回文件名或目录名
            5) public String getPath( )        返回文件或目录的路径。
            6) public long length( )        获取文件的长度 
            7) public String[] list( )        将目录中所有文件名保存在字符串数组中返回  
            8) public boolean renameTo( File newFile );    重命名文件
            9) public void delete( );        删除文件
            10) public boolean mkdir( );        创建目录
    4. 基于网络操作的 I/O 接口:
        1) Socket

    复制代码

    以上是按照Java官方API文档列出的总的目录,我们接下来逐一学习一下它们的应用场景,因为输入、输出流在编程上具有对称性,所以我们把它们合并在一起学习

    0x1: InputStream: 字节输入流

    0x2: OutputStream: 字节输出流

    ByteArrayInputStream、ByteArrayOutputStream

    ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型数组的缓冲区,然后利用ByteArrayOutputStream和ByteArrayInputStream的实例向数组中写入或读出byte型数据。在网络传输中我们往往要传输很多变量,我们可以利用ByteArrayOutputStream把所有的变量收集到一起,然后一次性把数据发送出去

    复制代码

    import java.io.*; 
    
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            int a=0;
            int b=1;
            int c=2;
            /*
             * ByteArrayOutputStream() 
             * Creates a new byte array output stream.
            */
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            /*
             * write(int b) 
             * Writes the specified byte to this byte array output stream. 
            */
            bout.write(a);
            bout.write(b);
            bout.write(c);
            /*
             * toByteArray() 
             * Creates a newly allocated byte array. 
             * 返回内部保存的临时byte缓存数组
            */
            byte[] buff = bout.toByteArray();
            for(int i=0; i<buff.length; i++)
            {
                System.out.println(buff[i]);
            } 
            System.out.println("***********************");
            /*
             * ByteArrayInputStream(byte[] buf) 
             * Creates a ByteArrayInputStream so that it uses buf as its buffer array. 
            */
            ByteArrayInputStream bin = new ByteArrayInputStream(buff);
            /*
             * read() 
             * Reads the next byte of data from this input stream. 
            */
            while((b = bin.read()) != -1) 
            {
                System.out.println(b);
            }
        }
    }

    复制代码

    FileInputStream、FileOutputStream

    复制代码

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            File f = new File("C:\1.txt");         
            //向文件里写如"Hello"字符串.
            try    
            {
                //要写入的数据转换成字节数组
                byte[] buf = "Hello".getBytes();
                /*
                 * FileOutputStream(File file) 
                 * Creates a file output stream to write to the file represented by the specified File object. 
                 * 如果1.txt存在,则删除1.txt里面的内容,文本所有内容变为Hello
                 * 如果1.txt不存在,在新建1.txt文本,写入Hello
                */
                FileOutputStream out = new FileOutputStream(f);
                /*
                 * write(byte[] b) 
                 * Writes b.length bytes from the specified byte array to this file output stream. 
                */
                out.write(buf); 
                out.close();
            }
            catch(Exception e)    
            {
                System.out.println(e);
            }
             
            //读取文件中的内容 
            try    
            { 
                /*
                 * FileInputStream(File file) 
                 * Creates a FileInputStream by opening a connection to an actual file, the file named by the File object file in the file system. 
                */
                FileInputStream in = new FileInputStream(f); 
                byte[] buf = new byte[1024];   
                /*
                 * read(byte[] b) 
                 * Reads up to b.length bytes of data from this input stream into an array of bytes.  
                 * 从流中读取内容
                */
                int len = in.read(buf);         
                String str = new String(buf,0,len);
              //打印f文件的内容.
                System.out.println(str);            
            }
            catch(Exception e)    
            {
                System.out.println(e);
            }
        }
    }

    复制代码

    ZipInputStream、ZipOutputStream(包装流)

    复制代码

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
    import java.util.zip.ZipOutputStream;
    import java.io.FileOutputStream;
     
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            // 定义要压缩的文件
            File file = new File("C:" + File.separator + "in.txt");    
            // 定义压缩文件名称
            File zipFile = new File("C:" + File.separator + "in.zip"); 
            /*
             * FileInputStream(File file) 
             * Creates a FileInputStream by opening a connection to an actual file, the file named by the File object file in the file system.
             * 定义文件的输入流 
            */
            InputStream input = new FileInputStream(file);
            // 声明压缩流对象
            ZipOutputStream zipOut = null;    
            /*
             * ZipOutputStream(OutputStream out) 
             * Creates a new ZIP output stream.
             * 再次体现了Java的流函数架构中的"装饰器设计模式"的强大之处,我们可以根据我们对功能的
             * 需要任意组合、加载我们需要的流,用通俗的话来说,把它们层层包裹在一起
            */
            zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
            /*
             * putNextEntry(ZipEntry e) 
             * Begins writing a new ZIP file entry and positions the stream to the start of the entry data. 
             * 设置ZipEntry对象
            */
            zipOut.putNextEntry(new ZipEntry(file.getName()));     
            int temp = 0;
            /*
             * read() 
             * Reads a byte of data from this input stream. 
             * 从文件流中读取内容
            */
            while((temp = input.read()) != -1)
            {    
                // 压缩输出
                zipOut.write(temp);    
            }
            // 关闭输入流
            input.close();    
            // 关闭输出流
            zipOut.close();    
            
             
            // read zip file as input stream
            InputStream is= new FileInputStream("C:" + File.separator + "in.zip");
            //zip is read by ZipInputStream
            ZipInputStream zis= new ZipInputStream(is);
            // now write zip file in extracted file
            ZipEntry ze;
            byte[] buff = new byte[1024];
            /*
             * getNextEntry() 
             * Reads the next ZIP file entry and positions the stream at the beginning of the entry data. 
            */
            while((ze = zis.getNextEntry()) != null)
            {
                // get file name
                FileOutputStream fos= new FileOutputStream("C:" + File.separator + "out.txt");
                int l=0;
                // write buffer to file
                while((l = zis.read(buff)) > 0)
                {
                    fos.write(buff,0, l);
                }
            }
            zis.close();
        }
    }

    复制代码

    BufferedInputStream、BufferedInputStream(包装流)

    复制代码

    import java.io.*; 
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            File filein = new File("C:/1.png");
            File fileout = new File("C:/out.png");
            try 
            {
                //前面说过,File类它不负责数据的输入输出,而专门用来管理磁盘文件与目录
                if (fileout.exists() == false) 
                { 
                    fileout.createNewFile();
                }
                //要使用文件流,自然要使用文件读取流函数
                FileInputStream in = new FileInputStream(filein);
                FileOutputStream out = new FileOutputStream(fileout);
                byte[] b = new byte[1];
                //在文件流外面包一层缓冲流读取函数
                BufferedInputStream bin = new BufferedInputStream(in);
                BufferedOutputStream bout = new BufferedOutputStream(out);
                //缓存读取、缓存写入
                while (bin.read(b) != -1)
                {
                    bout.write(b);
                }
                bout.close();
                bin.close();
                out.close();
                in.close();
            } 
            catch (Exception e) 
            {
                  e.printStackTrace();
            }
        }
    }

    复制代码

    DataInputStream、DataOutputStream(包装流)

    复制代码

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
     
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            writeDemo();
            readDemo();
        }
        
        public static void readDemo() throws IOException 
        {
            DataInputStream dos = new DataInputStream(new FileInputStream("C:/in.txt"));
            String s = dos.readUTF();
            System.out.println(s);        
        }
    
        public static void writeDemo() throws IOException 
        {
            /*
             * DataOutputStream(OutputStream out) 
             * Creates a new data output stream to write data to the specified underlying output stream. 
            */
            DataOutputStream dos = new DataOutputStream(new FileOutputStream("C:/in.txt"));
            /*
             * writeUTF(String str) 
             * Writes a string to the underlying output stream using modified UTF-8 encoding in a machine-independent manner.
            */
            dos.writeUTF("你好啊");//UTF-8修改版         
        }
    }

    复制代码

    ObjectInputStream、ObjectOutputStream

    ObjectOutputStream可以把对象直接存入到文件中,然后利用ObjectInputStream读取文件还原成对象,前提是该对象实现了Serializable接口

    复制代码

    import java.io.EOFException;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
     
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            FileOutputStream fop = new FileOutputStream("C:/out.txt");
            /*
             * ObjectOutputStream(OutputStream out) 
             * Creates an ObjectOutputStream that writes to the specified OutputStream. 
            */
            ObjectOutputStream oos = new ObjectOutputStream(fop);
            People p = new People(1,"zhang");
            /*
             * writeObject(Object obj) 
             * Write the specified object to the ObjectOutputStream.
            */
            oos.writeObject(p);
            p = new People(2,"li");
            oos.writeObject(p);
            p = new People(3,"zhao");
            oos.writeObject(p);
            //写入三个对象
            oos.close();
            //关闭输出流
            FileInputStream fis=new FileInputStream("C:/out.txt");
            /*
             * ObjectInputStream(InputStream in) 
             * Creates an ObjectInputStream that reads from the specified InputStream.  
            */
            ObjectInputStream ois = new ObjectInputStream(fis);
            try 
            {
                while(true)
                {
                    /*
                     * readObject() 
                     * Read an object from the ObjectInputStream. 
                    */
                    People p2=(People)ois.readObject();
                    System.out.println(p2);
                }
                //没有办法判断文件中对象的数量,所以,只有通过EOFException异常来中断
                //或者在写入的时候把所有的对象都放到一个ArrayLis里,这样就不需要判断了
            } 
            catch (ClassNotFoundException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            catch(EOFException e)
            {
                System.out.println("读取结束");
            }
        } 
    }
    
    class People implements Serializable
    {
        //必须实现Serializable接口
        int id;
        String name;
        People(int id,String name)
        {
            this.id=id;
            this.name=name;
        }
      
        public String toString()
        {
            return "id:"+id+" name:"+name;
        }
     
    }

    复制代码

    PipedInputStream、PipedOutputStream

    管道流内部在实现时还有大量的对同步数据的处理。管道输出流和管道输入流执行时不能互相阻塞,所以一般要开启独立线程分别执行

    复制代码

    import java.io.*;  
     
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            /*
             * PipedInputStream() 
             * Creates a PipedInputStream so that it is not yet connected. 
            */
            PipedInputStream pin = new PipedInputStream();  
            PipedOutputStream pout = new PipedOutputStream();  
            /*
             * connect(PipedOutputStream src) 
             * Causes this piped input stream to be connected to the piped output stream src. 
             * 输入流与输出流连接  
            */
            pin.connect(pout); 
              
            ReadThread readTh   = new ReadThread(pin);  
            WriteThread writeTh = new WriteThread(pout);  
            new Thread(readTh).start();  
            new Thread(writeTh).start();  
        } 
        
        public static void sop(Object obj) //打印  
        {  
            System.out.println(obj);  
        }  
    }
     
    
    class ReadThread implements Runnable  
    {  
        private PipedInputStream pin;  
        ReadThread(PipedInputStream pin)   //  
        {  
            this.pin=pin;  
        }  
        
        //由于必须要覆盖run方法,所以这里不能抛,只能try 
        public void run()  
        {  
            try  
            {  
                sop("R:读取前没有数据,阻塞中...等待数据传过来再输出到控制台...");  
                byte[] buf = new byte[1024];  
                int len = pin.read(buf);  //read阻塞  
                sop("R:读取数据成功,阻塞解除...");  
            
                String s= new String(buf,0,len);  
                sop(s);    //将读取的数据流用字符串以字符串打印出来  
                pin.close();       
            }  
            catch(Exception e)  
            {  
                throw new RuntimeException("R:管道读取流失败!");  
            }     
        }  
        
        public static void sop(Object obj) //打印  
        {  
            System.out.println(obj);  
        }  
    }  
      
    class WriteThread implements Runnable  
    {  
        private PipedOutputStream pout;  
        WriteThread(PipedOutputStream pout)  
        {  
            this.pout=  pout;  
        }  
        
        public void run()  
        {  
            try  
            {  
                sop("W:开始将数据写入:但等个5秒让我们观察...");  
                Thread.sleep(5000);  //释放cpu执行权5秒  
                /*
                 * write(int b) 
                 * Writes the specified byte to the piped output stream. 
                 * 向管道写入数据,同时解除管道上的阻塞状态
                */
                pout.write("W: writePiped 数据...".getBytes());    
                pout.close();  
            }  
            catch(Exception e)  
            {  
                throw new RuntimeException("W:WriteThread写入失败...");  
            }  
        }  
        //打印 
        public static void sop(Object obj)  
        {  
            System.out.println(obj);  
        }  
    }  

    复制代码

    在了解了"字节型"流处理函数的应用场景后,我们接下来继续学习"字符型"流处理函数

    0x3: Reader: 字符输入流

    0x4: Writer: 字符输出流

    在开始学习"字符型"流处理函数的应用场景之前,我们必须牢记一个概念,Java的流函数的整体架构是"装饰器设计模式",也就是说,所有的流函数都可以按照所需的功能进行任意组合、互相嵌套、包裹。而我们的字符型流处理函数本质上也是对字节型流处理函数的一次包裹(或者说加载了字节型流处理函数的功能)

    另外数据持久化或网络传输都是以字节进行的,所以必须要有字符到字节或字节到字符的转化。字符到字节需要转化,其中读的转化过程如下图所示:

    InputStreamReader 类是字节到字符的转化桥梁,InputStream 到 Reader 的过程要指定编码字符集,否则将采用操作系统默认字符集,很可能会出现乱码问题。StreamDecoder 正是完成字节到字符的解码的实现类。

    写入也是类似的过程如下图所示

    通过 OutputStreamWriter 类完成,字符到字节的编码过程,由StreamEncoder完成编码过程

    InputStreamReader、OutputStreamReader

    复制代码

    import java.io.*;  
     
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            InputStream inputStream = new FileInputStream("C:/in.txt");
            /*
             * InputStreamReader(InputStream in) 
             * Creates an InputStreamReader that uses the default charset. 
             * 在字节型输入流之上包裹一层字符型输入流
            */
            Reader reader = new InputStreamReader(inputStream);
            /*
             * read() 
             * Reads a single character. 
            */
            int data = reader.read();
            while(data != -1)
            { 
                char theChar = (char) data;
                System.out.print(theChar);
                data = reader.read();
            } 
            reader.close(); 
            
            
            OutputStream outputStream = new FileOutputStream("C:/out.txt");
            /*
             * OutputStreamWriter(OutputStream out) 
             * Creates an OutputStreamWriter that uses the default character encoding. 
             * 在字节型输出流之上包裹一层字符型输出流
            */
            Writer writer = new OutputStreamWriter(outputStream);
            /*
             * write(String str, int off, int len) 
             * Writes a portion of a string. 
            */
            writer.write("Hello World");
    
            writer.close();
        }
    }
    

    复制代码

    从上面的代码我们可以看到,我们使用字节型的文件流读取文件,然后再在上面包裹一层字符型流读取函数。除此之外,还有另一种方法(严格来说不能算另一种方法,因为java的流函数架构是"装饰器设计模式",功能之间可以任意组装),直接之用字符型文件流读取(本质上来说,字符型文件流读取也是一些功能的组装)。

    FileReader、FileWriter

    复制代码

    import java.io.*;  
     
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            /*
             * FileReader(String fileName)
             * Creates a new FileReader, given the name of the file to read from. 
            */
            Reader reader = new FileReader("C:/in.txt"); 
            int data = reader.read();
            while(data != -1) 
            { 
                char theChar = (char) data;
                System.out.print(theChar);
                data = reader.read();
            }
            reader.close();
            
            
            Writer writer = new FileWriter("C:/out.txt"); 
            writer.write("Hello World"); 
            writer.close();
        }
    }
    

    复制代码

    BufferedReader、BufferedWriter

    和BufferedInputStream、BufferedOutputStream不同的是,BufferedReader、BufferedWriter提供了ReadLine、newLine()这种以行为单位的字符读写机制

     

    复制代码

    import java.io.*;  
     
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            /*
             * FileReader(String fileName)
             * Creates a new FileReader, given the name of the file to read from. 
            */
            Reader reader = new FileReader("C:/in.txt"); 
            /*
             * BufferedReader(Reader in) 
             * Creates a buffering character-input stream that uses a default-sized input buffer.
             * 在Reader之上再包一层Buffer缓冲区的功能 
            */
            BufferedReader brd = new BufferedReader(reader);
    
            String data = brd.readLine();
            while(data != null) 
            {  
                System.out.print(data);
                data = brd.readLine();
            }
            brd.close();
            reader.close(); 
            
            
            Writer writer = new FileWriter("C:/out.txt"); 
            /*
             * BufferedWriter(Writer out) 
             * Creates a buffered character-output stream that uses a default-sized output buffer. 
            */
            BufferedWriter bwd = new BufferedWriter(writer);
            /*
             * write(String s, int off, int len) 
             * Writes a portion of a String. 
            */
            bwd.write("Hello World");
            /*
             * newLine() 
             * Writes a line separator. 
            */
            bwd.newLine();
            bwd.close();
            writer.close(); 
        }
    }
    

    复制代码

     

    CharArrayReader、CharArrayWriter

     

    CharArrayReader 是字符数组输入流。它和ByteArrayInputStream类似,只不过ByteArrayInputStream是字节数组输入流,而CharArray是字符数组输入流。CharArrayReader 是用于读取字符数组,它继承于Reader。操作的数据是以字符为单位

    复制代码

    import java.io.*; 
    
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            char a = 'a';
            char b = 'b';
            char c = 'c'; 
            /*
             * CharArrayWriter() 
             * Creates a new CharArrayWriter. 
            */
            CharArrayWriter carrWrt = new CharArrayWriter();
            /*
             * write(int c) 
             * Writes a character to the buffer. 
            */
            carrWrt.write(a);
            carrWrt.write(b);
            carrWrt.write(c);
            /*
             * toCharArray() 
             * Returns a copy of the input data. 
            */
            char[] buff = carrWrt.toCharArray();
            for(int i = 0; i < buff.length; i++)
            {
                System.out.println(buff[i]);
            } 
            System.out.println("***********************");
            
            /*
             * CharArrayReader(char[] buf) 
             * Creates a CharArrayReader from the specified array of chars. 
            */
            CharArrayReader carrRed = new CharArrayReader(buff);
            /*
             * read() 
             * Reads the next byte of data from this input stream. 
            */
            int data;
            while((data = carrRed.read()) != -1) 
            {
                System.out.println(data);
            }
        }
    }

    复制代码

    FilterReader、FilterWriter

    用来"封装其它的字符输入流,并为它们提供额外的功能"

    PipedReader、PipedWriter

    字符管道流,原理上和PipedInputStream类似

    PrintWriter

    printwriter是向文本输出流打印对象的格式化表示形式,它允许以一种格式化的方式进行数据流的写入,类似C语言中的printf()函数

     

    复制代码

    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    public class circle
    {  
        public static void main(String[] args) throws Exception
        {
            String filename = "C:/out.txt";
            /*
             * PrintWriter(Writer out) 
             * Creates a new PrintWriter, without automatic line flushing.
            */
            PrintWriter pw = new PrintWriter(new FileWriter(filename)); 
            String[] words = new String[]{"hello", "world", "!"};
            
            for (int i = 0; i < words.length; i++) 
            {
                /*
                 * format(String format, Object... args) 
                 * Writes a formatted string to this writer using the specified format string and arguments.  
                */
                pw.format("words: %s\n", words[i]); 
            }
            /*
             * flush() 
             * Flushes the stream. 
            */
            pw.flush();
        }
    }

    复制代码

     

     

     

    0x5: File 文件、目录操作接口

    我们已经学习了关于流操作的各种函数接口,接下来我么继续学习File类,要明确的一点是,虽然这个类名是File类,但是这个类却不负责文件流的实际读写,在我本人看来,我更愿意叫它"文件元数据Meta操作接口"。而File类常常和文件流读写函数配合起来,进行文件的操作

    复制代码

    import java.io.*;
    
    public class circle 
    {
        public void FileOperate() 
        {
        }
    
        /**
         * 新建目录
         * @param folderPath String 如 c:/fqf
         * @return boolean
        */
        public void newFolder(String folderPath) 
        {
            try 
            {
                String filePath = folderPath;
                filePath = filePath.toString();
                java.io.File myFilePath = new java.io.File(filePath);
                if (!myFilePath.exists()) 
                {
                    myFilePath.mkdir();
                }
            }
            catch (Exception e) 
            {
                System.out.println("新建目录操作出错");
                e.printStackTrace();
            }    
        }
    
        /**
         * 新建文件
         * @param filePathAndName String 文件路径及名称 如c:/fqf.txt
         * @param fileContent String 文件内容
         * @return boolean
         */
        public void newFile(String filePathAndName, String fileContent) 
        { 
            try 
            {
                String filePath = filePathAndName;
                filePath = filePath.toString();
                File myFilePath = new File(filePath);
                if (!myFilePath.exists()) 
                {
                    myFilePath.createNewFile();
                }
                FileWriter resultFile = new FileWriter(myFilePath);
                PrintWriter myFile = new PrintWriter(resultFile);
                String strContent = fileContent;
                myFile.println(strContent);
                resultFile.close();
            }
            catch (Exception e) 
            {
                System.out.println("新建目录操作出错");
                e.printStackTrace(); 
            } 
        }
    
        /**
         * 删除文件
         * @param filePathAndName String 文件路径及名称 如c:/fqf.txt
         * @param fileContent String
         * @return boolean
         */
        public void delFile(String filePathAndName) 
        {
            try 
            {
                String filePath = filePathAndName;
                filePath = filePath.toString();
                java.io.File myDelFile = new java.io.File(filePath);
                myDelFile.delete(); 
            }
            catch (Exception e) 
            {
                System.out.println("删除文件操作出错");
                e.printStackTrace(); 
            } 
        }
    
        /**
         * 删除文件夹
         * @param filePathAndName String 文件夹路径及名称 如c:/fqf
         * @param fileContent String
         * @return boolean
         */
        public void delFolder(String folderPath) 
        {
            try 
            {
                delAllFile(folderPath); //删除完里面所有内容
                String filePath = folderPath;
                filePath = filePath.toString();
                java.io.File myFilePath = new java.io.File(filePath);
                myFilePath.delete(); //删除空文件夹 
            }
            catch (Exception e) 
            {
                System.out.println("删除文件夹操作出错");
                e.printStackTrace(); 
            } 
        }
    
        /**
         * 删除文件夹里面的所有文件
         * @param path String 文件夹路径 如 c:/fqf
        */
        public void delAllFile(String path) 
        {
            File file = new File(path);
            if (!file.exists()) 
            {
                return;
            }
            if (!file.isDirectory()) 
            {
                return;
            }
            String[] tempList = file.list();
            File temp = null;
            for (int i = 0; i < tempList.length; i++) 
            {
                if (path.endsWith(File.separator)) 
                {
                    temp = new File(path + tempList[i]);
                }
                else 
                {
                    temp = new File(path + File.separator + tempList[i]);
                }
                if (temp.isFile()) 
                {
                    temp.delete();
                }
                if (temp.isDirectory()) 
                {
                    delAllFile(path+"/"+ tempList[i]);//先删除文件夹里面的文件
                    delFolder(path+"/"+ tempList[i]);//再删除空文件夹
                }
            }
        }
    
        /**
         * 复制单个文件
         * @param oldPath String 原文件路径 如:c:/fqf.txt
         * @param newPath String 复制后路径 如:f:/fqf.txt
         * @return boolean
        */
        public void copyFile(String oldPath, String newPath) 
        {
            try 
            {
                int bytesum = 0;
                int byteread = 0;
                File oldfile = new File(oldPath);
                if (oldfile.exists()) 
                { //文件存在时
                    InputStream inStream = new FileInputStream(oldPath); //读入原文件
                    FileOutputStream fs = new FileOutputStream(newPath);
                    byte[] buffer = new byte[1444];
                    int length;
                    while ( (byteread = inStream.read(buffer)) != -1) 
                    {
                        bytesum += byteread; //字节数 文件大小
                        System.out.println(bytesum);
                        fs.write(buffer, 0, byteread);
                    }
                    inStream.close();
                }
            }
            catch (Exception e) 
            {
                System.out.println("复制单个文件操作出错");
                e.printStackTrace(); 
            } 
        }
    
        /**
         * 复制整个文件夹内容
         * @param oldPath String 原文件路径 如:c:/fqf
         * @param newPath String 复制后路径 如:f:/fqf/ff
         * @return boolean
        */
        public void copyFolder(String oldPath, String newPath)
        { 
            try 
            {
                (new File(newPath)).mkdirs(); //如果文件夹不存在 则建立新文件夹
                File a=new File(oldPath);
                String[] file=a.list();
                File temp=null;
                for (int i = 0; i < file.length; i++) 
                {
                    if(oldPath.endsWith(File.separator))
                    {
                        temp=new File(oldPath+file[i]);
                    }
                    else
                    {
                        temp=new File(oldPath+File.separator+file[i]);
                    } 
                    if(temp.isFile())
                    {
                        FileInputStream input = new FileInputStream(temp);
                        FileOutputStream output = new FileOutputStream(newPath + "/" + (temp.getName()).toString());
                        byte[] b = new byte[1024 * 5];
                        int len;
                        while ( (len = input.read(b)) != -1) 
                        {
                            output.write(b, 0, len);
                        }
                        output.flush();
                        output.close();
                        input.close();
                    }
                    if(temp.isDirectory())
                    {//如果是子文件夹
                        copyFolder(oldPath+"/"+file[i],newPath+"/"+file[i]);
                    }
                }
            }
            catch (Exception e) 
            {
                System.out.println("复制整个文件夹内容操作出错");
                e.printStackTrace(); 
            } 
        }
    
        /**
         * 移动文件到指定目录
         * @param oldPath String 如:c:/fqf.txt
         * @param newPath String 如:d:/fqf.txt
        */
        public void moveFile(String oldPath, String newPath) 
        {
            copyFile(oldPath, newPath);
            delFile(oldPath); 
        }
    
        /**
         * 移动文件到指定目录
         * @param oldPath String 如:c:/fqf.txt
         * @param newPath String 如:d:/fqf.txt
        */
         public void moveFolder(String oldPath, String newPath) 
         {
             copyFolder(oldPath, newPath);
             delFolder(oldPath); 
         }
    }

    复制代码

     

    4. 后记

    复制代码

    1. 什么时候改用什么流函数:
    我在学习Java的的API的时候第一个问自己的问题就是这个,在我看来,可以遵循以下两点:
      1) 明确我们的目的,例如需要读取文件,就使用文件流FileInputStream、需要缓存就包上一层BufferedInputStream、要进行字符型读取就使用InputStreamReader
      2) 理解"装饰器设计模式"的概念,我们需要的功能可以通过流函数之间的包裹来进行实现,在编程的时候,注意参考API文档,查明哪些流对象之间可以互相包裹很重要
    2. 对流函数的深入理解:
    Java的源代码是公开的,为了深入理解Java中的IO机制,下一步希望从源代码角度去深入研究一下Java中的IO、流、缓存机制,以及优化方案
    展开全文
  • Java IO流 详解

    2019-11-06 11:01:22
    IO流 IO介绍 编程语言的I/O类库中常使用流这个抽象概念,它代表任何有能力产出数据的数据源或者是有能力接收数据的接收端对象。(from Thinking in Java)。 本文从四个方面对IO流进行概述,并举出大量案例增加理解...
  • java io流详解

    2021-03-04 09:57:40
    java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关 File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出。 想要在Java程序中表示...
  • javaIO流详解

    2017-04-13 12:52:19
    学习Java IO,不得不提到的就是JavaIO流。 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,168
精华内容 867
关键字:

javaio流详解

java 订阅