字符流、字节流

字节流(输出流)

1.IO概述

I:Input 输入

O:output 输出

java 字节流设置编码格式 java字节输出流_System

顶层父类:

java 字节流设置编码格式 java字节输出流_java 字节流设置编码格式_02

2.字节输出流基本使用
  • OutputStream抽象类是表示字节输出流的所有类的超类,因为这个父类是一个抽象类,不能直接创建对象,如果要使用需要借助其子类FileOutputStream
  • 如何使用字节输出流?
    1)创:创建输出流对象
    2)写:借助流对象调用write方法写出数据
    3)关:关闭流资源 close
  • 构造方法
public FileOutputStream(File file)
public FileOutputStream(String file)

public FileOutputStream(File file,boolean append)
public FileOutputStream(String file,boolean append)
构造方法中都要关联一个文件【不管是文件对象,或者一个字符串文件路径】
  • 常用的方法
- public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
- public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
- public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
- public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
- public abstract void write(int b) :将指定的字节输出流。

【代码实践】

public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1)创:创建输出流对象
        //关联文件,用来保存输出的数据
        //public FileOutputStream(File file)
        //FileOutputStream fos = new FileOutputStream(new File("file10.txt"));
        //public FileOutputStream(String file)
        FileOutputStream fos = new FileOutputStream("file10.txt");

        //2)写:借助流对象调用write方法写出数据
        byte[] bytes = "Hello".getBytes();
        fos.write(bytes);

        //3)关:关闭流资源 close
        fos.close();

    }
}
3.字节输出流构造方法

FileOutputStream构造方法:
没有拼接功能:
每次关联文件时:如果文件不存在,会直接创建,如果存在会把内容清空

public FileOutputStream(File file)
public FileOutputStream(String file)

内部原理,就是调用了含有append的构造方法,把append默认为false

有拼接功能:

public FileOutputStream(File file,boolean append): 当第二个参数append为true时,具有拼接功能
public FileOutputStream(String file,boolean append): 当第二个参数append为true时,具有拼接功能

构造方法中都要关联一个文件【不管是文件对象,或者一个字符串文件路径】

public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创
        //没有拼接功能
        // FileOutputStream fos = new FileOutputStream("file11.txt");
        //有拼接功能
        FileOutputStream fos = new FileOutputStream("file11.txt", true);
         
        //2.写
        fos.write("CCCCC".getBytes());
        //3.关

        fos.close();

    }
}
4.字节输出流的写出方法
写出字节数据的方法:
public void write(byte[] bytes):写出所有字节数组中的字节
public void write(byte[] bytes,int off,int len): 写出字节数组的内容,从off索引开始的后面len个
public void write(int i): 写出的是一个字节
/*
public void write(byte[] bytes):写出所有字节数组中的字节
public void write(byte[] bytes,int off,int len): 写出字节数组的内容,从off索引开始的后面len个
public void write(int i): 写出的是一个字节
 */
public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1:创
        OutputStream os = new FileOutputStream("file12.txt", true);
        //2:写
        byte[] bytes = "abc123".getBytes();
        //public void write(byte[] bytes):写出所有字节数组中的字节
        //os.write(bytes);

        //public void write(byte[] bytes,int off,int len):
        // 写出字节数组的内容,从off索引开始的后面len个
        //os.write(bytes, 3, 3);

        //public void write(int i): 写出的是一个字节
        os.write(65);

        //3:关
        os.close();

    }

}
5.字节输出流写出换行
windows:  \r\n
linux: \r
可以借助System.lineSeparator()

String ls=System.lineSeparator(); //各种系统通用
public class Demo01 {
    public static void main(String[] args) throws IOException {
        //windows:  \r\n
        //linux: \r
        //可以借助System.lineSeparator()
        //String ls=System.lineSeparator(); //各种系统通用

        //1.创
        FileOutputStream fos = new FileOutputStream("file13.txt");
        //2.写
        fos.write("窗前明月光".getBytes());
        fos.write("\r\n".getBytes());
        fos.write("疑是地上霜".getBytes());
        //String ls = System.lineSeparator();//换行符
        //fos.write(ls.getBytes());
        fos.write(System.lineSeparator().getBytes());
        fos.write("举头望明月".getBytes());

        //3.关
        fos.close();
    }
}

字节流(输入流)

1.字节输入流的使用

字节输入流的顶层父类是InputStream,是一个抽象类,这里定义了所有字节输入流所要使用的方法。

使用时借助其子类FileInputStream.

入门使用

