WSJ--Java IO学习笔记

一、流的分类

1、按照操作数据:字节流、字符流。
2、按照流向:输入流、输出流。

二、IO流常用的基类

1、字节流的抽象基类
    InputStream : 字节输入流
    OutputStream: 字节输出流
    BufferedInputStream :带缓冲区的字节输入流。
    BufferedOutputStream:带缓冲区的字节输出流。
2、字符流的抽象基类
    Reader :字符输入流
    Writer :字符输出流
    BufferedReader:带缓冲区的字符输入流。
    BufferedWriter:带缓冲区的字符输出流。
注意:由这四个类派生出来的子类名称都是以其父类父类名作为子类名后缀的。
     例如: InputStream 的子类FileInputStream.
           Reader 的子类FileReader
3、字节流和字符流的转换。
        InputStreamReader : 字节流通向字符流的通道,继承自Reader。
        OutputStreamWriter: 字符流通向字节流的通道,继承自Writer。 

三、字符流

1、FileWriter基本使用

public static void main(String[] args)
{    
    // 创建一个文本输入对象,该对象一旦被初始化就要指明操作的文件。
    // 该文件会被创建子啊指定目录下,如果存在,则会覆盖。
    // 目的:明确数据存放的地方。
    FileWriter fw = new FileWriter("1.txt");
    
    // 调用Write()方法将字符写入到流中。
    f.write("abcde");

    // 刷新流对象中的数据到缓冲区。
    f.flush();

    // 关闭流资源,同时会自动刷新流。
    f.close();
}

FileWriter构造方法

备注:throws IOException
    1、 FileWriter(File file);
    2、 FileWriter(File file,boolean append);
    3、 FileWriter(String filepath);
    4、 FileWriter(String filepath,boolean append);

2、IO异常处理标准格式

public static void main(String[] args){
    FileWriter fw = null;
    try{
        fw = new FileWriter("1.txt");
        fw.write("abc");
    }catch(IOException e){
        e.printStackTrace();
    }finally{
        try{
            if (fw != null){    
                fw.close();
            }
        }catch(IOException e){
            e.printStackTrace();
        }
    }
}

3、FileReader基本使用

public static void main(String[] args){
    // 创建文件读取流对象,并和指定名称的文件相关联。
    // 文件必须存在,否则:FileNotFoundException;
    FileReader fr = new FileReader("1.txt");
    // 使用read()方法进行读取数据
    int ch;        
    while((ch = fr.read()) != -1){
        System.out.println("数据 : " + ch);
    }
    // 关闭流
    fr.close();
} 

FileReader 相关方法

一、构造方法 : throws IOException
    1、 FileReader(File file);
    2、 FileReader(String filename);
二、其他方法
    1、getEncoding():返回此流所使用的字符编码名称。

4、BufferedWriter基本使用

缓冲区的作用:提高流的操作效率。因此必须有流缓冲区才有意义。

示例代码 :

public static void main(String[] args){
    // 创建一个字符写入流。
    FileWriter fw = new FileWriter("1.txt");
    // 加入缓冲技术,提高流的效率。
    BufferedWriter bufw = new BufferedWriter(fw);
    // 写入数据
    for (int i = 0 ;i < 5 ;i ++){
        bufw.writer("abnc");
        bufw.newLine();// 换一行。
        bufw.flush();// 刷新数据流
    }
    // 关闭缓冲区、流
    bufw.close();
}

BufferedWriter相关方法

一、构造方法
    1、BufferedWriter(Writer out);
        创建一个默认大小缓冲区的输出字符流。
    2、BufferedWriter(Writer out,int sz);
        创建一个指定大小缓冲区的输出字符流。
        throws IllegalArgumentException .when sz < 0;
二、成员方法 : all throws IOException 异常。
    1、void close(); 关闭该流。
    2、void flush(); 刷新该流。
    3、void newLine(); 写入一个行分割父。
    4、void write(char[] buff,int off,int len); 写入字符数组的某一部分。
    5、void write(int ch); 写入单个字符。
    6、void write(String ss,int off,int len); 写入字符串的某一部分。

5、BufferedReader基本使用

示例代码 :

public static void main(String[] args) throws IOException{
    FileReader fr = new FileReader("1.txt");
    BufferedReader bufr = new BufferedReader(fr);
    String line = null;
    while((line = bufr.readLine()) != null){
        System.out.println("第一行数据:" + line);
    }
    bufr.close();
}

BufferedReader相关方法

一、构造方法
    1、BufferedReader(Reader in);
    2、BufferedReader(Reader in,int sz);
        创建一个指定缓冲区大小的字符输出流。throws IllegalArgumentException when sz < 0    
二、成员方法。
    1、readLine(); 读取一行文本。
        终止条件:回车'\r'、换行'\n' 、 回车后直接加换行。
        返回值: 返回包含该行内容的字符串,不包含终止符;如果到达末尾则返回null。

6、文件拷贝代码

