学习笔记:Java_I/O(part_two)

来源:互联网 发布:电动车用骑行导航软件 编辑:程序博客网 时间:2024/06/16 19:11

I/O流

(概述、文件字节流、文件字符流、转换流、缓冲流)

  IO流这部分,算上学习File文件类的时间,总共花了三天时间学习,知识庞杂,种类繁多。但是说到底,各种各样的IO流,核心的方法无外乎构造()、read()、write()三种,根据文件类型的不同,选取不同的IO流。
  东西太多,一次整理不完,因此分成几篇文章来整理,这里是IO概述、文件字节流、文件字符流、转换流四部分


I/O流概述

输入输出的概念

  • 输入输出指的是系统内存与外部设备,网络等进行交互的过程。
    |

I/O概念

  流是一个抽象的概念。当Java程序需要从数据源读取数据时,会开启一个到数据源的流,这个流就是输出流,数据源可以是文件,内存或者网络等。同样,当程序需要输出数据到目的地时也一样会开启一个流,这个流就是输入流,数据目的地也可以是文件、内存或者网络等。流的创建是为了更方便地处理数据的输入输出。
  流对象的操作依赖于操作系统,流通道本身并没有作用

流分类

  • 四大父类(抽象基类)
类名 类名 操作属性 操作对象 字节输入流 InputStream 读入 字节 字符输入流 Reader 读入 字符 字节输出流 OutputStream 写出 字节 字符输出流 Writer 写出 字符

* 根据是否具有额外功能:

类名 类名 操作属性 操作对象 额外功能 转换流 InputStreamReader
OutputStreamWriter 输入转换流
输出转换流 字节和字符 转换字节到字符 缓冲流 BufferedXXX XXX的功能 XXX的操作对象 可以通过缓冲原理实现加速并且实现一些新功能

流对象操作步骤

  1. 创建流子类对象,绑定数据目的(数据源和目标文件)
  2. 调用流方法进行读写操作
  3. .close();释放流对象(Java在程序结束时会自动关闭所有打开的流,但即便如此,显式的关闭任何打开的流仍是一个良好的习惯)。

I/O流注意事项

  • I/O流只能对整个文件进行操作,对文件中个别数据进行操作只能用数据库才能实现。
  • 流对象进行操作的时候经常会抛出IOException异常,所以需要用try{}catch{}语句来写

文件字节流和文件字符流

主要区别

  • 文件字节流可以读写任意文件(不包括文件夹),每次只操作文件中的一个字节。利用字节流创建的新文件可以保证不出错。
  • 文件字符流只能读写文本文件(用.txt格式打开之后能读懂的文件就是文本文件),用字符流创建除文本文件以外任意文件都会造成文件损坏。
  • 字节流不能直接操纵unicode字符,这时字符流的必要性就体现出来,因为一次操纵一个字符(即两个字节),这样就避免了数据传输中,汉字出现乱码等问题。

文件字节流

类名 类名 操作属性 操作对象 文件字节输入流 FileInputStream 从文件中读入 字节 文件字节输出流 FileOutputStream 写出到文件中 字节

文件字节输入流

构造器

  • 作用是绑定输入数据源
  • 文件字节输入流有两种构造方法:
    ——————————
    |FileInputStream(String filePath);|
    |FileInputStream(File file);   |
    ——————————

  • 示例代码