1)创:创建输入流对象==[需要关联文件]==

public FileInputStream(String file)
public FileInputStream(File file)

2)读:调用read方法读取数据

public int read():一次读取一个字节返回,如果没有返回-1
public int read(byte[] bytes):一次读取多个字节放到数组,返回有效读取的个数,如果没有返回-1

3)关:调用close方法关资源

public void close():关流

【代码实践】

/*
字节输入流的基本使用:
 */
public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创
        FileInputStream fis = new FileInputStream("file01.txt");
        //2.读
        //int read()
        //传统写法:不会这么去读取
        //int r = fis.read();
        //System.out.println("r = " + r);
        //System.out.println(fis.read());//98
        //System.out.println(fis.read());//99
        //System.out.println(fis.read());//-1 //表示结束

        //优化写法:以后就这么写
        int b;
        while ((b=fis.read())!=-1) {
            System.out.println(b);
        }


        //3.关
        fis.close();
    }
}
读取数据的代码优化

字节输入流:
1)创
2)读
3)关

/*
public int read(byte[] bytes):读取多个数据到字节数组,返回有效读取字节个数,如果没有读取到字节返回-1
 */
public class Demo02 {
    public static void main(String[] args) throws IOException {
        //1.创
        FileInputStream fis = new FileInputStream("file02.txt");
        //2.读
        //写法一:
        //byte[] bytes = new byte[3];
        //int len = fis.read(bytes);
        //System.out.println(len+":"+ Arrays.toString(bytes));//3:[97, 98, 99]
        //len = fis.read(bytes);
        //System.out.println(len+":"+ Arrays.toString(bytes));//1:[49, 98, 99]
        //len = fis.read(bytes);
        //System.out.println(len+":"+ Arrays.toString(bytes));//-1:[49, 98, 99]


        //写法二:高效读取
        byte[] bytes = new byte[10];
        int len;

        while ((len = fis.read(bytes)) != -1) {
            //String
            System.out.println(new String(bytes,0,len));
          //将字节数组中从0开始往后len个字节数据变成字符串
        }

        //3.关
        fis.close();

    }
}
2.文件拷贝
需求:
完成 img1/美女.jpg  拷贝到  img2/beauty.jpg

思路:
借助FileInputStream 读取读取数据到内存,然后借助OutputStream写出数据到目标文件

步骤:
1)创:分别创建字节输入和输出流对象
2)读写 : 边读边写
3)关 : 关流
public class Demo01 {
    public static void main(String[] args) throws IOException {
        //完成 img1/美女.jpg  拷贝到  img2/beauty.jpg
        //1)创:分别创建字节输入和输出流对象
        FileInputStream fis = new FileInputStream("img1/美女.jpg");
        FileOutputStream fos = new FileOutputStream("img2/beauty.jpg");
        //2)读写 : 边读边写

        //int b;//临时保存读取的字节
        //while ((b = fis.read()) != -1) {
        //    //将读取的字节,写道文件中
        //    fos.write(b);
        //}


        byte[] bytes = new byte[1024];
        int len;
        while ((len = fis.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
        }


        //3)关 : 关流
        fos.close();
        fis.close();
    }
}
3.字节流读取文本乱码问题
使用字节输入流读取中文:
字节流不适合用来处理文本数据,字符流才适合用来处理文本数据
public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创
        FileInputStream fis = new FileInputStream("file03.txt");
        //2.读
        //int b;
        //while ((b = fis.read()) != -1) {
        //    System.out.println((char)b);
        //}

        byte[] bytes = new byte[2];
        int len;
        while ((len = fis.read(bytes)) != -1) {
            System.out.println(new String(bytes, 0, len));
        }

        //3.关
        fis.close();
    }
}

java 字节流设置编码格式 java字节输出流_java 字节流设置编码格式_03

字符流(输入流)

字符输入流的使用

和字节输入流的操作一样

Reader是一个抽象类,是字符输入流的超类,定义了字符输入流的相关方法。

实际使用时,用其子类FileReader

基本使用步骤

1)创

构造方法:
public FileReader(String path)
public FileReader(File path)

2)读: 调用read方法读取字符

public int read(): 一次读取一个字符,如果读取到最后没有内容,返回-1
public int read(char[] chars): 一次读取多个字符,返回有效读取的字符个数,如果没有内容了,返	回-1

3)关: 调用close

public void close()
【代码实践】
import java.io.FileReader;
import java.io.IOException;