public copyText_buff(){
    // 输入输出缓冲区
    BufferedReader bufr = null;
    BufferedWriter bufw = null;
    try{
        bufr = new BufferedReader(new FileReader("1.txt"));
        bufw = new BufferedWriter(new FileWriter("1_copy.txt"));
    
        String line = null;
    
        while((line = bufr.readLine()) != null){
            bufw.Write(line);
            bufw.newLine();
            bufw.flush();
        }
    }catch(IOException e){
        throw new RuntimeException("创建字符流失败");
    }finally{
        try{
            if (bufr != null)
                bufr.close();
        }catch(IOException ee){
            throw new RuntimeException("字符写流关闭失败");
        }
        try{
            if (bufw != null)
                bufw.close();
        }catch(IOException ee){
            throw new RuntimeException("字符读流关闭失败");
        }    
    }
}

7、装饰设计模式

装饰设计模式:当要对已有对象进行功能增强时。可以定义类,将已有对象传入,基于
            已有的功能、并提供加强功能。自定义的该类成为装饰类。
            装饰类通常会通过构造方法接收被装饰的对象。

8、LineNumberReader基本用法

LineNumberReader是BufferedReader的子类。

示例代码 :

public lineNumberReaderDemo() throws IOException{
    // 构建对象
    FileReader fr = new FileReader("1.txt");
    LineNumberReader lfr = new LineNumberReader(fr);
    // 设置行号
    lfr.setLineNumber = 100;
    // 读取内容和行号
    String line = null;
    while((line = lfr.readLine()) != null){
        System.out.println(lfr.getLineNumber + " : " + line);
    } 
    // 关闭流
    lfr.close();
}

*方法介绍 : *

一、构造方法
    LineNumberReader(Reader in);
        使用默认输入缓冲区大小,创建行编号reader。
    LineNumberReader(Reader in,int sz);
        使用指定大小的输入缓冲区,创建行编号Reader。
        throws IllegalArgumentException when sz < 0
二、成员方法
    public void setLineNumber(int lineNumber);
        设置当前行号
    public int getLineNumber();
        获取当前行号。

9、readLine()的实现原理

public static void main(String[] args)throws IOException 
{
    // readLine()底层实现是使用的数组,我这使用的是StringBuilder效果是一样的。
    FileReader fr = new FileReader("PersonDemo.java");

    LineNumberReader lnr = new LineNumberReader(fr);

    String line = null;
    lnr.setLineNumber(100);
    while((line=lnr.readLine())!=null)
    {
        System.out.println(lnr.getLineNumber()+":"+line);
    }
    lnr.close();
}

10、装饰设计模式和继承的区别

1、 继承体系
    MyReader // 专门用于读取数据的类。
        |--MyTextReader
            |--MyBufferedTextReader
        |--MyMediaReader
            |--MyBufferedMediaReader
        |--MyDataReader
            |--MyBufferedDataReader
        .
        .    
        .
问题就来了,MyReader每次增加一个子类都要增加一个相应的BufferedReader子类。
    造成类的体系过于臃肿。类的扩展性很差。
2、装饰设计模式体系
    MyReader // 专门用于读取数据的类。
        |--MyBufferedReader
        |--MyTextReader
        |--MyMediaReader
        |--MyDataReader
        .
        .    
        .
    类的扩展性强。单独描述缓冲内容,将需要被缓冲的对象作为参数传递进缓冲区。优化了体系结构。

四、字节流

字节流:InputStream、OutputStream。

1、FileOutputStream 基本用法

示例代码 :*

public static void main(String[] args){
    // 创建输出流对象
    FileOutputStream out = new FileOutputStream("1.txt");
    // 输出数据
    out.write("abcd".getBytes());
    // 关闭流
    out.close();
}

方法介绍 :

一、构造方法:
    FileOutputStream(File file);
        创建一个指向File的文件输出流对象。
    FileOutputStream(File file,boolean append);
        创建文件输出流,并指明是否追加内容。
    FileOutputStream(String filename);
    FileOutputStream(String filename,boolean append);

2、FileInputStream基本用法

示例代码 :

public static void main(String[] args)throws IOException{
    FileInputStream in = FileInputStream("1.map");
    int ch = 0;
    while((ch = in.read()) != -1){
        System.out.println("字符 : " + (char)in);
    }
    in.close();
}

方法介绍 :

一、构造方法
    1、FileInputStream(File file);
    2、FileInputStream(String filename);
二、成员方法
    1、public int available();
        返回可以不受阻塞地从此文件输出流中的读取的字节数。

字符流实现拷贝图片

public static void main(String[] args){
    FileOutputStream out = null;
    FileInputStream in = null;
    try{
        out = new FileOutputStream("copy_1.bmp");
        in = new FileInputStream("1.bmp");
        byte[] tmp = new byte[1024];
        int len = 0;
        while((len = in.read(tmp)) != -1){
            out.write(tmp,0,len);
        }
    }catch(IOException e){
        throw RuntimeException("流创建失败");
    }finally{
        try{
            if(in != null)
                in.close();
        }catch(IOException ee){
            throw RuntimeException("输入流关闭失败");
        }
        try{
            if(out != null)
                out.close();
        }catch(IOException ee){
            throw RuntimeException("输出流关闭失败");
        }
        
    }
}

