io流_io流与socket中的io流区别 - CSDN
io流 订阅
流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出 [1]  。 展开全文
流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出 [1]  。
信息
中文名
输入输出流
外文名
Input Output Stream
领    域
计算机编程
编程语言
C++
表现形式
内部表示和外部表示
定    义
以流的方式进行输入输出
IO流概念
输入输出(IO)与流的概念输入输出(IO)是指计算机同任何外部设备之间的数据传递。常见的输入输出设备有文件、键盘、打印机、屏幕等。数据可以按记录(或称数据块)的方式传递,也可以 流的方式传递 [1]  。所谓记录,是指有着内部结构的数据块。记录内部除了有需要处理的实际数据之外,还可能包含附加信息,这些附加信息通常是对本记录数据的描述。C++IO流,特指以流的方式进行输入输出的ISO/ANSI标准C++库的输入输出类库,也就是专门负责处理IO操作的一套系统。任何需要传递的数据,都要经过这套系统的处理 [1]  。
收起全文
  • Java 常用IO流操作详解

    2019-07-03 15:00:03
    IO流大家肯定不陌生,简单整理了一下常用IO流基本用法,其他的IO流以后有时间在整理。 1.基本概念IO:Java对数据的操作是通过流的方式,IO流用来处理设备之间的数据传输,上传文件和下载文件,Java用于操作流的...

    IO流大家肯定不陌生,简单整理了一下常用IO流基本用法,其他的IO流还有很多以后有时间在整理。
    这里写图片描述

    1.基本概念

    IO:Java对数据的操作是通过流的方式,IO流用来处理设备之间的数据传输,上传文件和下载文件,Java用于操作流的对象都在IO包中。

    2.IO流的分类

    图示:(主要IO流)
    这里写图片描述

    3.字节流

    (1).字节流基类

    1).InputStream

    InputStream:字节输入流基类,抽象类是表示字节输入流的所有类的超类。

     常用方法:
    
     	// 从输入流中读取数据的下一个字节
    	abstract int read()
    	// 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b中
    	int read(byte[] b)
    	// 将输入流中最多 len 个数据字节读入 byte 数组
    	int read(byte[] b, int off, int len)
    	
    	// 跳过和丢弃此输入流中数据的 n个字节
    	long skip(long n)
    
    	// 关闭此输入流并释放与该流关联的所有系统资源
    	void close()
    

    2).OutputStream

    OutputStream:字节输出流基类,抽象类是表示输出字节流的所有类的超类。

     常用方法:
     	// 将 b.length 个字节从指定的 byte 数组写入此输出流
    	void write(byte[] b)
    	// 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流
    	void write(byte[] b, int off, int len)
    	// 将指定的字节写入此输出流
    	abstract void write(int b)
    
    	// 关闭此输出流并释放与此流有关的所有系统资源
    	void close()
    	
    	// 刷新此输出流并强制写出所有缓冲的输出字节
    	void flush()
    

    (2).字节文件操作流

    1).FileInputStream

    FileInputStream:字节文件输入流,从文件系统中的某个文件中获得输入字节,用于读取诸如图像数据之类的原始字节流。

     构造方法:
     	// 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的File对象file指定
        FileInputStream(File file)
    	// 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的路径name指定
    	FileInputStream(String name)
     
     常用方法:覆盖和重写了父类的的常用方法。
    
    	    // 读取f盘下该文件f://hell/test.txt
    		//构造方法1
    		InputStream inputStream = new FileInputStream(new File("f://hello//test.txt"));
    		int i = 0;
    		//一次读取一个字节
    		while ((i = inputStream.read()) != -1) {
    			
    			// System.out.print(i + " ");// 65 66 67 68
    			//为什么会输出65 66 67 68?因为字符在底层存储的时候就是存储的数值。即字符对应的ASCII码。
    			System.out.print((char) i + " ");// A B C D
    		}
    		//关闭IO流
    		inputStream.close();
    
    	    // 读取f盘下该文件f://hell/test.txt
    		//构造方法2
    		InputStream inputStream2 = new FileInputStream("f://hello/test.txt");
    		// 字节数组
    		byte[] b = new byte[2];
    		int i2 = 0;
    		//  一次读取一个字节数组
    		while ((i2 = inputStream2.read(b)) != -1) {
                
    			System.out.print(new String(b, 0, i2) + " ");// AB CD
    		}
    		//关闭IO流
    		inputStream2.close();
    

    注: 一次读取一个字节数组,提高了操作效率,IO流使用完毕一定要关闭。

    2).FileOutputStream

    FileOutputStream:字节文件输出流是用于将数据写入到File,从程序中写入到其他位置。

     构造方法:
     	// 创建一个向指定File对象表示的文件中写入数据的文件输出流
    	FileOutputStream(File file)
    	// 创建一个向指定File对象表示的文件中写入数据的文件输出流
    	FileOutputStream(File file, boolean append)
    	// 创建一个向具有指定名称的文件中写入数据的输出文件流
    	FileOutputStream(String name)
    	// 创建一个向具有指定name的文件中写入数据的输出文件流
    	FileOutputStream(String name, boolean append)
     
     常用方法:覆盖和重写了父类的的常用方法。
    
    	    OutputStream outputStream = new FileOutputStream(new File("test.txt"));
    		// 写出数据
    		outputStream.write("ABCD".getBytes());
    		// 关闭IO流
    		outputStream.close();
    
    		// 内容追加写入
    		OutputStream outputStream2 = new FileOutputStream("test.txt", true);
    		// 输出换行符
    		outputStream2.write("\r\n".getBytes());
    		// 输出追加内容
    		outputStream2.write("hello".getBytes());
    		// 关闭IO流
    		outputStream2.close();
    

    注;输出的目的地文件不存在,则会自动创建,不指定盘符的话,默认创建在项目目录下;输出换行符时一定要写\r\n不能只写\n,因为不同文本编辑器对换行符的识别存在差异性。

    (3).字节缓冲流(高效流)

    1).BufferedInputStream

    BufferedInputStream:字节缓冲输入流,提高了读取效率。

    	 构造方法:
    	 // 创建一个 BufferedInputStream并保存其参数,即输入流in,以便将来使用。
    	 BufferedInputStream(InputStream in)
    	 // 创建具有指定缓冲区大小的 BufferedInputStream并保存其参数,即输入流in以便将来使用
    	 BufferedInputStream(InputStream in, int size)
    
    	    InputStream in = new FileInputStream("test.txt");
    		// 字节缓存流
    		BufferedInputStream bis = new BufferedInputStream(in);
    		byte[] bs = new byte[20];
    		int len = 0;
    		while ((len = bis.read(bs)) != -1) {
    
    			System.out.print(new String(bs, 0, len));
    			// ABCD
    			// hello
    		}
    		// 关闭流
    		bis.close();
    

    2).BufferedOutputStream

    BufferedOutputStream:字节缓冲输出流,提高了写出效率。

    	 构造方法:
    	 // 创建一个新的缓冲输出流,以将数据写入指定的底层输出流
    	 BufferedOutputStream(OutputStream out)
    	 // 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流
    	 BufferedOutputStream(OutputStream out, int size)
    	 
    	 常用方法:
    	 // 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流
    	 void write(byte[] b, int off, int len)
    	 // 将指定的字节写入此缓冲的输出流
     	 void write(int b)
    	 // 刷新此缓冲的输出流
    	 void flush()
    
      	    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("test.txt", true));
    		// 输出换行符
    		bos.write("\r\n".getBytes());
    		// 输出内容
    		bos.write("Hello Android".getBytes());
    		// 刷新此缓冲的输出流
    		bos.flush();
    		// 关闭流
    		bos.close();
    

    4.字符流

    (1).字符流基类

    1).Reader

    Reader:读取字符流的抽象类.

      常用方法:
     	// 读取单个字符
    	int read()
    	// 将字符读入数组
    	int read(char[] cbuf)
    	// 将字符读入数组的某一部分
    	abstract int read(char[] cbuf, int off, int len)
    	// 跳过字符
    	long skip(long n)
    	
    	// 关闭该流并释放与之关联的所有资源
    	abstract void close()
    

    2).Writer

    Writer:写入字符流的抽象类.

     常用方法:
     	// 写入字符数组
    	 void write(char[] cbuf)
    	// 写入字符数组的某一部分
    	abstract void write(char[] cbuf, int off, int len)
    	// 写入单个字符
    	void write(int c)
    	// 写入字符串
    	void write(String str)
    	// 写入字符串的某一部分
    	void write(String str, int off, int len)
    
    	// 将指定字符添加到此 writer
    	Writer append(char c)
    	// 将指定字符序列添加到此 writer
    	Writer append(CharSequence csq)
    	// 将指定字符序列的子序列添加到此 writer.Appendable
    	Writer append(CharSequence csq, int start, int end)
    
    	// 关闭此流,但要先刷新它
    	abstract void close()
    	// 刷新该流的缓冲
    	abstract void flush()
    

    (2).字符转换流

    1).InputStreamReader

    InputStreamReader:字节流转字符流,它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

     构造方法:
     	// 创建一个使用默认字符集的 InputStreamReader
    	InputStreamReader(InputStream in)
    	// 创建使用给定字符集的 InputStreamReader
    	InputStreamReader(InputStream in, Charset cs)
    	// 创建使用给定字符集解码器的 InputStreamReader
    	InputStreamReader(InputStream in, CharsetDecoder dec)
    	// 创建使用指定字符集的 InputStreamReader
    	InputStreamReader(InputStream in, String charsetName)
     特有方法:
        //返回此流使用的字符编码的名称 
        String getEncoding() 
    
            //使用默认编码		
    		InputStreamReader reader = new InputStreamReader(new FileInputStream("test.txt"));
    		int len;
    		while ((len = reader.read()) != -1) {
    			System.out.print((char) len);//爱生活,爱Android
    	
    		}
    		reader.close();
    		
    		 //指定编码	
    		InputStreamReader reader = new InputStreamReader(new FileInputStream("test.txt"),"utf-8");
    		int len;
    		while ((len = reader.read()) != -1) {
    			System.out.print((char) len);//????????Android
    		}
    		reader.close();
    

    注:Eclipse默认使用GBK编码,test.txt文件所以是GBK编码,当指定utf-8编码时所以会乱码。

    2).OutputStreamWriter

    OutputStreamWriter:字节流转字符流。

     构造方法:
     	// 创建使用默认字符编码的 OutputStreamWriter
    	OutputStreamWriter(OutputStream out)
    	// 创建使用给定字符集的 OutputStreamWriter
    	OutputStreamWriter(OutputStream out, Charset cs)
    	// 创建使用给定字符集编码器的 OutputStreamWriter
    	OutputStreamWriter(OutputStream out, CharsetEncoder enc)
    	// 创建使用指定字符集的 OutputStreamWriter
    	OutputStreamWriter(OutputStream out, String charsetName)
     特有方法:
        //返回此流使用的字符编码的名称 
        String getEncoding() 
    

    (3).字符缓冲流(高效流)

    1).BufferedReader

    BufferedReader:字符缓冲流,从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

     构造方法:
        // 创建一个使用默认大小输入缓冲区的缓冲字符输入流
    	BufferedReader(Reader in)
    	// 创建一个使用指定大小输入缓冲区的缓冲字符输入流
    	BufferedReader(Reader in, int sz)
     特有方法:
        // 读取一个文本行
    	String readLine()
    
    		//生成字符缓冲流对象
    		BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("test.txt")));
    		String str;
    		//一次性读取一行
    		while ((str = reader.readLine()) != null) {
    			System.out.println(str);// 爱生活,爱Android
    		}
    
    		//关闭流
    		reader.close();
    

    2).BufferedWriter

    BufferedWriter:字符缓冲流,将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

     构造方法:
     	// 创建一个使用默认大小输出缓冲区的缓冲字符输出流
    	BufferedWriter(Writer out)
    	// 创建一个使用给定大小输出缓冲区的新缓冲字符输出流
    	BufferedWriter(Writer out, int sz)
     特有方法:
     	// 写入一个行分隔符
    	void newLine() 
    

    (4).FileReader、FileWriter

     FileReader:InputStreamReader类的直接子类,用来读取字符文件的便捷类,使用默认字符编码。
     FileWriter:OutputStreamWriter类的直接子类,用来写入字符文件的便捷类,使用默认字符编码。
    

    #5.高效流效率比对
    读取f盘下的一个视频文件到项目中:文件大小29.5 MB

    读取方式一:

            FileInputStream inputStream = new FileInputStream("f://滑板//HEEL_FLIP.mp4");
    		FileOutputStream outputStream = new FileOutputStream("HEEL_FLIP.mp4");
    		int len;
    		// 开始时间
    		long begin = System.currentTimeMillis();
    		// 一次读取一个字节
    		while ((len = inputStream.read()) != -1) {
    			outputStream.write(len);
    		}
    		// 用时毫秒
    		System.out.println(System.currentTimeMillis() - begin);// 213195
            //关闭流释放资源
    		inputStream.close();
    		outputStream.close();
    

    读取方式二:

            FileInputStream inputStream = new FileInputStream("f://滑板//HEEL_FLIP.mp4");
    		FileOutputStream outputStream = new FileOutputStream("HEEL_FLIP.mp4");
    		int len;
    		byte[] bs = new byte[1024];
    		// 开始时间
    		long begin = System.currentTimeMillis();
    		// 一次读取一个字节数组
    		while ((len = inputStream.read(bs)) != -1) {
    			outputStream.write(bs, 0, len);
    		}
    		// 用时毫秒
    		System.out.println(System.currentTimeMillis() - begin);// 281
    
    		inputStream.close();
    		outputStream.close();
    

    读取方式三:

            FileInputStream inputStream = new FileInputStream("f://滑板//HEEL_FLIP.mp4");
    		BufferedInputStream bis = new BufferedInputStream(inputStream);
    		FileOutputStream outputStream = new FileOutputStream("HEEL_FLIP.mp4");
    		BufferedOutputStream bos = new BufferedOutputStream(outputStream);
    		int len;
    		byte[] bs = new byte[1024];
    		// 开始时间
    		long begin = System.currentTimeMillis();
    		while ((len = bis.read(bs)) != -1) {
    			bos.write(bs, 0, len);
    		}
    		// 用时毫秒
    		System.out.println(System.currentTimeMillis() - begin);// 78
    
    		bis.close();
    		bos.close();
    

    注:由此可以看出高效缓冲流读写速度是非常快的,建议使用。

    更多方法查看API

    展开全文
  • 本课程是《Java初级至应用》系统课程的第三模块,全套课程精细讲解,课程超过其他机构30%的课程量,经过我们全套课程系统学习的同学,可轻松从事Java工程师或系统架构师岗位,课程提供全套代码笔记其它相关素材及...
  • IO流详细总结

    2018-08-31 18:28:44
    一、IO流简介: 流的定义:流是指一连串流动的字符,是以先进先出方式发送信息的通道。 按流向分:输出流:OutputStream和Writer为基类  输入流:InputStream和Reader为基类 按处理数据单元划分:字节流:字节...

     

    一、IO流简介:

    流的定义:流是指一连串流动的字符,是以先进先出方式发送信息的通道。

    按流向分:输出流:OutputStream和Writer为基类

                    输入流:InputStream和Reader为基类

    按处理数据单元划分:字节流:字节输入流:InputStream基类

                                                    字节输出流:OutputStream基类

                                      字符流:字符输入流:Reader基类

                                       字节输出流:Writer基类

    (字节流是 8 位通用字节流,字符流是16位Unicode字符流)

     

    1.1 InputStream

    引入相关的类:InputStream ins =null;

    构建输入流,例如FileInputStream:

    ins =new FileInputStream(new File(path));

    操控字节输入流的,所用的方法也是针对字节的。

    常用方法:

     

    返回值类型  

    方法名

    方法简介

    abstract int read( ) 从此输入流中读取下一个字节(此方法是抽象方法,子类必须实现该方法。
    int read(byte [ ] b ) 从输入流中读取一定数量的字节,存储在参数指定的字节数组中。
    int read(byte [ ] b ,int off ,int len ) 读到 len字节从输入流读入字节数组数据。
    long skip( long n ) 跳过并丢弃 n字节从输入流中的数据。
    int available( ) 返回此输入流下一个方法可以读取的字节数。
    void close( ) 关闭流。

     

    案例:

    使用缓冲数组的方法读取文件内容,提高效率

     

    public static void readArr() {

                            // 1、明确源数据源

                            File f = new File("F:/1/余文佳/1.txt");

                            // 2、构建流的对象

                            InputStream ins = null;

                            try {

                                        ins = new FileInputStream(f);

                                        // 3、声明缓冲数组

                                        int i;// 表示读取了多少个字符到数组中

                                        byte[] bt = new byte[5];// 字节缓冲数组

                                        // 4、读取数据到数组中

                                        //可以读多少写多少,转化成char类型,但是文件中都是英文,如果有中文则输出乱码

                                        while ((i = (ins.read(bt))) != -1) {

                                                    for (int j = 0; j < i; j++) {

                                                                System.out.print((char) bt[j]);

                                                    }

                                        }

                            } catch (Exception e) {

                                        e.printStackTrace();

                            } finally {

                                 //关闭流

                                        try {

                                                    if (ins != null) {

                                                                ins.close();

                                                    }

                                        } catch (Exception e) {

                                                    e.printStackTrace();

                                        }

                            }

                }

     

    tips:

    关于InputStream.read(byte[] b)和InputStream.read(byte[] b,int off,int len)这两个方法都是用来从流里读取多个字节的,有经验的程序员就会发现,这两个方法经常 读取不到自己想要读取的个数的字节。比如第一个方法,程序员往往希望程序能读取到b.length个字节,而实际情况是,系统往往读取不了这么多。仔细阅读Java的API说明就发现了,这个方法 并不保证能读取这么多个字节,它只能保证最多读取这么多个字节(最少1个)。因此,如果要让程序读取count个字节,最好用以下代码:

     

    byte[] b = new byte[count];

    int readCount = 0; // 已经成功读取的字节的个数

    while (readCount < count) {

    readCount += in.read(bytes, readCount, count - readCount);

    }

     

    用这段代码可以保证读取count个字节,除非中途遇到IO异常或者到了数据流的结尾(EOFException)

     

    1.2 OutputStream

    常用方法:

     

    返回值类型

    方法名

    方法简介

    void flush( ) 刷新输出流,是缓存数据被写出来
    void write(byte [ ] b) 写b.length 字节从指定的字节数组的输出流
    void write(byte [ ] b, int off, int len) 写len字节从字节数组数据中到输入流
    abstract int write( int b ) 将指定的字节写入该输出流中
    void close( ) 关闭流

     

    1.1.1  FileInputStream

     

        FileInputStream是读取原始字节的图像数据流。读取字符流,考虑使用FileReader。

    常用方法:

    见InputStream中的方法

     

    构建输入流:(准备工作)

     

    FIle file =new File(path);

    InputStream ins =null;

    ins =new FileInputStream; //这里需要try catch

     

    读取文件字符:

     

    int i =0;

    while( ( i=ins.read( ) ) != -1){

               System.out.println( i );

      }  //输出的是自动转化的ASCII值,此处会抛出  IOException,需要try catch

     

    或者提高效率,使用缓冲数组byte[ ] b,可读取英文文件,需要转化成char字符:

     

    int len =0;

    byte [ ]b=new byte [ 1024 ];//建立缓冲流数组

    while((len=ins.read( b ))!= -1){

             for( int j=0;j<len ;j++){

             System.out.println( (char) bt [ j ] );

         }

    } //中间嵌套for循环,读多少输出多少,中文不可用,会输出乱码-->此处会抛出  IOException,需要try catch

     

    完整案例

     

    package cn.pojo;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.InputStream;

    public class InputStreamDemo {

                public static void main(String[] args) {

                            readByte();

                            readArr();

                }

                /**

                 * 读取字节

                 */

                public static void readByte() {

                            // 1、明确源数据源

                            File f = new File("F:\\1\\余文佳\\1.txt");

                            // 2、构建输入流对象

                            InputStream ins = null;

                            try {

                                        ins = new FileInputStream(f);

                                        int i;

                                        // 3、 读取文件字符

                                        while ((i = ins.read()) != -1) {

                                                    System.out.println("i=" + i);// 输出为转化的ascii码值

                                        }

                            } catch (Exception e) {

                                        e.printStackTrace();

                            } finally {

                                        // 4、关闭资源

                                        if (ins != null) {

                                                    try {

                                                                ins.close();

                                                    } catch (Exception e) {

                                                                e.printStackTrace();

                                                    }

                                        }

                            }

                }

                // 2、使用缓冲数组的方法读取文件内容,提高效率

                public static void readArr() {

                            // 1、明确源数据源

                            File f = new File("F:/1/余文佳/1.txt");

                            // 2、构建流的对象

                            InputStream ins = null;

                            try {

                                        ins = new FileInputStream(f);

                                        // 3、声明缓冲数组

                                        int i;// 表示读取了多少个字符到数组中

                                        byte[] bt = new byte[5];// 字节缓冲数组

                                        // 4、读取数据到数组中

                                        while ((i = (ins.read(bt))) != -1) {

                                                    for (int j = 0; j < i; j++) {

                                                                System.out.print((char) bt[j]);

                                                    }

                                        }

                            } catch (Exception e) {

                                        e.printStackTrace();

                            } finally {

                                        //关闭流

                                        try {

                                                    if (ins != null) {

                                                                ins.close();

                                                    }

                                        } catch (Exception e) {

                                                    e.printStackTrace();

                                        }

                            }

                }

    }

     

     

    1.2.1  FileOutputStream

     

    是OutputSTream的子类,主要功能是从源文件写入资料至指定文件中

     

    构造方法:1、FileOutputStream( File file )// 创建“File对象”对应的“文件输入流”;默认“追加模式”是false,

                                             即“写到输出的流内容”不是以追加的方式添加到文件中。若要追加则为(File file, true);

                       2、FileOutputStream( String path ) // 创建“文件(路径为path)”对应的“文件输入流”; (若没有,自动系统调用方法创建)

                                                                                    默认“追加模式”是false,即“写到输出的流内容”不是以追加的方式添加到文件中。  若要追加则为(String path, true); 

     

    try {

                    // 构造方法1

                    File file = new File("E:/java47.txt");

                    FileOutputStream fos1 = new FileOutputStream(file);

                    // File file = new File("E:/java47.txt");

                    // FileOutputStream fos1 = new  FileOutputStream(file);

                    // 没有该文件会直接创建文件,但不能有多级目录,否则会报错,或者这只是个目录

                    // -->java.io.FileNotFoundException:E:\java\java48.txt (系统找不到指定的路径。)

                    // 构造方法2       

                    FileOutputStream fos2 = new FileOutputStream("E:/java/java48.txt");// 规则如上

               } catch (Exception e) {

                    e.printStackTrace();

               }

     

     

    常用方法:(同OutputStream)

    返回值类型

    方法名

    方法简介

    void flush( ) 刷新输出流,是缓存数据被写出来
    void write(byte [ ] b) 写b.length 字节从指定的字节数组的输出流
    void write(byte [ ] b, int off, int len) 写len字节从字节数组数据中到输入流
    abstract int write( int b ) 将指定的字节写入该输出流中
    void close( ) 关闭流

    应用主要步骤:1、构建字节输出流对象

                            2、写数据

                            3、关闭流

    案例:

     

    package cn.pojo;

     

    import java.io.File;

    import java.io.FileOutputStream;

    import java.io.OutputStream;

     

    /**

    * 字节输出流案例

    *

    * @author kuang

    *

    */

    public final class OutputStreamDemo {

     

            public static void main(String[] args) {

                    // 1、明确目标数据源

                    File f = new File("E:/java48/java48.txt");

                    // 判断文件是否存在,否则创建

                    if (!f.exists()) {

                        f.getParentFile().mkdirs();// 先创建目录

                        try {

                            f.createNewFile();// 再创建文件 此处需要处理异常,

                        } catch (Exception e) {

                            e.printStackTrace();

                        }

                    }

                    // 2、构建输出流对象(通过子类实例化父类的对象)

                    OutputStream outs = null ; // 首先准备好一个输出的对象

                    try {

                        outs = new FileOutputStream(f) ; // 构造方法 ,实例化,此处需要处理异常

                        // 执行写入文件的操作

                        String st = "java48班" ; // 创建字符串

                        byte[] bt = st.getBytes(); // 只能输出byte数组,所以将字符串变为byte数组

                                                               // 使用String st.getByte();方法

                        outs.write(bt); // 将内容输出,保存文件

                        outs.flush(); // 刷新输出流

                        System.out.println("写入成功!"); // 若(文件夹必须存在)没有文件,会创建文件然后写入;若文件已有相同内容,则直接覆盖

                    } catch (Exception e) {

                        e.printStackTrace();

                    } finally {

                            // 4、关闭资源

                            if (outs != null) { 

                            try {

                                outs.close(); // 此处也要处理异常

                            } catch (Exception e) {

                                e.printStackTrace();

                            }

                        }

                    }

            }

    }

     

    Test:用FileInputStream 和 FileOutputStream 实现文件的复制

     

    package cn.pojo;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileOutputStream;

    import java.io.InputStream;

    import java.io.OutputStream;

    public class Demo {

         // 检查文件是否存在,否则创建

         public static void checkFile(File file) {

               if (!file.exists()) {

                    file.getParentFile().mkdirs();// 创建多级目录

                    try {

                         file.createNewFile();// 创建文件,此处需要处理异常

                         System.out.println("创建文件成功!");

                    } catch (Exception e) {

                         e.printStackTrace();

                    }

               }

         }

         public static void main(String[] args) {

               // 明确源文件和目标文件

               File o = new File("E:/java48/java48.txt");// 源文件

               File t = new File("E:/java48/新建.txt");// 目标文件

               checkFile(t);// 这里仅仅检查了目标文件

               // 构建输入、输出流对象

               InputStream ins = null; // 输入的对象

               OutputStream outs = null; // 输出的对象

               // 进行实例化,需要处理异常

               try {

                    ins = new FileInputStream(o);// 源文件作为输入对象--->若要拼接后面加上true

                    outs = new FileOutputStream(t);// 目标文件作为输出对象--->若要拼接后面加上true

                    // 创建缓冲数组

                    byte[] b = new byte[1024];

                    int len = 0;

                    // 执行边读边写操作

                    while ((len = ins.read(b)) != -1) {

                         outs.write(b, 0, len);

                    }

                    // 刷新输出流

                    outs.flush();

                    // 至此复制成功

               } catch (Exception e) {

                    e.printStackTrace();

               } finally {

                    // 关闭流(先开的后关)

                    try {

                         if (outs != null) {// 为了避免空指针异常,进行判空

                               outs.close();

                         }

                         if (ins != null) {

                               ins.close();

                         }

                    } catch (Exception e) {

                         e.printStackTrace();

                    }

               }

         }

    }

     

     

    1.1.2  BufferedInputStream

     

    带缓冲区的输入流,默认缓冲区大小是8M,能够减少访问磁盘的次数,提高文件读取性能;

    是 FileInputStream 的子类。 实现了装饰设计模式!

    BufferedInputStream没有无参构造方法,它必须传入一个InputStream(一般是FileInputStream),来一起使用,以提高读写效率。

    构造方法:1、BufferInputStream(InputStream in)// 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

                                                                                           创建一个内部缓冲区数组并将其存储在 buf 中,该buf的大小默认为8192。

                       2、BufferedInputStream(InputStream in, int size) //创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

                                                                                                        创建一个长度为 size 的内部缓冲区数组并将其存储在 buf 中。

    常用方法

    返回值类型

    方法名

    方法简介

    abstract int read( ) 从此输入流中读取下一个字节(此方法是抽象方法,子类必须实现该方法。
    int read(byte [ ] b ) 从输入流中读取一定数量的字节,存储在参数指定的字节数组中。
    int read(byte [ ] b ,int off ,int len ) 读到 len字节从输入流读入字节数组数据。

     

     

     

     

    1.2.2   BufferedOutputStream

     

    带缓冲区的输出流,能够提高文件的写入效率。实现了装饰设计模式!

     

    BufferedOutputStream没有无参构造方法,它必须传入一个OutputStream(一般是FileOutputStream),来一起使用,以提高读写效率。

    构造方法:1、BufferOutputStream(OutputStream outs)// 创建一个 BufferedInputStream 并保存其参数,即输出流outs,将数据写入指定的基本输入流中。

                                                                                     

                       2、BufferedOutputStream(OutputStream outs, int size) //创建具有指定缓冲区大小的 BufferedOutputStream ,即输出流outs,将数据写入指定的基本输入流中 。

                                                                                                   

    常用方法

    返回值类型

    方法名

    方法简介

    void flush( ) 刷新输出流,是缓存数据被写出来
    void write(byte [ ] b) 写b.length 字节从指定的字节数组的输出流
    void write(byte [ ] b, int off, int len) 写len字节从字节数组数据中到输入流

    Test使用 BufferedInputStream 和 BufferedOutputStream 实现文件的复制

    (与上面的FileInputStream Test类似)

     

    tips:为什么要用BufferedInputStream 和 BufferedOutputStream?

    优点:效率高 

    缺点:内存占用多

    why?

            不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。

    带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多。

     

     

    1.1.3  DataInputStream

            数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。 DataInputStream 对于 多线程访问不一定是安全的。 线程安全是可选的,它由此类方法的使用者负责。

     

    构造方法:DataInputStream(InputStream in); 

     

    常用方法:

     

    返回值类型

    方法名

    方法简介

    int read(byte [ ]  b) 读取一定数量的字节从包含输入流并存入缓冲区阵列b
    int read (byte [ ]  b, int off, int len) 读到 len 从包含输入流读入字节数组数据字节
    boolean readBoolean( ) 读 true / false
    byte readByte( ) 读取并返回一个输入字节
    char readChar( ) 读取两个字节返回一个 char 价值
    float readFloat( ) 四字节读取输入并返回一个 float 价值
    double readDouble( ) 八字节读取输入并返回一个 double 价值
    int readInt( ) 四字节读取输入并返回一个 int 价值
    String readLine( ) 从输入流读取下一行文本
    short readShort( ) 两字节读取输入并返回一个 short 价值
    String readUTF( ) 读取一个字符串,一直采用 modified UTF-8 编码格式

     

    1.2.3  DataOutputStream

     

            数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。 DataInputStream 对于多线程访问不一定是安全的。 线程安全是可选的,它由此类方法的使用者负责。

     

    构造方法: DataOutputStream( OutputStream outs);

     

    常用方法:

     

     

    返回值类型

    方法名

    方法简介

    void flush( ) 刷新数据输出流
    int size( ) 返回柜台 written 电流值,这个数据写入输出流的字节数为止
    void write( int b ) 将指定的字节(论证b的低八位)的底层输出流
    void write( byte [ ] b, int off, int len ) 写 len 字节指定字节数组中的起始偏移量 off 当前输出流
    void writeBoolean( boolean v ) 写一个 boolean 当前输出流作为一个字节的值
    void writeByte( int v ) 写了 byte 当前输出流作为一个字节的值
    void writeBytes( String s ) 将字符串写入到基础的输出流作为字节序列
    void writeChar( int v ) 写一个char当前输出流作为一个双字节的值,高字节优先
    void writeChars( String s ) 将字符串写入底层输出流,作为一个字符序列
    void writeFloat( float v ) 将浮点型参数的 int使用 floatToIntBits方法在类 Float,然后写道, int值基本为4字节输出流量,高字节优先。
    void writeDouble( double v ) 将双参数到一个 long使用 doubleToLongBits方法在类 Double,然后写道, long值基本的输出流的字节的数量,高字节优先。
    void writeInt( int v ) 写一个 int当前输出流为四个字节,高字节优先。
    void writeShort( int v ) 写一个 short当前输出流的两个字节,高字节优先。
    void writeUTF( String str ) 一个字符串写入到输出流的潜在使用在一个机器无关的方式 modified UTF-8编码。

    案例 1:

     

     

    package cn.pojo;

     

    import java.io.DataInputStream;

    import java.io.DataOutputStream;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileOutputStream;

     

    //二进制流

    public class Demo2 {

     

        public static void main(String[] args) {

            // 1、指明目标和源

            File o = new File("temp/Hello.class");

            File t = new File("tmp/Hello.class");

            // 2、构建流对象

            DataInputStream dis = null;

            DataOutputStream dos = null;

            try {

                dis = new DataInputStream(new FileInputStream(o));

                dos = new DataOutputStream(new FileOutputStream(t));

                int i;

                // 3、读写流

                while ((i = dis.read()) != -1) {

                    dos.write(i);

                }

                dos.flush();

                System.out.println("操作成功!");

            } catch (Exception e) {

                e.printStackTrace();

            } finally {

                // 4、关闭流

                try {

                    if (dos != null) {

                        dos.close();

                    }

                    if (dis != null) {

                        dis.close();

                    }

                catch (Exception e) {

                    e.printStackTrace();

                }

            }

        }

    }

     

     

    案例 2:

    package cn.pojo;

    import java.io.DataInputStream;

    import java.io.DataOutputStream;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileOutputStream;

    import java.io.IOException;

    public class Demo {

         // 检查文件是否存在,否则创建

         public static void checkFile(File file) {

               if (!file.exists()) {

                    file.getParentFile().mkdirs();// 创建多级目录

                    try {

                         file.createNewFile();// 创建文件,此处需要处理异常

                         System.out.println("创建文件成功!");

                    } catch (Exception e) {

                         e.printStackTrace();

                    }

               }

         }

         // 明确源文件和目标文件

         public static void main(String[] args) throws IOException {

               myWrite();

               myReader();

         }

         private static void myWrite() throws IOException {

               // TODO Auto-generated method stub

               // 创建数据输出流对象

               File o = new File("E:/java48/111.txt");// 源文件

               File t = new File("E:/java48/新建111.txt");// 目标文件

               checkFile(o);

               checkFile(t);

               FileOutputStream fos = new FileOutputStream(o);

               DataOutputStream dos = new DataOutputStream(fos);

               // 写数据

               dos.writeByte(10);

               dos.writeShort(100);

               dos.writeInt(1000);

               dos.writeLong(10000);

               dos.writeFloat(12.34F);

               dos.writeDouble(12.56);

               dos.writeChar('a');

               dos.writeBoolean(true);

               // 释放资源

               dos.close();

         }

         private static void myReader() throws IOException {

               // TODO Auto-generated method stub

               // 创建数据输入流对象

               File o = new File("E:/java48/111.txt");// 源文件

               FileInputStream fis = new FileInputStream(o);

               DataInputStream dis = new DataInputStream(fis);

               // 读数据

               byte b = dis.readByte();

               short s = dis.readShort();

               int i = dis.readInt();

               long l = dis.readLong();

               float f = dis.readFloat();

               double d = dis.readDouble();

               char c = dis.readChar();

               boolean bl = dis.readBoolean();

               // 释放资源

               dis.close();

               System.out.println(b);

               System.out.println(s);

               System.out.println(i);

               System.out.println(l);

               System.out.println(f);

               System.out.println(d);

               System.out.println(c);

               System.out.println(bl);

         }

    }

     

    输出内容为:

    10

    100

    1000

    10000

    12.34

    12.56

    a

    true

     

     

    1.1.4  ObjectInputStream :对象输入流

     

    特点 : 可以从输入流中读取java对象,而不需要每次读取一个字节,需要把InputStream包装到ObjectInputStream中,就可以从中读取对象,对象必须实现序列化,对象类实现Serializable接口

    例:(实现序列化)

    public class Pet implements Serializable {

         private static final long serialVersionUID = 1L;

     }

     

    构造方法:1、ObjectInputStream( ) ;

                     2、ObjectInputStream( InputStream ins) ; 

                             

    例如:创建方式 1 :

               String path = "xx";// 路径和文件

               File file = new File(path);// 创建文件

               // 构建InputStream,然后ObjectInputStream

               InputStream ins = null;

               ObjectInputStream ois = null;

               try {

                    ins = new FileInputStream(file);// 这里需要处理异常

                    ois = new ObjectInputStream(ins);// 两层构造

               } catch (Exception e) {

                    e.printStackTrace();

               }

    创建方式2:

                        String path = "xx";// 路径和文件

               try {

                    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));// 多层构造,需要处理异常

               } catch (Exception e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

               }

     

     

    常用方法:

     

    返回值类型

    方法名

    方法简介

    void close( ) 关闭输入流
    int read( ) 读取一个字节的数据
    int read( byte [ ] b, int off, int len )  读入一个字节数组
    boolean readBoolean( ) 在布尔值中读取
    byte readByte( ) 读取一个8位字节
    char readChar( ) 读取一个16位字符
    double readDouble( )  
    float readFloat( )  
    int readInt( ) 读取一个32位的int
    String readLine( )   过时的
    Object readObject( ) 读取对象输入流中的对象
    String readUTF( ) 读modified UTF-8的格式字符串

     

     

    1.2.4  ObjectOutputStream :对象输出流

     

    特点: 能够让你把对象写入到输出流中,而不需要每次写入一个字节。你可以把OutputStream包装到ObjectOutputStream中,然后就可以把对象写入到该输出流中了

               对象必须实现序列化,对象类实现Serializable接口

    例:(实现序列化)

    public class Pet implements Serializable {

         private static final long serialVersionUID = 1L;

     }

     

    构造方法:   1、ObjectOutputStream( ) ;

                        2、ObjectOutputStream( OutputStream ins) ; 

     

    例如:创建方式 1 :

            String path = "xx";// 路径和文件

            File file = new File(path);// 创建文件

            // 构建OutputStream,然后ObjectOutputStream

            OutputStream outs = null;

            ObjectOutputStream oos = null;

            try {

               outs = new FileOutputStream(file);// 这里需要处理异常

               oos = new ObjectOutputStream(outs);// 两层构造:先用FileOutputSTream,再用ObjectOutputStream

            } catch (Exception e) {

                 e.printStackTrace();

            }

    创建方式2:

            String path = "xx";// 路径和文件

            try {

                 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));// 多层构造,需要处理异常

            } catch (Exception e) {

                 e.printStackTrace();

            }

     

    常用方法:

     

    返回值类型

    方法名

    方法简介

    void close( ) 关闭流
    void flush( ) 刷新流
    protect Object replaceObject( ) 这种方法将允许受信任的子类对象来代替一个物体对另一个序列化期间
    void write( byte [ ] b ) 写入一个字节数组
    void write( byte [ ] b, int off, int len ) 写入字节数组的字节数
    void write( int val ) 写一个字节
    void writeBoolean( boolean val ) 写一个布尔值
    void writeByte( byte val ) 写入一个8位字节
    void writeChar( int val ) 写入一个16位字符
    void writeInt( int val ) 写入一个32位长的int
    void writeObject( Object obj ) 写入指定对象的对象
    void writeUTF( String str ) 原始数据写在 modified UTF-8格式字符串

    ObjiectInputStream 和 ObjectOutputStream 案例:(创建一个宠物类,放入一个集合中,使用者两个类进行读写操作)

     

    package cn.pojo;

    import java.io.Serializable;

    //宠物类

    public class Pet implements Serializable {// 要实现序列化

         private static final long serialVersionUID = 514910705505845579L;

         private String id;// id编号

         private String name;// 昵称

         public Pet() {

         }

         public Pet(String id, String name) {

               this.id = id;

               this.name = name;

         }

         public String getId() {

               return id;

         }

         public void setId(String id) {

               this.id = id;

         }

         public String getName() {

               return name;

         }

         public void setName(String name) {

               this.name = name;

         }

         @Override

         public String toString() {

               return "Pet [id=" + id + ", name=" + name + "]";

         }

    }

     

     

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileOutputStream;

    import java.io.InputStream;

    import java.io.ObjectInputStream;

    import java.io.ObjectOutputStream;

    import java.io.OutputStream;

    import java.util.ArrayList;

    public class Demo3_Pet {

         public static void main(String[] args) {

               // 1、明确当前目标和源

               File o = new File("F:/temp/pet.txt");

               File t = new File("F:/temp/pet.txt");

               ArrayList<Pet> arr = new ArrayList<Pet>();

               Pet pet1 = new Pet("001", "小白");

               Pet pet2 = new Pet("002", "小绿");

               Pet pet3 = new Pet("003", "大黄");

               arr.add(pet1);

               arr.add(pet2);

               arr.add(pet3);

               // 2、构建流对象

               InputStream ins = null;

               OutputStream outs = null;

               ObjectInputStream ois = null;

               ObjectOutputStream oos = null;

               try {

                    outs = new FileOutputStream(o);

                    oos = new ObjectOutputStream(outs);

                    // 输出对象信息:序列化

                    oos.writeObject(arr);

                    oos.flush();

                    System.out.println("写出成功!");

                    // 读文件对象:反序列化

                    ins = new FileInputStream(o);

                    ois = new ObjectInputStream(ins);

                    Object ob = ois.readObject();

                    // 遍历输出集合中对象信息

                    if (ob instanceof ArrayList) {

                         @SuppressWarnings("unchecked")

                         ArrayList<Pet> li = (ArrayList<Pet>) ob;

                         for (Pet p : li) {

                               System.out.println(p);

                         }

                    }

               } catch (Exception e) {

                    e.printStackTrace();

               } finally {

                    // 关闭流------>这里与其他不同,先关闭InputStream的,再关闭OutputStream,(仅本总结中)

                    try {

                         if (ins != null) {

                               ins.close();

                         }

                         if (outs != null) {

                               outs.close();

                         }

                    } catch (Exception e) {

                         e.printStackTrace();

                    }

               }

         }

    }

     

    Tips:

            该对象首先要可序列化,然后把多个对象存储到容器里,如ArrayList<?> list; 

            然后把list序列化存储,然后再反序列化读文件,读出来就是一串对象了

     

     

    字符流:

     

    1、字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串。字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的。字符流操作的是缓冲区(当我们对文件进行读写操作时如果不调用close() 或 flush()方法时不能看到数据的变化)。

    2、字符输入流 Reader 基类

         字符输出流 Writer 基类

    3、Reader 和 Writer都是抽象类

     

     

    2.1.1  InputStreamReader

     

    特点:将字节输入流转换为字符输入流。是字节流通向字符流的桥梁,可以指定字节流转换为字符流的字符集。

     

    构造方法:1、InputStreamReader( InputStream ins) ; 创建一个默认字符集的 InputStreamReader

                       2、InputStreamReader( InputStream ins ,“ encoding”) ; 创建使用指定字符集的 InputStreamReader

     

     

    常用方法:

    返回值类型

    方法名

    方法简介

    void close( ) 关闭流
    String getEncoding( ) 返回此流使用的字符编码名称
    int read( ) 读取单个字符
    int read( char [ ] ch, int off, int len ) 将字符读入一个数组的一部分
    boolean ready( ) 告诉是否该流已准备好阅读

    读文件内容的常用三种方法:1、int  read()

     

             //public int read() throws IOException

             //读取单个字符。在字符可用、发生 I/O 错误或者已到达流的末尾前,此方法一直阻塞。

             public static void readOneStr() throws IOException{

                 InputStreamReader isr=new InputStreamReader(new FileInputStream("E:\\test\\javaIo\\1.txt"));

                 int ch=0;

                 while((ch=isr.read())!=-1){

                     System.out.print((char)ch);

                 }

                 isr.close();

            }

     

    2、int  read( char [ ]ch, int off, in len )

     

             //public int read(char[] cbuf) throws IOException

             //将字符读入数组。在某个输入可用、发生 I/O 错误或者已到达流的末尾前,此方法一直阻塞。

             public static void readOneStrArr() throws IOException{

                 InputStreamReader isr=new InputStreamReader(new FileInputStream("E:\\test\\javaIo\\1.txt"));

                 char [] ch=new char[1024];

                 int len=0;

                 while((len=isr.read(ch))!=-1){

                     System.out.print(new String(ch,0,len));

                 }

                 isr.close();

             }

     

    3、int read( char [ ] ch)

     

            //public int read(char[] cbuf) throws IOException

             //将字符读入数组的某一部分。在某个输入可用、发生 I/O 错误或者到达流的末尾前,此方法一直阻塞。

             public static void readOneStrArrLen() throws IOException{

                 InputStreamReader isr=new InputStreamReader(new FileInputStream("E:\\test\\javaIo\\1.txt"));

                 char [] ch=new char[1024];

                 int len=0;

                 while((len=isr.read(ch,0,ch.length))!=-1){

                     System.out.print(new String(ch,0,len));

                 }

                 isr.close();

             }

     

     

    2.2.1  OutputStreamWriter  

     

    特点:将字节输出流转为字符输出流,是字符流通向字节流的桥梁,可使用指定的 encoding 要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,

              否则将接受平台默认的字符集。

     

    构造方法:1、OutputStreamWriter(OutputStream outs) ; 创建使用默认字符编码的 OutputStreamWriter

                     2、 OutputStreamWriter(OutputStream outs , “ecoding”) ;  可以设置编码格式

     

    常用方法:

     

    返回值类型

    方法名

    方法简介

    void close( ) 关闭流
    void flush( ) 刷新流
    String getEcoding( ) 返回此流使用的字符编码格式名称
    void writer( int val ) 写入一个字符
    void writer( char [ ]ch, int off, int len ) 写入一个字符数组的一部分
    void writer( String str, int off, int len ) 写入字符串的一部分

    用OutputStreamWriter 将内存中的数据写入文件中有5种方式:

     

    1、 void   writer( int  val )

     

     //public void write(int c)throws IOException

     //写入单个字符。要写入的字符包含在给定整数值的 16 个低位中,16 高位被忽略。

             public static void writerOneChar() throws IOException{

                 OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("E:\\test\\javaIo\\1.txt"));

                 osw.write(97);//char ch=(char)97; 

                 osw.write('c');

                 osw.flush();

                 osw.close();

             }

     

    2、 void    writer( char [ ]ch )

     

     //public void write(char[] cbuf)throws IOException 写入字符数组。

             public static void writerCharArr() throws IOException{

                 OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("E:\\test\\javaIo\\1.txt"));

                 char [] ch=new char[]{'我','爱','中','国'};

                 osw.write(ch);

                 osw.flush();

                 osw.close();

             }

     

    3、 void    writer( char [ ]ch, int off, int len)

     

     //public abstract void write(char[] cbuf,int off,int len)throws IOException 写入字符数组的某一部分。

             public static void writerCharArrLen() throws IOException{

                 OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("E:\\test\\javaIo\\1.txt"));

                 char [] ch=new char[]{'我','爱','中','国'};

                 osw.write(ch,0,ch.length-1);

                 osw.flush();

                 osw.close();

             }

     

    4、 viod   writer( String str )

     

     //public void write(String str) throws IOException  写入字符串。

             public static void writerOneStr() throws IOException{

                 OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("E:\\test\\javaIo\\1.txt"));

                 osw.write("中国");

                 osw.flush();

                 osw.close();

             }

     

    5、 void   writer( String str, int off ,int len )

     

     //public void write(String str,int off, int len)throws IOException; 写入字符串的某一部分。

             public static void writerOneStrArrLen() throws IOException{

                 OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("E:\\test\\javaIo\\1.txt"));

                 String str="我爱中国";

                 osw.write(str,0,str.length()-2);

                 osw.flush();

                 osw.close();

             }

     

     

    包装流设置字符集的案例,使用InputStreamReader 和 OUtputStreamWriter:

     

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileOutputStream;

    import java.io.InputStream;

    import java.io.InputStreamReader;

    import java.io.OutputStream;

    import java.io.OutputStreamWriter;

    import java.util.Scanner;

    /**

     * 包装流设置字符集

     *

     * @author kuang

     *

     */

    public class homework_2 {

         public static void main(String[] args) {

               // 确定源和目标文件

               Scanner sc = new Scanner(System.in);

               File o = new File("kh/java48.template");

               File t = new File("kh/java48.txt");

               check(o);

               check(t);

               // 构建流对象

               InputStream ins = null;

               OutputStream outs = null;

               InputStreamReader insr = null;

               OutputStreamWriter outsw = null;

               try {

                    outs = new FileOutputStream(o);// 先做为目标文件写入内容

                    outsw = new OutputStreamWriter(outs, "UTF-8");//编码格式为UTF-8

                    System.out.println("输入你要写入的内容:");

                    String msg = sc.next();

                    // 写入内容

                    outsw.write(msg);

                    // 刷新

                    outsw.flush();

                    System.out.println("已经完全写入!");

                    ins = new FileInputStream(o);// 作为源文件

                    insr = new InputStreamReader(ins, "UTF-8");//编码格式为UTF-8

                    outs = new FileOutputStream(t);// 作为写入的目标文件

                    outsw = new OutputStreamWriter(outs, "UTF-8");//编码格式为UTF-8

                    char[] ch = new char[1024];

                    int i = 0;

                    // 执行边读边写

                    while ((i = insr.read(ch)) != -1) {

                         outsw.write(ch, 0, i);

                    }

                    // 刷新

                    outsw.flush();

               } catch (Exception e) {

                    e.printStackTrace();

               } finally {

                    // 关闭流

                    try {

                         if (outs != null) {

                               outs.close();

                         }

                         if (ins != null) {

                               ins.close();

                         }

                    } catch (Exception e) {

                         e.printStackTrace();

                    }

               }

         }

         public static void check(File file) {

               try {

                    if (!file.exists()) {

                         file.getParentFile().mkdirs();// 创建文件夹

                         file.createNewFile();// 创建文件

                         System.out.println("没有该文件!已创建成功!");

                    }

               } catch (Exception e) {

                    e.printStackTrace();

               }

         }

    }

     

    2.1.1.1  FileReader 

    2.2.1.1  FileWriter 

    与上面InputStreamReader 和 OutputStreamWriter没啥区别 ,不多说

     

    2.1.2  BufferedReader(缓冲流)

     

    特点:字节输入缓冲流,从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。BufferedReader 由Reader类扩展而来,提供通用的缓冲方式文本读取,而且提供了很实用的readLine。

     

    构造方法:1、BufferedReader( Reader in ) ; 创建一个使用默认大小输入缓冲区的缓冲字符输入流

                     2、BufferedReader( Reader in, int sz ) ; 创建一个使用指定大小的输入缓冲区的缓冲字符输入流

     

    常用方法:

    该类读取文本的方法就是父类Reader提供的read()系列方法(见2.1.1 InputStreamReader)。在这里仅介绍他自己特有的方法readLine() 

     

    返回值类型

    方法名

    方法简介

    String readLine( ) 读一行文本 --> 特有

    例:

     

    //public String readLine()throws IOException读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。

             public static void readLineTest() throws IOException{

                 BufferedReader br=new BufferedReader(new FileReader("E:\\test\\javaIo\\1.txt"));               

                 String str=null;

                 while((str=br.readLine())!=null){

                     System.out.println(str);

                 }

                 br.close();

             }

     

     

    2.2.2  BufferedWriter (缓冲流)

     

    特点:字节输出缓冲流,将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。 该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。

     

    构造方法:1、BufferedWriter( Writer out ) ;创建一个使用默认大小输出缓冲区的缓冲字符输出流

                     2、BufferedWriter( Writer out,  int sz ) ;创建一个新的缓冲字符输出流,该流使用给定大小的输出缓冲区。

     

    常用方法:

    该类写入文本的方法就是父类Writer提供的write()系列方法(见2.2.1 OutputStreamWriter),在这里仅介绍他特有的newLine( )方法。

     

    返回值类型

    方法名

    方法简介

    void newLine( ) 写行分隔符

    例:

     

      public static void newLineTest() throws IOException{

                       BufferedWriter bw=new BufferedWriter(new FileWriter("E:\\test\\javaIo\\2.txt"));

                       bw.write("爱我");

                       bw.newLine();

                       bw.write("中华");

                       bw.flush();

                       bw.close();

                   }

               //结果:(加入了换行符)

                 爱我

                 中华

     

    字符缓冲流 案例:(使用 BufferedReader 和 BufferedWriter)

     

    import java.io.BufferedReader;

    import java.io.BufferedWriter;

    import java.io.File;

    import java.io.FileReader;

    import java.io.FileWriter;

    import java.io.Reader;

    import java.io.Writer;

    /**

     * 字符缓冲流

     *

     * @author kuang

     *

     */

    public class Demo2 {

         public static void main(String[] args) {

               // 1、指明源和目标

               File o = new File("F:/temp/java48.template");

               File t = new File("F:/temp/java48.txt");

               // 2、构建流的对象

               Reader re = null;

               Writer wt = null;

               BufferedReader bfr = null;

               BufferedWriter bfw = null;

               try {

                    re = new FileReader(o);

                    bfr = new BufferedReader(re);

                    wt = new FileWriter(t);

                    bfw = new BufferedWriter(wt);

                    String msg = null;

                    // 读取操作

                    while ((msg = bfr.readLine()) != null) {// 读一行

                         // System.out.println(msg);

                         bfw.write(msg);

                         bfw.write("\r\n");// 执行换行,读一行 写一行 换行

                         // 或者 :bfw.newLine();//换行

                    }

                    bfw.flush();

               } catch (Exception e) {

                    e.printStackTrace();

               } finally {

                    // 关闭流

                    try {

                         if (wt != null) {// 为了避免空指针异常,进行判空

                               wt.close();

                         }

                         if (re != null) {

                               re.close();

                         }

                    } catch (Exception e) {

                         e.printStackTrace();

                    }

               }

         }

    }

     

             (= =!)

     

     

     

     

    最近整理出了有关大数据,微服务,分布式,Java,Python,Web前端,产品运营,交互等1.7G的学习资料,有视频教程,源码,课件,软件工具,面试题等等,这里将珍藏多年的资源免费分享给各位小伙伴们。

    领取方式:https://blog.csdn.net/qq_42914528/article/details/81777449                                      

                                                             

    欢迎大家关注我的公众号:

    里面会分享很多JAVA技术、新知识、新技术、面试宝典等。
    有让技术爱好者(程序猿)得到很大提升的文章资料。

    还在犹豫什么,赶紧关注一波,微信搜索公众号:程序员的成长之路。或者扫描下方二维码进行关注。

                                                                         

                                                                           欢迎关注公众号,和我一起成长!

     

     

    展开全文
  • java——IO流

    2020-06-06 09:25:37
    IO流 字符流 字节流 转换流
    展开全文
  • java IO流学习总结

    2019-03-15 11:46:16
    近期学习了Java的IO流,尝试着总结一下。 java.io 包下的IO流很多: 其中,以Stream结尾的为字节流,以Writer或者Reader结尾的为字符流。所有的输入流都是抽象类IuputStream(字节输入流)或者抽象类Reader...

    https://www.cnblogs.com/hopeyes/p/9736642.html

    近期学习了Java的IO流,尝试着总结一下。

    java.io 包下的IO流很多:

    其中,以Stream结尾的为字节流,以Writer或者Reader结尾的为字符流。所有的输入流都是抽象类IuputStream(字节输入流)或者抽象类Reader(字符输入流)的子类,所有的输出流都是抽象类OutputStream(字节输出流)或者抽象类Writer(字符输出流)的子类。字符流能实现的功能字节流都能实现,反之不一定。如:图片,视频等二进制文件,只能使用字节流读写。

     1、字符流FileReader和FileWriter

    FileReader类

    构造方法摘要
    FileReader(File file) 
              在给定从中读取数据的 File 的情况下创建一个新 FileReader。
    FileReader(FileDescriptor fd) 
              在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。
    FileReader(String fileName) 
              在给定从中读取数据的文件名的情况下创建一个新 FileReader。

     FileWriter类

    构造方法摘要
    FileWriter(File file) 
              根据给定的 File 对象构造一个 FileWriter 对象。
    FileWriter(File file, boolean append) 
              根据给定的 File 对象构造一个 FileWriter 对象。
    FileWriter(FileDescriptor fd) 
              构造与某个文件描述符相关联的 FileWriter 对象。
    FileWriter(String fileName) 
              根据给定的文件名构造一个 FileWriter 对象。
    FileWriter(String fileName, boolean append) 
              根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。

    使用FileReader和FileWriter类完成文本文件复制:

     CopyFile

    2、字符缓冲流BufferedReader和BufferedWriter

    字符缓冲流具备文本特有的表现形式,行操作

    public class BufferedReader extends Reader

    (1)从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

    (2)可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

    (3)通常,Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。例如,

     BufferedReader in
       = new BufferedReader(new FileReader("foo.in"));

    (4)将缓冲指定文件的输入。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。 

    public class BufferedWriter extends Writer

    (1)将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

    (2)可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

    (3)该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。并非所有平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。

    (4)通常 Writer 将其输出立即发送到底层字符或字节流。除非要求提示输出,否则建议用 BufferedWriter 包装所有其 write() 操作可能开销很高的 Writer(如 FileWriters 和 OutputStreamWriters)。例如,

     PrintWriter out
       = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
    

    (5)缓冲 PrintWriter 对文件的输出。如果没有缓冲,则每次调用 print() 方法会导致将字符转换为字节,然后立即写入到文件,而这是极其低效的。

     

     使用BufferedReader和BufferedWriter完成文件复制

     CopyFile2

    缓冲区的工作原理:1、使用了底层流对象从具体设备上获取数据,并将数据存储到缓冲区的数组内。2、通过缓冲区的read()方法从缓冲区获取具体的字符数据,这样就提高了效率。3、如果用read方法读取字符数据,并存储到另一个容器中,直到读取到了换行符时,将另一个容器临时存储的数据转成字符串返回,就形成了readLine()功能。

    3、字节流FileInputStream和FileOutputStream 

    public class FileInputStream extends InputStream

    (1)FileInputStream 从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。

    (2)FileInputStream 用于读取诸如图像数据之类的原始字节流。

    构造方法摘要
    FileInputStream(File file) 
              通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
    FileInputStream(FileDescriptor fdObj) 
              通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。
    FileInputStream(String name) 
              通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

    public class FileOutputStream extends OutputStream

    (1)文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。文件是否可用或能否可以被创建取决于基础平台。特别是某些平台一次只允许一个 FileOutputStream(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。(2) FileOutputStream 用于写入诸如图像数据之类的原始字节的流。

    构造方法摘要
    FileOutputStream(File file) 
              创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
    FileOutputStream(File file, boolean append) 
              创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
    FileOutputStream(FileDescriptor fdObj) 
              创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。
    FileOutputStream(String name) 
              创建一个向具有指定名称的文件中写入数据的输出文件流。
    FileOutputStream(String name, boolean append) 
              创建一个向具有指定 name 的文件中写入数据的输出文件流。

    例:使用字节流复制图片

    复制代码

     1 import java.io.FileInputStream;
     2 import java.io.FileOutputStream;
     3 import java.io.IOException;
     4 
     5 public class CopImg {
     6     public static void main(String[] args) throws IOException {
     7         FileInputStream fin=new FileInputStream("C:\\Users\\Administrator\\Desktop\\Img.jpg");
     8         FileOutputStream fout=new FileOutputStream("C:\\Users\\Administrator\\Desktop\\ImgCopy.jpg");
     9         int len=0;
    10         byte[] buff=new byte[1024];
    11         while((len=fin.read(buff))!=-1) {
    12             fout.write(buff, 0, len);
    13         }
    14         fin.close();
    15         fout.close();
    16     }
    17 }

    复制代码

    4、字节缓冲流BufferedInputStream和BufferedOutputStream

    public class BufferedInputStream extends FilterInputStream

    BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark 操作后读取的所有字节。

    public class BufferedOutputStream extends FilterOutputStream

    该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。

    例:使用字节缓冲流实现图片的复制

    复制代码

     1 import java.io.BufferedInputStream;
     2 import java.io.BufferedOutputStream;
     3 import java.io.FileInputStream;
     4 import java.io.FileOutputStream;
     5 import java.io.IOException;
     6 
     7 public class CopyImg {
     8     public static void main(String[] args) throws IOException {
     9         BufferedInputStream bfin=new BufferedInputStream(new FileInputStream("C:\\Users\\Administrator\\Desktop\\Img.jpg"));
    10         BufferedOutputStream bfout=new BufferedOutputStream(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\ImgCopybuff.jpg"));
    11         int len=0;
    12         byte[] buff=new byte[1024];
    13         while((len=bfin.read(buff))!=-1) {
    14             bfout.write(buff, 0, len);
    15         }
    16         bfin.close();
    17         bfout.close();
    18     }
    19 }

    复制代码

    5、转换流:InputStreamReader和OutputStreamWriter

    InputStreamReader和OutputStreamWriter是字符和字节的桥梁,也可称之为字符转换流。原理:字节流+编码。

    FileReader和FileWriter作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接使用子类完成操作,简化代码。

    一旦要指定其他编码时,不能使用子类,必须使用字符转换流。

     

    public class InputStreamReader extends Reader

    (1)InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

    (2)每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

    (3)为了达到最高效率,可以考虑在 BufferedReader 内包装 InputStreamReader。例如:

     BufferedReader in = new BufferedReader(new InputStreamReader(System.in));//重要

     InputStreamReaderDemo

    public class OutputStreamWriter extends Writer

    (1)OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

    (2)每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。注意,传递给 write() 方法的字符没有缓冲。

    (3)为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。例如:

    Writer out = new BufferedWriter(new OutputStreamWriter(System.out));//重要

    例如:利用标准输出流将文本输出到命令行

     OutputStreamWriterDemo

     TransStreamDemo

    6、打印流PrintWriter和PrintStream

    public class PrintWriter extends Writer

    (1)向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有 print 方法。不能输出字节,但是可以输出其他任意类型。

    (2)与 PrintStream 类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。

    (3)此类中的方法不会抛出 I/O 异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用checkError() 是否出现错误。 

    复制代码

     1 import java.io.FileWriter;
     2 import java.io.IOException;
     3 import java.io.PrintWriter;
     4 /**
     5  * 注意:创建FileWriter对象时boolean参数表示是否追加;
     6  *              而创建打印流对象时boolean参数表示是否自动刷新
     7  */
     8 public class PrintWriterDemo {
     9     public static void main(String[] args) throws IOException {
    10         //PrintWriter pw=new PrintWriter("print.txt");
    11         PrintWriter pw=new PrintWriter(new FileWriter("print.txt"),true);
    12         pw.write("测试打印流");
    13         pw.println("此句之后换行");
    14         pw.println("特有功能:自动换行和自动刷新");
    15         pw.println("利用构造器设置自动刷新");
    16         pw.close();
    17     }
    18 }

    复制代码

    使用字符打印流复制文本文件:

     PrintWriterDemo

    public class PrintStream extends FilterOutputStreamimplements Appendable, Closeable
    (1)PrintStream 为其他输出流添加了功能(增加了很多打印方法),使它们能够方便地打印各种数据值表示形式(例如:希望写一个整数,到目的地整数的表现形式不变。字节流的write方法只将一个整数的最低字节写入到目的地,比如写fos.write(97),到目的地(记事本打开文件)会变成字符'a',需要手动转换:fos.write(Integer.toString(97).getBytes());而采用PrintStream:ps.print(97),则可以保证数据的表现形式)。
    
    1 //PrintStream的print方法 
    2  public void print(int i) {
    3         write(String.valueOf(i));
    4  }
    (2)与其他输出流不同,PrintStream 永远不会抛出 IOException;而是,异常情况仅设置可通过 checkError 方法测试的内部标志。
    另外,为了自动刷新,可以创建一个 PrintStream;这意味着可在写入 byte 数组之后自动调用 flush 方法,可调用其中一个 println 方法,或写入一个换行符或字节 ('\n')。
    (3)PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。  
    使用字节打印流复制文本文件:
    

     PrintStreamDemo

    7、对象操作流ObjectInputStream和ObjectOutputStream

    public class ObjectOutputStream extends OutputStream implements ObjectOutput,ObjectStreamConstants

    (1)ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。只能使用 ObjectInputStream 读取(重构)对象。

    (2)只能将支持 java.io.Serializable 接口的对象写入流中。

    (3)writeObject 方法用于将对象写入流中。所有对象(包括 String 和数组)都可以通过 writeObject 写入。可将多个对象或基元写入流中。必须使用与写入对象时相同的类型和顺序从相应 ObjectInputstream 中读回对象。

    构造方法:ObjectOutputStream(OutputStream out)    创建写入指定 OutputStream 的 ObjectOutputStream。

    public class ObjectInputStream extends InputStream implements ObjectInput,ObjectStreamConstants

    (1)ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

    (2)只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流读取。

    (3)readObject 方法用于从流读取对象。应该使用 Java 的安全强制转换来获取所需的类型。在 Java 中,字符串和数组都是对象,所以在序列化期间将其视为对象。读取时,需要将其强制转换为期望的类型。 

    例:对象读写:

     Student

     ObjectOperate

     ObjectOperate2

    序列化接口Serializable的作用:没有方法,不需要覆写,是一个标记接口为了启动一个序列化功能。唯一的作用就是给每一个需要序列化的类都分配一个序列版本号,这个版本号和类相关联。在序列化时,会将这个序列号也一同保存在文件中,在反序列化时会读取这个序列号和本类的序列号进行匹配,如果不匹配会抛出java.io.InvalidClassException.

    注意:静态数据不会被序列化,因为静态数据在方法区,不在对象里。

    或者使用transient关键字修饰,也不会序列化。

    8、SequenceInputStream 

    表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

    案例:媒体文件切割与合并

    复制代码

     1 import java.io.File;
     2 import java.io.FileInputStream;
     3 import java.io.FileOutputStream;
     4 import java.io.IOException;
     5 import java.util.Properties;
     6 
     7 public class CutFile {
     8     /**
     9      * 将一个媒体文件切割成碎片
    10      * 思路:1、读取源文件,将源文件的数据分别复制到多个文件
    11      * 2、切割方式有两种:按照碎片个数切,或者按照指定大小切
    12      * 3、一个输入流对应多个输出流
    13      * 4、每个碎片都需要编号,顺序不能错
    14      * @throws IOException 
    15      */
    16     public static void main(String[] args) throws IOException {
    17         File srcFile=new File("C:\\Users\\Administrator\\Desktop\\Test\\img.jpg");
    18         File partsDir=new File("C:\\Users\\Administrator\\Desktop\\cutFiles");
    19         splitFile(srcFile,partsDir);
    20     
    21     }
    22     //切割文件
    23     private static void splitFile(File srcFile, File partsDir) throws IOException {
    24         if(!(srcFile.exists()&&srcFile.isFile())) {
    25             throw new RuntimeException("源文件不是正确文件或者不存在");
    26         }
    27         if(!partsDir.exists()) {
    28             partsDir.mkdirs();
    29         }
    30         FileInputStream fis=new FileInputStream(srcFile);
    31         FileOutputStream fos=null;
    32         
    33         byte[] buf=new byte[1024*60];
    34         
    35         int len=0;
    36         int count=1;
    37         while((len=fis.read(buf))!=-1) {
    38             //存储碎片文件
    39             fos=new FileOutputStream(new File(partsDir,(count++)+".part"));
    40             fos.write(buf, 0, len);
    41             fos.close();
    42         }
    43         /*将源文件和切割的信息也保存起来,随着碎片文件一起发送
    44          * 信息:源文件的名称
    45          * 碎片的个数
    46          *将这些信息单独封装到一个文件中
    47          *还要一个输出流完成此操作 */
    48         
    49         String fileName=srcFile.getName();
    50         int partCount=count;
    51         fos=new FileOutputStream(new File(partsDir,count+".properties"));
    52 //        fos.write(("fileName="+fileName+System.lineSeparator()).getBytes());
    53 //        fos.write(("fileCount="+Integer.toString(partCount)).getBytes());
    54         Properties prop=new Properties();
    55         prop.setProperty("fileName", srcFile.getName());
    56         prop.setProperty("partCount", Integer.toString(partCount));
    57         //将属性集中的信息持久化
    58         prop.store(fos, "part file info");
    59         fis.close();
    60         fos.close();
    61         
    62     }
    63 }

    复制代码

     mergeFile

    9、用于操作数组和字符串的流对象

    ByteArrayInputStream  ByteArrayOutputStream

    CharArrayReader   CharArrayWriter

    StringReader    StringWriter

    关闭这些流都是无效的,因为这些都未调用系统资源,不需要抛IO异常。

     

     View Code

     

    10、RandomAccessFile

     View Code

    11、File类:

    File: 文件和目录路径名的抽象表示形式,File类的实例是不可改变的

    (1)File类常用功能

    复制代码

    File: 文件和目录路径名的抽象表示形式,File类的实例是不可改变的
    
     * File类的构造方法:
     *             File(String pathname) 将指定的路径名转换成一个File对象
     *             File(String parent,String child) 根据指定的父路径和文件路径创建对象
     *             File(File parent,String child)
     * File类常用功能:
     *             创建:boolean createNewFile():当指定文件(或文件夹)不存在时创建文件并返回true,否则返回false,路径不存在则抛出异常
     *                 boolean mkdir()  :当指定文件(或文件夹)不存在时创建文件夹并返回true,否则返回false
     *                 boolean mkdirs() :创建指定文件夹,所在文件夹目录不存在时,则顺道一块创建
            
     *             删除:boolean delete():删除文件
                注意:要删除一个目录,需要先删除这个目录下的所有子文件和子目录
     *             获取:File getAbsoluteFile()
     *                 File getParentFile()
     *                 String getAbsolutePath()
     *                 String getParent()
     *                 String getPath()
     *                 long lastModified() 
    *             判断: boolean exists();
     *                 boolean isAbsolute() 
     *                 boolean isDirectory() 
     *                 boolean isFile() 
     *                 boolean isHidden()    
     *             修改:boolean renameTo(File dest): 将当前File对象所指向的路径修改为指定File所指的路径 (修改文件名称)    

    复制代码

    案例:打印指定文件(夹)及其所有子目录

    复制代码

     1 import java.io.File;
     2 /**
     3  *打印目录
     4  */
     5 public class FileDemo1 {
     6     public static void main(String[] args){
     7         File f=new File("E:\\BaiduNetdiskDownload");
     8         printTree( f,0);
     9     }
    10     
    11     public static void printTree(File f,int level) {
    12         for(int j=0;j<level;j++) {
    13             System.out.print("\t");
    14         }
    15         System.out.println(f.getAbsolutePath());
    16         if(f.isDirectory()) {
    17             level++;
    18             File strs[]=f.listFiles();
    19             for(int i=0;i<strs.length;i++) {
    20                 File f0=strs[i];
    21                 printTree(f0,level+1);
    22             }
    23         }
    24     }
    25 }

    复制代码

     (2)File类重要方法之过滤器

    String[] list()
    String[] list(FilenameFilter)
    File[] listFiles()
    File[] listFiles(FilenameFilter)
    File[] listFiles(FileFilter filter)

    File类的list方法可以获取目录下的各个文件,传入过滤器还能按照特定需求取出需要的文件。下面来看一下过滤器怎么用的。首先看

    String[] list(FilenameFilter)
    

    查看FilenameFilter源码,发现其实是一个接口:

    复制代码

    public interface FilenameFilter {
        /**
         * Tests if a specified file should be included in a file list.
         *
         * @param   dir    the directory in which the file was found.
         * @param   name   the name of the file.
         * @return  <code>true</code> if and only if the name should be
         * included in the file list; <code>false</code> otherwise.
         */
        boolean accept(File dir, String name);
    }

    复制代码

    那么我们要想使用过滤器,应该先实现接口,假设我们要找某个文件夹下的txt文件:

    复制代码

     1 import java.io.File;
     2 import java.io.FilenameFilter;
     3 
     4 public class FileDemo {
     5     public static void main(String[] args) {
     6         File file = new File("C:\\Test");
     7         if(file.isDirectory()) {
     8             String[] list=file.list(new FilenameFilterbytxt());//传入过滤器
     9             for(String l:list) {
    10                 System.out.println(l);
    11             }
    12         }
    13     }
    14 }
    15 
    16 class FilenameFilterbytxt implements FilenameFilter{
    17     @Override
    18     public boolean accept(File dir, String name) {
    19         // TODO Auto-generated method stub
    20         return name.endsWith(".txt");//当文件名以.txt结尾时返回true.
    21     }
    22     
    23 }

    复制代码

    但是我们看到第8行代码只是传入了过滤器,那么accept方法是如何被调用的呢?查看

    String[] list(FilenameFilter) 的源码:

    复制代码

     1  /*list(FilenameFilter)源码解析*/
     2 public String[] list(FilenameFilter filter) {
     3         String names[] = list();//调用list()方法获取所有名称
     4         if ((names == null) || (filter == null)) {
     5             return names; 
     6         }
     7         List<String> v = new ArrayList<>();//用于保存过滤后的文件名
     8         for (int i = 0 ; i < names.length ; i++) {//遍历
     9             //调用filter的accept方法,传入当前目录this和遍历到的名称names[i]
    10             if (filter.accept(this, names[i])) {
    11                 v.add(names[i]);//满足过滤器条件的添加到集合中
    12             }
    13         }
    14         return v.toArray(new String[v.size()]);//将集合转成数组返回,限定增删操作
    15     }                        

    复制代码

    也就是说,我们实现的accept方法是在构造器中被调用的。

    类似地,FileFilter 也是一个接口,采用匿名内部类的方式实现接口,使用File[] listFiles(FileFilter filter)获取目录下所有文件夹:

    复制代码

     1 import java.io.File;
     2 import java.io.FileFilter;
     3 
     4 public class FileDemo {
     5     public static void main(String[] args) {
     6         File file = new File("C:\\Test");
     7         if(file.isDirectory()) {
     8             File[] list=file.listFiles(new FileFilter() {
     9                 @Override
    10                 public boolean accept(File pathname) {
    11                     // TODO Auto-generated method stub
    12                     return pathname.isDirectory();
    13                 }
    14                 
    15             });
    16             
    17             for(File f:list) {
    18                 System.out.println(f);
    19             }
    20         }
    21     }
    22 }

    复制代码

     File[] listFiles(FileFilter filter) 方法的源码如下:

    复制代码

     1 /*File[] listFiles(FileFilter filter)源码解析*/
     2  public File[] listFiles(FileFilter filter) {
     3         String ss[] = list();//调用list()获取所有的名称数组
     4         if (ss == null) return null;//健壮性判断,数组为null则返回
     5         ArrayList<File> files = new ArrayList<>();//创建File类型集合
     6         for (String s : ss) {//遍历
     7             File f = new File(s, this);//private File(String child, File parent)私有构造调用
     8             if ((filter == null) || filter.accept(f))//条件判断
     9                 files.add(f);//添加到集合
    10         }
    11         return files.toArray(new File[files.size()]);//集合转成数组返回
    12     }

    复制代码

     12、IO流使用规律总结:

     (1)明确要操作的数据是数据源还是数据目的(要读还是要写)

          源:InputStream  Reader

          目的:OutputStream  Writer

     (2)明确要操作的设备上的数据是字节还是文本

          源:

              字节:InputStream

              文本:Reader

          目的:

              字节:OutputStream

              文本:Writer

    (3)明确数据所在的具体设备

          源设备:

            硬盘:文件 File开头

            内存:数组,字符串

            键盘:System.in

            网络:Socket

          目的设备:

            硬盘:文件 File开头

            内存:数组,字符串

            屏幕:System.out

            网络:Socket

    (4)明确是否需要额外功能?

        需要转换——转换流 InputStreamReader OutputStreamWriter

        需要高效——缓冲流Bufferedxxx

        多个源——序列流 SequenceInputStream

        对象序列化——ObjectInputStream,ObjectOutputStream

        保证数据的输出形式——打印流PrintStream Printwriter

        操作基本数据,保证字节原样性——DataOutputStream,DataInputStream

    展开全文
  • Java-IO流

    2019-01-18 13:14:40
    1.3、IO流的分类 1.4、IO流特性 1.5、IO流常用到的五类一接口 1.6、Java IO流对象 1.6.1、输入字节流InputStream 1.6.2、输出字节流OutputStream 1.6.3、字符输入流Reader 1.6.4、字符输出流Writer 1.6.5、...

    目录

    1、流的概念和作用

    1.2、Java IO所采用的模型

    1.3、IO流的分类

    1.4、IO流特性

    1.5、IO流常用到的五类一接口

    1.6、Java IO流对象

    1.6.1、输入字节流InputStream

    1.6.2、输出字节流OutputStream

    1.6.3、字符输入流Reader

    1.6.4、字符输出流Writer

    1.6.5、字节流和字符流使用情况:(重要)

    1.7、字符流与字节流转换

    1.8、字节流和字符流的区别(重点)

    1.9、System类对IO的支持​

    2.0、处理流BufferedReader,BufferedWriter,BufferedInputStream

    2.1、什么是装饰者模式?

    2.2、Scanner类

    2.3、序列化

    反序列化

    transient关键字(一个类某些属性不需要序列化)

    2.2、总结


    1、流的概念和作用

    流:代表任何有能力产出数据的数据源对象或者是有能力接受数据的接收端对象<Thinking in Java>

    流的本质:数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。 

    作用:为数据源和目的地建立一个输送通道

    1.2、Java IO所采用的模型

    Java的IO模型设计非常优秀,它使用Decorator(装饰者)模式,按功能划分Stream,您可以动态装配这些Stream,以便获得您需要的功能。

           例如,您需要一个具有缓冲的文件输入流,则应当组合使用FileInputStream和BufferedInputStream。

    1.3、IO流的分类

                  1.3.1、按数据流的方向分为 输入流、输出流

            此输入、输出是相对于我们写的代码程序而言,

            输入流:从别的地方(本地文件,网络上的资源等)获取资源 输入到 我们的程序中

            输出流:从我们的程序中 输出到 别的地方(本地文件), 将一个字符串保存到本地文件中,就需要使用输出流。

        1.3.2、按处理数据单位不同分为 字节流、字符流  

             1字符 = 2字节 、 1字节(byte) = 8位(bit)  、 一个汉字占两个字节长度

           字节流:每次读取(写出)一个字节,当传输的资源文件有中文时,就会出现乱码,

            字符流:每次读取(写出)两个字节,有中文时,使用该流就可以正确传输显示中文。

        1.3.3、按功能不同分为 节点流、处理流

              节点流:以从或向一个特定的地方(节点)读写数据。如FileInputStream 

              处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,

        1.3.4、4个基本的抽象流类型,所有的流都继承这四个。

               输入流      输出流

          字节流  InputStream  outputStream

          字符流  Reader      Writer

          inputStream:字节输入流

          outputStream:字节输出流

          Reader:字符输入流

          Writer:字符输出流

         

        1.5、总结流的分类

            看上面的几个分类,可能对于初次学io的同学会感觉到有些混乱,那什么时候用字节流,什么时候该用输出流呢?其实非常简单,举一个例子就学会了,

            1、首先自己要知道是选择输入流还是输出流,这就要根据自己的情况而定,如果你想从程序写东西到别的地方,那么就选择输出流,反之用输入流

            2、然后考虑你传输数据时,是选择使用字节流传输还是字符流,也就是每次传1个字节还是2个字节,有中文肯定就选择字符流了。(详情见1.8)

            3、前面两步就可以选出一个合适的节点流了,比如字节输入流inputStream,如果要在此基础上增强功能,那么就在处理流中选择一个合适的即可。

    字符流的由来: Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。

    1.4、IO流特性

    1、先进先出,最先写入输出流的数据最先被输入流读取到。

    2、顺序存取,可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile可以从文件的任意位置进行存取(输入输出)操作

    3、只读或只写,每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。

    1.5、IO流常用到的五类一接口

    在整个Java.io包中最重要的就是5个类和一个接口。5个类指的是File、OutputStream、InputStream、Writer、Reader;一个接口指的是Serializable.掌握了这些IO的核心操作那么对于Java中的IO体系也就有了一个初步的认识了。

    主要的类如下:

         1. File(文件特征与管理):File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。  

         2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。

         3. OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。

         4.Reader(文件格式操作):抽象类,基于字符的输入操作。

         5. Writer(文件格式操作):抽象类,基于字符的输出操作。

         6. RandomAccessFile(随机文件操作):一个独立的类,直接继承至Object.它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。

    1.6、Java IO流对象

     

    1.6.1、输入字节流InputStream

    认识每个类的功能即作用

         ByteArrayInputStream:字节数组输入流,该类的功能就是从字节数组(byte[])中进行以字节为单位的读取,也就是将资源文件都以字节的形式存入到该类中的字节数组中去,我们拿也是从这个字节数组中拿

         PipedInputStream:管道字节输入流,它和PipedOutputStream一起使用,能实现多线程间的管道通信

         FilterInputStream :装饰者模式中处于装饰者,具体的装饰者都要继承它,所以在该类的子类下都是用来装饰别的流的,也就是处理类。具体装饰者模式在下面会讲解到,到时就明白了

         BufferedInputStream:缓冲流,对处理流进行装饰,增强,内部会有一个缓存区,用来存放字节,每次都是将缓存区存满然后发送,而不是一个字节或两个字节这样发送。效率更高

           DataInputStream:数据输入流,它是用来装饰其它输入流,它“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”

         FileInputSream:文件输入流。它通常用于对文件进行读取操作

         File:对指定目录的文件进行操作,具体可以查看讲解File的博文。注意,该类虽然是在IO包下,但是并不继承自四大基础类。

           ObjectInputStream:对象输入流,用来提供对“基本数据或对象”的持久存储。通俗点讲,也就是能直接传输对象(序列化中使用),

     

    1.6.2、输出字节流OutputStream

    IO 中输出字节流的继承图可见上图,可以看出:

    1. OutputStream 是所有的输出字节流的父类,它是一个抽象类。
    2. ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,
    3. ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流(序列化中使用)。

           

    1.6.3、字符输入流Reader

    在上面的继承关系图中可以看出:

    1. Reader 是所有的输入字符流的父类,它是一个抽象类。
    2. CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据。
    3. BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。
    4. FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。
    5. InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。后面会有Reader 与InputStream 的对应关系。

    1.6.4、字符输出流Writer

    在上面的关系图中可以看出:

    1. Writer 是所有的输出字符流的父类,它是一个抽象类。
    2. CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。PipedWriter 是向与其它线程共用的管道中写入数据,
    3. BufferedWriter 是一个装饰器为Writer 提供缓冲功能。
    4. PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。
    5. OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,后面会有它们的对应图。

    1.6.5、字节流和字符流使用情况:(重要

    字符流和字节流的使用范围:字节流一般用来处理图像,视频,以及PPT,Word类型的文件。字符流一般用于处理纯文本类型的文件,如TXT文件等,字节流可以用来处理纯文本文件,但是字符流不能用于处理图像视频等非文本类型的文件。

    1.7、字符流与字节流转换

    转换流的作用,文本文件在硬盘中以字节流的形式存储时,通过InputStreamReader读取后转化为字符流给程序处理,程序处理的字符流通过OutputStreamWriter转换为字节流保存。

    转换流的特点:

    1. 其是字符流和字节流之间的桥梁
    2. 可对读取到的字节数据经过指定编码转换成字符
    3. 可对读取到的字符数据经过指定编码转换成字节

    何时使用转换流?

    1. 当字节和字符之间有转换动作时;
    2. 流操作的数据需要编码或解码时。

    具体的对象体现:

    1. InputStreamReader:字节到字符的桥梁
    2. OutputStreamWriter:字符到字节的桥梁

    这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。

     

    OutputStreamWriter(OutStreamout):将字节流以字符流输出。

    InputStreamReader(InputStream in):将字节流以字符流输入。

    1.8、字节流和字符流的区别(重点

    字节流和字符流的区别:(详细可以参见http://blog.csdn.net/qq_25184739/article/details/51203733)    

             节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,字节流不调用colse()方法时,信息已经输出了,而字符流只有在调用close()方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用flush()方法。

    ·        读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

    ·        处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

    结论:只要是处理纯文本数据,就优先考虑使用字符流。除此之外都使用字节流。

    1.9、System类对IO的支持

     针对一些频繁的设备交互,Java语言系统预定了3个可以直接使用的流对象,分别是:

    ·        System.in(标准输入),通常代表键盘输入。

    ·        System.out(标准输出):通常写往显示器。

    ·        System.err(标准错误输出):通常写往显示器。

     标准I/O
          Java程序可通过命令行参数与外界进行简短的信息交换,同时,也规定了与标准输入、输出设备,如键盘、显示器进行信息交换的方式。而通过文件可以与外界进行任意数据形式的信息交换。

    2.0、处理流BufferedReader,BufferedWriter,BufferedInputStream

    BufferedOutputsStream,都要包上一层节点流。也就是说处理流是在节点流的基础之上进行的,带有Buffered的流又称为缓冲流,缓冲流处理文件的输入输出的速度是最快的。所以一般缓冲流的使用比较多。

     

    2.1、什么是装饰者模式?

           推荐一篇博文,http://blog.csdn.net/jason0539/article/details/22713711  就详细说明了什么是装饰者模式?用我自己的话来说,就是往一个添加更多的功能,而我们首先想到的是继承,继承就很好的符合了我们的要求,不管你想加多少层的功能,都可以使用继承一层层的实现,但是这带来了一个问题,一旦我需要改变我的需求,那么我就需要往源码中改东西,再就是在这个继承链中某个类做一些修改,这不符合我们的设计模式思想,所以就有了装饰者模式,装饰者中拥有被装饰者的实例,然后有什么具体的装饰我们都另写一个类来继承该装饰者,当我们需要该装饰时,就new出该类来,然后将其被装饰者当作参数传递进去。

                       

              关说可能没理解那么清楚,现在来看看一个具体的实例。比如,我们需要制作一份鸡腿堡,流程是怎样的呢?看下图

                  1、先有基本原料,也就是两块面包,这是不管做什么汉堡都需要的,

                  2、做什么汉堡,取决于加什么材料,比如生菜,鸡肉等,所以根据材料来做汉堡,想做什么汉堡就加什么材料

                  3、所有材料加完之后,直接计算价格即可

                这样使用装饰者模式,是不是比一直使用继承方便的多的多呢?换一种汉堡,也不需要改源码,什么也不需要,希望你能够理解清楚其中的思想。

                        

     

          3.2、io流中的装饰者模式的运用

                画张图,在结合源码和自己写的代码来看。

                      

     

              到这里,应该可以对前面的处理流和节点流有所理解了把,其实处理流就是一个具体的装饰者,而节点流就是被装饰者。

    2.2、Scanner类

     Java 5添加了java.util.Scanner类,这是一个用于扫描输入文本的新的实用程序。它是以前的StringTokenizer和Matcher类之间的某种结合。由于任何数据都必须通过同一模式的捕获组检索或通过使用一个索引来检索文本的各个部分。于是可以结合使用正则表达式和从输入流中检索特定类型数据项的方法。这样,除了能使用正则表达式之外,Scanner类还可以任意地对字符串和基本类型(如int和double)的数据进行分析。借助于Scanner,可以针对任何要处理的文本内容编写自定义的语法分析器。

    Scanner套接字节流或字符流:

    字节流的套接:在Scanner的构造方法中Scanner(InputStream source),InputStream只要经过适当的套接,总能获得你想要的流接口。

    字符流的套接:Scanner(Readable source),你需要使用Java SE5中新加入的一个接口Readable,该接口表示“具有read()方法的某种东西”,查看Readable接口的API你可以发现你想要的带有Reader的类基本都在其中。

    2.3、序列化

    将保存在内存中的对象数据转化为二进制数据流进行传输,任何对象都可以序列化

    实现方法:实现java.io.Serializable接口

    作用:把一个Java对象写入到硬盘或者传输到网路上面的其它计算机,这时我们就需要自己去通过java把相应的对象写成转换成字节流。对于这种通用的操作,我们为什么不使用统一的格式呢?没错,这里就出现了java的序列化的概念。在Java的OutputStream类下面的子类ObjectOutput-Stream类就有对应的WriteObject(Object object) 其中要求对应的object实现了java的序列化的接口。

    在使用tomcat开发JavaEE相关项目的时候,我们关闭tomcat后,相应的session中的对象就存储在了硬盘上,如果我们想要在tomcat重启的时候能够从tomcat上面读取对应session中的内容,那么保存在session中的内容就必须实现相关的序列化操作,还有jdbc加载驱动用的就是反序列化,将字符串变为对象。。。

    //序列化类:java.ioObjectOutputStream
    
    //讲对象变为指定的二进制数据
    
    class Book implements Serializable{
    
    	private String title;
    
    	private double price;
    
    	public Book(String tit,double pri){
    
    		this.title=tit;
    
    		this.price=pri;
    
    	}
    
    	public String toString() {
    
    		return "书名:"+this.title+",价格:"+this.price;
    
    	}
    
    }
    
    public class Demo10 {
    
    	public static void main(String[] args) throws Exception {
    
    //序列化到指定的文本
    
    		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("e:"+File.separator+"demoA.txt")));
    
    		oos.writeObject(new Book("java开发", 45.2));
    
    		oos.close();
    
    	}
    
    }/

    反序列化

    将二进制数据换回原对象

    构造:

        ObjectInputStream(InputStream in)

    方法:

         Object readObject() 从 ObjectInputStream 读取对象 

    
    class Book implements Serializable{
    
    	private String title;
    
    	private double price;
    
    	public Book(String tit,double pri){
    
    		this.title=tit;
    
    		this.price=pri;
    
    	}
    
    	public String toString() {
    
    		return "书名:"+this.title+",价格:"+this.price;
    
    	}
    
    }
    
    public class Demo11 {
    
    	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
    
    		ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("e:"+File.separator+"demoA.txt")));
    
    		Object obj=ois.readObject();
    
    		Book book=(Book) obj;
    
    		System.out.println(book);
    
    		ois.close();
    
    	}
    
    }

    transient关键字(一个类某些属性不需要序列化)

    以上序列化和反序列化实现了的对象序列化,但是可以发现,操作时是将整个对象的所有属性序列化,那么transient关键字可以将某些内容不需要保存,就可以通过transient关键字来定义

    private transient string title;

    此时title属性无法被序列化,

    2.2、总结

    inputStream类的功能不足被Scanner解决了

    OutputStream类的功能不足被PrintStream解决了

    Reader类功能不足被BufferReader解决了

    Writer类的功能不足被PrintWriter解决了

    输出数据用printStream,printwriter读取数据用Scanner其次是bufferReader

    借鉴的博客有:

    https://www.cnblogs.com/ylspace/p/8128112.html

    https://www.cnblogs.com/runningTurtle/p/7088125.html

    https://www.jb51.net/article/112602.htm

    https://www.cnblogs.com/whgk/p/6920018.html

    展开全文
  • io流知识汇总

    2020-07-24 18:23:42
    目录io流是什么?io流的分类关于io流中的垃圾回收机制问题操作流的基本步骤节点流字符流FileReaderFileWriter复制文本文件字节流复制图片节点流的注意事项处理流缓冲流缓冲流原理缓冲流例子转换流概念 io流是什么? ...
  • IO流

    2020-08-03 12:38:22
    字节: 字节输入: InputStream类 API: 方法 返回值 说明 read() int 从输入中读取下一个字节,返回0~255范围内的int字节值。如果因为已经到达末尾而没有可用的字节,返回-1 read(byte[] b) int ...
  • java IO流的概念理解

    2019-02-18 08:41:37
    1.Java Io流的概念,分类,类图。 1.1 Java Io流的概念     java的io是实现输入和输出的基础,可以方便的实现数据的输入和输出操作。在java中把不同的输入/输出源(键盘,文件,网络连接等)抽象表述为“流”...
  • Java IO流学习总结(一)—— IO流分类和常用IO流汇总 IO流的分类: - 按流向分类:输入流、输出流 - 按操作对象分类:字节流、字符流 - 按功能分类:节点流、处理流 IO流的设计模式为装饰设计模式; ...
  • 最近项目中需要用到IO流来读取图片以提供前台页面展示,由于以前一直是用url路径的方式进行图片展示,一听说要项目要用IO流读取图片感觉好复杂一样,但任务下达下来了,做为程序员只有选择去执行喽,于是找了点资料看了会...
  • IO流实例详解

    2018-04-02 19:57:24
    IO流一、IO流简介01.流的概念和作用流是一组有顺序的,有起点和终点的字节集合,是对数据传输的的总称或抽象。即数据在两设备之间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观...
  • 在上一篇的IO流引入中,我们拿读写简单文本文件为例,说明了IO流在我们开发中最常用的一个场景,那么我们今天就来看看IO流究竟是什么,究竟能帮助我们干什么以及它的主要组成部分。 1,IO流是什么 说白了,IO流...
  • 你真的懂IO流

    2020-07-20 11:55:09
    目录什么是IO流IO流的分类输入输出流字节字符流 什么是IO流 在我们的程序运行当中,不可避免的要与数据打交道,我们应该如何获取这些数据?这就用到IO流了 IO:Input/Output,输入输出流 作用:通过IO流可以完成硬盘...
  • Java之IO流---字节流

    2018-06-15 11:24:21
    1.1 IO流的引入 IO流在很多语言已有体现,诸如C语言的stdio.h,C++中的iostream。Java中的IO流大抵是用于在控制台、磁盘、内存上进行数据的读写操作,完成数据的传递。 我们可以对它进行如下分类: 按处理的...
  • IO流的分类

    2019-05-11 09:12:23
    IO流的分类可以分为以下三种: 第一种:输入流和输出流 按照流的流向来分,可以分为输入流和输出流。输入,输出都是从程序运行所在内存的角度来划分的。 输入流:只能从中读取数据,而不能向其写入数据,由...
  • Java IO流学习总结一:输入输出流 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/53761199 本文出自【赵彦军的博客】 Java流类图结构:流的概念和作用流是一组有顺序的,有起点和终点的字节...
  • 什么是IO流

    2018-01-15 17:08:33
    什么是IO流 先看一段百度上的解释: 当然:如果你看不懂,那么你只需要记住下面3句话. 1. (1).我们知道,每个人家里喝的水都是从自来水厂来的,自来水厂的水又是从水源地来的, (2).水是通过水管来的。 (3)....
  • 关于Java的IO流以前也总结过不少,根据API画出了IO流的类结构图,也写了不少相关的程序 但是没有对IO流做一个综合型的总结,最近在CSDN和ITeye上看了不少对IO流的总结,感觉有必要 抽时间总结一次,这既是对Java基础...
  • IO流与多线程总结

    2016-09-22 16:28:28
    IO流 1.概念 IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的类都在IO包中 流按流向分为两种:输入流,输出流。 流按操作类型分为两种:字节流与字符流。 字节流可以操作...
1 2 3 4 5 ... 20
收藏数 479,811
精华内容 191,924
关键字:

io流