public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创
        FileReader fr = new FileReader("file03.txt");
        //2.读
        //int read():读取一个字符,没有字符返回-1

        //System.out.println((char) fr.read());
        //System.out.println((char) fr.read());
        //System.out.println((char) fr.read());
        //System.out.println((char) fr.read());
        //System.out.println((char) fr.read());
        //System.out.println((char) fr.read());
        //System.out.println((char) fr.read());
        //System.out.println((char) fr.read());
        //System.out.println((char) fr.read());
        //System.out.println( fr.read());//-1
        //System.out.println( fr.read());//-1

        // int c;
        // while ((c = fr.read()) != -1) {
        //     System.out.println((char) c);
        // }


        //int read(char[] cbuf):读取多个字符到字符数组,返回读取有效个数,如果没有返回-1
        char[] cbuf = new char[2];
        int len;
        while ((len = fr.read(cbuf)) != -1) {
            //读取的有效字符变成字符串
            System.out.println(new String(cbuf, 0, len));
        }


        //3.关
        fr.close();
    }
}

字符流(输出流)

字符输出流的使用

和字节输出流使用极其相似

字符输出流的超类是Writer,是抽象类,里面定义了一些字符输出流通用的方法

public void close(): 关流
    public void flush(): 刷新
    public void write(int c) :写出一个字符
    public void write(char[] chars) :一次写出一个字符数组
    public void write(char[] chars,int off, int len) :一次写出一个字符数组中指定的字符
    public void write(String str) :一次写出一个字符串
    public void write(String str,int off, int len)

真正使用时,使用的是其子类FileWriter

使用步骤

  1. 构造方法:
//没有拼接
public FileWriter(String fileName)
public FileWriter(File file)
//有拼接,但是append要为true
public FileWriter(String fileName , boolean append)
public FileWriter(File file , boolean append)
  1. 写:调用write方法
public void write(int c) :写出一个字符
public void write(char[] chars) :一次写出一个字符数组
public void write(char[] chars,int off, int len) :一次写出一个字符数组中指定的字符
public void write(String str) :一次写出一个字符串
public void write(String str,int off, int len)
  1. 关:调用close
public void close(): 关流
代码实践
/*
字符输出流的基本使用
 */
public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创
        //没有拼接
        // FileWriter fw = new FileWriter("file04.txt");

        //拼接
        FileWriter fw = new FileWriter("file04.txt",true);
        //2.写
        //write(int c)
        fw.write('A');
        //write(char[] chars)
        char[] chars = {'a', '1', '我'};
        fw.write(chars);
        //write(char[] chars,int off,int len)
        fw.write(chars,1,2);
        fw.write(System.lineSeparator());//换行
        //write(String str)
        fw.write("静夜思");
        fw.write("\r\n");//换行
        //write(String str,int off,int len)
        fw.write("静夜思",1,2);

        //3.关
        fw.close();

    }
}

关闭和刷新的区别

关闭和刷新

关闭:关流,把缓冲区的数据刷出【关流+刷新】
public void close()
刷新:把缓冲区的数据刷出到硬盘或者其他存储介质【就是刷新】
public void flush()
/*
关闭和刷新的区别
关闭:close  关闭后不能继续写【刷新+关闭资源】
刷新:flush  刷新后可以继续写【刷新】
 */
public class Demo02 {
    public static void main(String[] args) throws IOException {
        //1.创
        FileWriter fw = new FileWriter("file05.txt");
        //2.写
        fw.write("我爱香港!!");//将字符数据临时保存到缓冲区
        fw.flush();//将缓存中的数据写出到文件中

        fw.write("一国两制");
        fw.flush();
        //3.关
        fw.close();
        //fw.write("我爱祖国");
    }
}

字符流和字节流的使用区别

字符流的使用场景:当处理纯文本字符数据时,可以使用字符流

字节流的使用场景:常处理字节数据时的复制拷贝,可以使用字节流: 比如,图片,视频,超文本文件的处理

IO异常的处理

JDK7之前的处理方式:

try - catch - finnaly进行处理
关流的动作,需要放到finally中,如果存在多个流需要关闭,可以自定义一个专门用来关流的工具类
/*
try - catch - finnaly进行处理
关流的动作,需要放到finally中,如果存在多个流需要关闭,可以自定义一个专门用来关流的工具类
 */