/** 这里是在方法内对异常进行处理的完整步骤,比较麻烦,不如throws之后在外边处理好用* 这里只举例输入流的例子,输出流大同小异,定义时候的区别在其他代码里体现。*/import java.io.File;import java.io.FileInputStream;import java.io.IOException;public class MyInputStream {    public static void main(String[] args) {        File file = new File("d:\\java\\全职高手.txt");        FileInputStream in = null;//try外定义方便显式关闭输入流;        try {            in = new FileInputStream(file);        } catch (IOException ea) {            ea.getMessage();//打印错误信息;            throw new RuntimeException("\n运行发生错误,请尝试重新运行:");//关闭程序;        } finally {            try {                if (in != null)//判断输入流是否存在且创建成功;                    in.close();            } catch (IOException eb) {                eb.getMessage();                throw new RuntimeException("\n输入流关闭失败,请尝试重新运行程序");            }        }    }}

常用方法

方法表达式 返回值 注意事项 read(); int(字节值) 每次只读取一个字节,方法返回字节值,到达文件末尾返回-1 read(byte b[]) int(实际读取的字节个数) 每次读取最多b空间大小的数量的字节,到达末尾返回-1
b的大小太大会浪费空间,太小又影响速度,所以一般定义大小为1024 read(byte b[], int off, int len) int(实际读取的字节个数) off指定数据存放在数组中的位置len指定方法读取的最大字节数 close(); void 显式关闭输入流

文件字节输出流

构造器

  • 作用是绑定输出的输出目的
  • 文件字节输出流有四种构造方法:
    ———————————————-
    |FileOutputStream(String filePath);        |
    |FileOutputStream(File file);           |   
    |FileOutputStream(String filePath, boolean append); |
    |FileOutputStream(File file, boolean append);   |
    ———————————————-

  • 输出流对象的构造方法可以创建对象,但是如果源文件存在,默认会覆盖原来的文件

  • 所有在构造方法的参数后边常常可以添加另外一个参数boolean append来决定如果文件存在是否覆盖,当apped**值为true**时,输出流会创建新文件覆盖目标文件,否则不覆盖,在目标文件中进行续写

常用方法

方法表达式 返回值 注意事项 write(int b); void 参数虽然是int类型,但是实际传参必须是byte类型 write(byte b[]) void 写入b空间大小的数量的字节
b的大小太大会浪费空间,太小又影响速度,所以一般定义大小为1024 write(byte b[], int off, int len) void off指定数据存放在数组中的位置,即偏移量len指定方法写入的最大字节数 close(); void 显式关闭输出流

文件字符流

类名 类名 操作属性 操作对象 文件字节输入流 FileReader 从文件中读入 字节 文件字节输出流 FileWriter 写出到文件中 字节

* 转换流失文件字符流的父类,继承关系:
* java.io.FileReader extends java.io.inputStreamReader;
* java.io.inputStreamReader extends java.io.Reader;
* java.io.Reader extends java.lang.Object;
* 文件字符输入流和文件字符输出流都采用系统默认的编码表,中文版Windows系统默认系统编码表为GBK;

文件字符输入流

构造器

  • 作用是绑定输入数据源
  • 文件字符输入流有两种构造方法:
    ————————–
    |FileReader(String filePath);|
    |FileReader(File file);   |
    ————————–

常用方法

方法表达式 返回值 注意事项 read(); int(字符值) 每次只读取一个字节,方法返回字节值,到达文件末尾返回-1 read(byte b[]) int(实际读取的字符个数) 每次读取最多b空间大小的数量的字节,到达末尾返回-1
b的大小太大会浪费空间,太小又影响速度,所以一般定义大小为1024 read(byte b[], int off, int len) int(实际读取的字符个数) off指定数据存放在数组中的位置len指定方法读取的最大字节数 close(); void 显式关闭输入流

文件字节输出流

构造器

  • 作用是绑定输出的输出目的
  • 文件字符输出流有四种构造方法:
    —————————————-
    |FileWriter(String filePath);        |
    |FileWriter(File file);            |   
    |FileWriter(String filePath, boolean append); |
    |FileWriter(File file, boolean append);   |
    ————————————–
  • 输出流对象的构造方法可以创建对象,但是如果源文件存在,默认会覆盖原来的文件
  • 所有在构造方法的参数后边常常可以添加另外一个参数boolean append来决定如果文件存在是否覆盖,当apped**值为true**时,输出流会创建新文件覆盖目标文件,否则不覆盖,在目标文件中进行续写
  • 与文件字节输出流不同,文件字符输出流只能创建有效的文本文件。

常用方法

方法表达式 返回值 注意事项 write(int c); void 参数虽然是int,但是实际传参要传char类型 write(char b[]) void write(byte b[], int off, int len) void off指定数据存放在数组中的位置,即偏移量len指定方法写入的最大字符数 write(String str) 把字符串中所有字符写到文件中 write(String str, int off, int len) void flush() void 冲流,将数据写入文件(不进行冲流则数据无法写入文件
每次写入数据后进行一次冲流是一个好习惯 close(); void 显式关闭输出流,再关闭流的同时进行一次冲流操作

文件字节流复制文件代码举例

import java.io.*;class ClsByte {    private String originalpath, finalpath;    private long starttime, endtime;    public ClsByte(String a, String b) {        this.originalpath = a;        this.finalpath = b;    }    public void function() {        System.out.println("字节流复制文件,开始执行:");        starttime = System.currentTimeMillis();        File orifile = new File(originalpath);        File tarfile = new File(finalpath);        FileOutputStream out = null;        FileInputStream in = null;        byte[] data = new byte[1024];        try {            in = new FileInputStream(orifile);            out = new FileOutputStream(tarfile, false);            int len = 0;            while ((len = in.read(data)) != -1) {                out.write(data, 0, len);            }        } catch (IOException e) {            e.getStackTrace();            throw new RuntimeException("\n文件传输中发生错误,请重试");        } finally {            try {                if (in != null) {                    in.close();                }            } catch (IOException e) {                throw new RuntimeException("\n输入流关闭失败,请重试");            }            try {                if (out != null) {                    out.close();                }            } catch (IOException e) {                throw new RuntimeException("\n输出流关闭失败,请重试");            }        }        endtime = System.currentTimeMillis();        System.out.println("文件复制成功\n源文件" + orifile.getAbsolutePath() + "源文件大小" + orifile.getTotalSpace() + "B");        System.out.println("目标文件" + tarfile.getAbsolutePath() + "目标文件大小" + tarfile.getTotalSpace() + "B");        System.out.println("消耗时间" + (endtime - starttime) + "millseconds");    }}

文件字符流复制文件代码举例

import java.io.*;import java.util.*;class ClsChar {    private String originalpath, finalpath;    private long starttime, endtime;    public ClsChar(String a, String b) {        this.originalpath = a;        this.finalpath = b;    }    public void function() {        System.out.println("\n字符流复制文件,开始执行:");        starttime = System.currentTimeMillis();        File orifile = new File(originalpath);        File tarfile = new File(finalpath);        FileReader in = null;        FileWriter out = null;        char [] data = new char [1024];        try {            in = new FileReader(orifile);            out = new FileWriter(tarfile, false);            int len = 0;            while ((len = in.read(data)) != -1) {                out.write(new String(data, 0, len));                out.flush();            }        } catch (IOException e) {            e.getStackTrace();            throw new RuntimeException("\n文件传输中发生错误,请重试");        } finally {            try {                if (in != null) {                    in.close();                }            } catch (IOException e) {                throw new RuntimeException("\n输入流关闭失败,请重试");            }            try {                if (out != null) {                    out.close();                }            } catch (IOException e) {                throw new RuntimeException("\n输出流关闭失败,请重试");            }        }        endtime = System.currentTimeMillis();        System.out.println("文件复制成功\n源文件" + orifile.getAbsolutePath() + "源文件大小" + orifile.getTotalSpace() + "B");        System.out.println("目标文件" + tarfile.getAbsolutePath() + "目标文件大小" + tarfile.getTotalSpace() + "B");        System.out.println("消耗时间" + (endtime - starttime) + "millseconds");    }}

转换流

转换流特性

  两种转换流都是字符流,区别在于,Output是由字符转字节,Input是由字节转字符

转换流和文件字符流的区别

  • 文件字符流是转换流的子类
  • 文件字符流的编码表已指定为系统默认编码表,转换流则可以指定编码表
  • FileWriter和FileReader:作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码。

  • *
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));//默认字符集。InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");//指定GBK字符集。FileReader fr = new FileReader("a.txt");
  • 这三句代码的功能是一样的,其中第三句最为便捷。
  • 注意:一旦要指定其他编码时,绝对不能用子类,必须使用字符转换流。什么时候用子类呢?
    • 条件:
      1. 操作的是文件。
      2. 使用默认编码。

构造器

  • InputStreamReader(InputStream in)
    • 创建的转换流使用默认字符集
  • InputStreamReader(InputStream in, Charset cs)
    • 创建的转换流使用指定的字符集”cs”
  • OutputStreamWriter(OutputStream out)
    • 创建的转换流使用默认字符集
  • OutputStreamWriter(OutputStream out, Charset cs)
    • 创建的转换流使用指定的字符集”cs”

缓冲流

  • Java中提高了一套缓冲流,它的存在,可提高IO流的读写速度。缓冲流必须指向一个底层流,底层流负责将数据读入缓冲区,缓冲流再从缓冲区中读取数据
  • 根据流的分类分类字节缓冲流字符缓冲流
    • 字节缓冲流(BufferedReader/BufferedWriter)的底层流是字节流(InputStream/OutputStream);
    • 字符缓冲流(BufferedInputStream/BufferedOutputStrean)的底层流是字符流(Reader/Writer)

构造器

  • 四种缓冲流的构造器各有两种,这里拿字符缓冲输入流举例:
方法 参数含义 BufferedReader(Reader in); 创建一个缓冲字符输入流和保存输入流 in,供以后使用。 BufferedInputStream(InputStream in, int size) ; 创建一个具有指定的缓冲区大小的字节缓冲输入流,并保存输入流 in,供以后使用。

方法

字节缓冲流

  BufferedInputStream/BufferedOutputStream的方法基本都继承自InputStream/OutputStream,没有什么自己独特的方法,这里不再赘述

字符缓冲流

  同样,这里对于从父类中继承的方法(read(), write(), close(), flush())等都不再赘述,只介绍一些独特的方法。
* 字符缓冲输出流

方法 功能 注意事项 void newLine(); 写行分隔符,也就是换行 这里体现的是系统无关性
但其实在Windows系统下,在字符串尾部或头部写入“\r\n”是一样的效果
  • 字符缓冲输入流
方法 功能 注意事项 String readLine(); 读一行文本 读取成功则返回当前行文本,否则返回null

缓冲字符流复制文件代码举例

import java.io.*;public class ClsBufferedByte {    private String originalpath, finalpath;    private long starttime, endtime;    public ClsBufferedByte(String a, String b) {        this.originalpath = a;        this.finalpath = b;    }    public void function() {        System.out.println("\n缓冲字节流复制文件,开始执行:");        starttime = System.currentTimeMillis();        File orifile = new File(originalpath);        File tarfile = new File(finalpath);        BufferedInputStream in = null;        BufferedOutputStream out = null;        FileInputStream rootin = null;        FileOutputStream rootout = null;        byte[] data = new byte[1024];        try {            rootin = new FileInputStream(orifile);            rootout = new FileOutputStream(tarfile);            in = new BufferedInputStream(rootin);            out = new BufferedOutputStream(rootout);            int len = 0;            while ((len = in.read(data)) != -1) {                out.write(data, 0, len);            }        } catch (IOException e) {            e.getStackTrace();            throw new RuntimeException("\n文件传输中发生错误,请重试");        } finally {            try {                if (in != null) {                    in.close();                }            } catch (IOException e) {                throw new RuntimeException("\n输入流关闭失败,请重试");            }            try {                if (out != null) {                    out.close();                }            } catch (IOException e) {                throw new RuntimeException("\n输出流关闭失败,请重试");            }        }        endtime = System.currentTimeMillis();        System.out.println("文件复制成功\n源文件" + orifile.getAbsolutePath() + "源文件大小" + orifile.getTotalSpace() + "B");        System.out.println("目标文件" + tarfile.getAbsolutePath() + "目标文件大小" + tarfile.getTotalSpace() + "B");        System.out.println("消耗时间" + (endtime - starttime) + "millseconds");    }}

缓冲字符流复制文件代码举例

import java.io.*;public class ClsBufferedChar {    private String originalpath, finalpath;    private long starttime, endtime;    public ClsBufferedChar(String a, String b) {        this.originalpath = a;        this.finalpath = b;    }    public void function() {        System.out.println("\n缓冲字符流复制文件(按行读取),开始执行:");        starttime = System.currentTimeMillis();        File orifile = new File(originalpath);        File tarfile = new File(finalpath);        BufferedReader in = null;        BufferedWriter out  = null;        FileReader rootin = null;        FileWriter rootout = null;        String data = null;        try {            rootin = new FileReader(orifile);            rootout = new FileWriter(tarfile);            in = new BufferedReader(rootin);            out  = new BufferedWriter(rootout);            while ((data = in.readLine()) != null) {                out.write(data);                out.flush();            }        } catch (IOException e) {            e.getStackTrace();            throw new RuntimeException("\n文件传输中发生错误,请重试");        } finally {            try {                if (in != null) {                    in.close();                }            } catch (IOException e) {                throw new RuntimeException("\n输入流关闭失败,请重试");            }            try {                if (out != null) {                    out.close();                }            } catch (IOException e) {                throw new RuntimeException("\n输出流关闭失败,请重试");            }        }        endtime = System.currentTimeMillis();        System.out.println("文件复制成功\n源文件" + orifile.getAbsolutePath() + "源文件大小" + orifile.getTotalSpace() + "B");        System.out.println("目标文件" + tarfile.getAbsolutePath() + "目标文件大小" + tarfile.getTotalSpace() + "B");        System.out.println("消耗时间" + (endtime - starttime) + "millseconds");    }}
0 0
原创粉丝点击