3、带缓冲区的字节流

示例代码 :

public void copy_1() throws IOException{
    BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream("copy_1.mp3"));
    BufferedInputStream fis = new BufferedInputStream(new FileInputStream("1.mp3"));
    
    int ch = 0;
    
    while((ch = fis.read()) != -1){
        fos.write(ch);
    }
    
    fos.close();
    fis.close();
    
}    

BufferedOutputStream介绍

一、构造方法:
    1、BufferedOutputStream(OutputStream out);
        创建一个带有默认长度缓冲区的,字节输出流。
    2、BufferedOutputStream(OutputStream out,int sz);
        创建一个指定长度缓冲区的字节输出流。
        throws IllegalArgumentException when sz < 0    ;

BufferedInputStream介绍

一、构造方法
    BufferedInputStream(InputStream in);
        创建一个默认缓冲区大小的字节输入流。
    BufferedInputStream(ImputStream in,int sz);
        创建一个指定缓冲区大小的字节输入流。
二、其他方法
    public int available();
        返回不受阻塞地从此流读取的字节数。

4、字节和字符流的相互转换

获取键盘输入流 :

// 获取键盘输入流。字节流
InputStream in = System.in;
// 将字节流转换成字符流对象。使用转换流对象,InputStreamReader
InputStreamReader ins = new InputStreamReader(in);
// 加入缓冲区技术
BufferedReader r = new BufferedReader(ins);
// 综上 ,获取键盘输入流的最常见写法。
BufferedReader rr = new BufferedReader(new InputStreamReader(System.in));

InputStreamReader介绍

InputStreamReader 是字节流通向字符流的桥梁:他使用指定的charset(字符编码)读取字节并将其解码为字符。
                  他使用的字符及可以显示自定,否则使用系统默认的字符集(JVM 环境)。
为了提高效率可以在BufferedReader中包装一个InputStreamReader。例如:
    BufferedReader r = new BufferedReader(new InputStreamReader(System.in));

一、构造方法:
    1、 InputStreamReader(InputStream in);
              创建一个默认字符集的InputStreamReader。
    2、 InputStreamReader(InputStream in,Charset cs);
            创建一个指定字符集的InputStreamReader。
    3、 InputStreamReader(InputStream in,CharsetDecoder csd);
            创建一个给定字符解码器的InputStreamReader。
    4、 InputStreamReader(InputStream in,String charsetName);
            创建一个指定字符集的InputStreamReader。
二、其他方法
    1、 public String getEncoding();
            返回此流所使用的字符编码名称。

标准输出流

// 获取标准输出流,字节流。
OutputStream out = System.out;
// 将字节流转换成字符流。
OutputStreamWriter outs = new OutputStreamWriter(out);
// 加入缓冲区技术
BufferedWriter w = new BufferWriter(outs);
// 综上,获取标准输出的最常见写法:
BufferedWriter ww = new BufferedWriter(new OutputStreamWriter(System.out));

OutputStreamWriter介绍

OutputStreamWriter 是字符流通向字节流的桥梁。使用自定的charset将指定的字符编码为字节。
字符集可以显示指定也可以默认。每次调用Write()都会针对给定的字符(字符集)调用编码转换器。
在写入基础流之前这些字节会在缓冲区中积累可以指定缓冲区大小。为了提高效率可以将
OutputStreamWriter封装到BufferedWriter中,例如:
    Writer out = new BufferedWriter(new OutputStreamWriter(System.out));

一、构造方法
    1、 OutputStreamWriter(OutputStream out);
              创建一个默认字符集的OutputStreamReader。
    2、 OutputStreamWriter(OutputStream out,Charset cs);
            创建一个指定字符集的OutputStreamReader。
    3、 OutputStreamWriter(OutputStream out,CharsetDecoder csd);
            创建一个给定字符解码器的OutputStreamReader。
    4、 OutputStreamWriter(OutputStream out,String charsetName);
            创建一个指定字符集的OutputStreamReader。
二、其他方法
    1、 public void flush();
            刷新该流的缓冲。
    2、 public String getEncoding();
            获取该流使用的字符编码名

五、流操作的基本规律

通过三个明确来完成:
1、 明确源和目的
    源:输入流 ,InputStream、Reader。
    目的:输出流,OutputStream、Writer。
2、操作数据是否是纯文本
    是:字符流
    否:字节流
3、明确体系后在明确所需要使用的对象。
    通过设备来区分:
    源设备:内存、硬盘、键盘。
    目的设备:内存、硬盘、控制台。

扩展:把录入的数据按照指定的编码表utf-8,将数据保存到文件中。
    分析: 
    1、 目的:OutputStream、Writer
    2、 文本:Writer
    3、 硬盘:FileWriter
    
    4、 指定编码,因此使用转换流。
    BufferedWriter w = 
    new BufferedWriter(new OutputStreamWriter(new FileOutputStream("1.txt"),"utf-8));

注意:通常在需要进行编码转换时使用转换流。字符通向字节。

你可能感兴趣的:(WSJ--Java IO学习笔记)