public class Demo01 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //完成 img1/美女.jpg  拷贝到  img2/beauty.jpg
            //1)创:分别创建字节输入和输出流对象
            fis = new FileInputStream("img1/美女.jpg");
            fos = new FileOutputStream("X:/img2/beauty.jpg");
            //2)读写 : 边读边写


            byte[] bytes = new byte[1024];
            int len;
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3)关 : 关流
            //CloseUtil.close(fos, fis);
            //CloseUtil.close(fos, fis);
            CloseUtil.close(fis,fos);


        }
    }
}

工具类

/*
关流工具类的优化
 */
public class CloseUtil {
    //杜绝其他类创建这个工具类的对象
    private CloseUtil(){}

    public static void close(AutoCloseable... resource) {
        for (AutoCloseable r : resource) {
            try {
                if (r != null)
                    r.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

JDK7 处理方式

优点就是可以自动关流,可以使用try-with-resource

【格式】

try (创建流对象语句,如果多个,使用';'隔开) {
   // 读写数据
} catch (IOException e) {
   e.printStackTrace();
}

【代码实践】

/*
try-whit-resource:自动关流


 */
public class Demo02 {
    public static void main(String[] args) {

        //1)创:分别创建字节输入和输出流对象
        try (FileInputStream fis = new FileInputStream("img1/美女.jpg");
             FileOutputStream fos = new FileOutputStream("img2/beauty.jpg")
        ) {

            //2)读写 : 边读边写

            byte[] bytes = new byte[1024];
            int len;
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

属性集

属性集使用

Properties: 属性集 ,是HashTable的子类 HashTable又是Map接口的实现类,Properties内部存储的数据,就是键值对。

基本方法使用

特有方法:
- public Object setProperty(String key, String value) : 保存一对属性。 【put】
- public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。【get】
- public Set<String> stringPropertyNames() :所有键的名称的集合。 【keySet】

【代码实践】

public class Demo01 {
    public static void main(String[] args) {
        Properties pro = new Properties();
        //Object setProperty(String key, String value) : 保存一对属性。 【put】
        pro.setProperty("username", "root");
        pro.setProperty("password", "root");
        pro.setProperty("driverClass", "com.mysql.jdbc.Driver");
        pro.setProperty("url", "jdbc:mysql:///day01");

        System.out.println("pro = " + pro);

        //String getProperty(String key) :使用此属性列表中指定的键搜索属性值。【get】
        //Object username = pro.get("username");
        String username = pro.getProperty("username");
        System.out.println("username = " + username);

        //Set<String> stringPropertyNames() :所有键的名称的集合。 【keySet】
        Set<String> names = pro.stringPropertyNames();
        System.out.println("names = " + names);

    }
}

和流相关的方法

存储属性集中的键值对信息到配置文件
public void store(Writer write,String comments) : 
		write 是一个字符输出流需要关联一个文件,comments是注释
public void store(OutputStream out,String comments) :
		write 是一个字符输出流需要关联一个文件,comments是注释
//将内存中的Properties属性信息保存到文件中
//void store(Writer write,String comments) :write 是一个字符输出流需要关联一个文件,comments是注释
//void store(OutputStream out,String comments) :write 是一个字符输出流需要关联一个文件,comments是注释

try (FileWriter fileWriter = new FileWriter("mysql.properties");) {
    pro.store(fileWriter, "This is comments, 这是注释");
} catch (IOException e) {
    e.printStackTrace();
}
如果要加载本地文件的键值对信息到Properties中
public void load(InputStream in):传入的流目的就是关联配置文件
public void load(Reader in):传入的流目的就是关联配置文件
public class Demo02 {
    public static void main(String[] args) {
        Properties pro = new Properties();
        System.out.println("pro = " + pro);

        //void load(InputStream in):传入的流目的就是关联配置文件
        //void load(Reader in):传入的流目的就是关联配置文件
        try (FileReader reader = new FileReader("mysql.properties");) {
            pro.load(reader);//加载配置文件中的属性信息到pro对象
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("pro = " + pro);

    }
}
tore(fileWriter, "This is comments, 这是注释");
} catch (IOException e) {
    e.printStackTrace();
}
如果要加载本地文件的键值对信息到Properties中
public void load(InputStream in):传入的流目的就是关联配置文件
public void load(Reader in):传入的流目的就是关联配置文件
public class Demo02 {
    public static void main(String[] args) {
        Properties pro = new Properties();
        System.out.println("pro = " + pro);

        //void load(InputStream in):传入的流目的就是关联配置文件
        //void load(Reader in):传入的流目的就是关联配置文件
        try (FileReader reader = new FileReader("mysql.properties");) {
            pro.load(reader);//加载配置文件中的属性信息到pro对象
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("pro = " + pro);

    }
}