Java基础系列(十九)字节流和字符流

一、字节输出流OutputStream

OutputStream此抽象类,是表示输出字节流的所有类的超类。操作的数据都是字节。
这里写图片描述

1.1、FileOutputStream类

OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件。
FileOutputStream类,即文件输出流,是用于将数据写入 File的输出流。
构造方法:
这里写图片描述

1.1.1、FileOutputStream类写入数据到文件中

//需求:将数据写入到文件中。
//创建存储数据的文件。
File file = new File("c:\\file.txt");
//创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
//输出流目的是文件,会自动创建。如果文件存在,则覆盖。
FileOutputStream fos = new FileOutputStream(file);
//调用父类中的write方法。
byte[] data = "abcde".getBytes();
fos.write(data);
//关闭流资源。
fos.close();

1.1.2、给文件中续写和换行

我们直接new FileOutputStream(file)这样创建对象,写入数据,会覆盖原有的文件,那么我们想在原有的文件中续写内容怎么办呢?
继续查阅FileOutputStream的API。发现在FileOutputStream的构造函数中,可以接受一个boolean类型的值,如果值true,就会在文件末位继续添加。
其构造方法如下:

这里写图片描述

File file = new File("c:\\file.txt");
FileOutputStream fos = new FileOutputStream(file, true);
String str = "\r\n"+"itcast";
fos.write(str.getBytes());
fos.close();

二、字节输入流InputStream

把内存中的数据读到内存中,我们通过InputStream可以实现。InputStream此抽象类,是表示字节输入流的所有类的超类,定义了字节输入流的基本共性功能方法。
这里写图片描述

2.1、FileInputStream类

InputStream有很多子类,其中子类FileInputStream可用来读取文件内容。
FileInputStream 从文件系统中的某个文件中获得输入字节
构造方法:
这里写图片描述

2.1.1、FileInputStream类读取数据read方法

File file = new File("c:\\file.txt");
//创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
FileInputStream fis = new FileInputStream(file);
//读取数据。使用 read();一次读一个字节。
int ch = 0;
while((ch=fis.read())!=-1){
    System.out.println("ch="+(char)ch);
}
// 关闭资源。
fis.close();

2.1.2、读取数据read( byte [ ] )方法

在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的read方法,一次可以读取多个字符。

/*
* 演示第二个读取方法, read(byte[]);
*/
File file = new File("c:\\file.txt");
// 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
FileInputStream fis = new FileInputStream(file);        
//创建一个字节数组。
byte[] buf = new byte[1024];    //长度可以定义成1024的整数倍。      
int len = 0;
while((len = fis.read(buf))!= -1){
    System.out.println(new String(buf,0,len));
}
fis.close();

三、字节流练习

1、复制文件

读取一个已有的数据,并将这些读到的数据写入到另一个文件中。

//1,明确源和目的。
File srcFile = new File("c:\\YesDir\test.JPG");
File destFile = new File("copyTest.JPG");
//2,明确字节流 输入流和源相关联,输出流和目的关联。
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
//3, 使用输入流的读取方法读取字节,并将字节写入到目的中。
int ch = 0;
while((ch=fis.read())!=-1){
    fos.write(ch);
}
//4,关闭资源。
fos.close();
fis.close();

上述复制文件有个问题,每次都从源文件读取一个,然后在写到指定文件,接着再读取一个字符,然后再写一个,一直这样下去。效率极低。

2、缓冲数组方式复制文件

File srcFile = new File("c:\\YesDir\test.JPG");
File destFile = new File("copyTest.JPG");
// 明确字节流 输入流和源相关联,输出流和目的关联。
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
//定义一个缓冲区。
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
    fos.write(buf, 0, len);// 将数组中的指定长度的数据写入到输出流中。
}
// 关闭资源。
fos.close();
fis.close();

四、字符流

经过前面的学习,我们基本掌握的文件的读写操作,在操作过程中字节流可以操作所有数据,可是当我们操作的文件中有中文字符,并且需要对中文字符做出处理时怎么办呢?

4.1、字节流读取字符的问题

通过以下程序读取带有中文的文件:

public static void main(String[] args) throws IOException {
    //给文件中写中文
    writeCNText();
    //读取文件中的中文
    readCNText();
}   
//读取中文
public static void readCNText() throws IOException {
    FileInputStream fis = new FileInputStream("c:\\cn.txt");
    int ch = 0;
    while((ch = fis.read())!=-1){
        System.out.println(ch);
    }
}
//写中文
public static void writeCNText() throws IOException {
    FileOutputStream fos = new FileOutputStream("c:\\cn.txt");
    fos.write("火之意志".getBytes());
    fos.close();
}

上述程序中我们读取拥有中文的文件时,使用的字节流在读取,那么我们读取到的都是一个一个字节。只要把这些字节去查阅对应的编码表,就能够得到与之对应的字符。API中是否给我们已经提供了读取相应字符的功能流对象,Reader,读取字符流的抽象超类。

4.2、字符输入流Reader

这里写图片描述

4.3、FileReader类

FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。FileReader读取包含中文的文件:

public static void main(String[] args) throws IOException {
    //给文件中写中文
    writeCNText();
    //读取文件中的中文
    readCNText();
}   
//读取中文
public static void readCNText() throws IOException {
    FileReader fr = new FileReader("D:\\test\\cn.txt");
    int ch = 0;
    while((ch = fr.read())!=-1){
        //输出的字符对应的编码值
        System.out.println(ch);
        //输出字符本身
        System.out.println((char)ch);
    }
}
//写中文
public static void writeCNText() throws IOException {
    FileOutputStream fos = new FileOutputStream("D:\\test\\cn.txt");
    fos.write("火之意志".getBytes());
    fos.close();
}

五、字符输出流Writer

既然有专门用于读取字符的流对象,那么肯定也有写的字符流对象,Writer是写入字符流的抽象类。其中描述了相应的写的动作。
这里写图片描述

5.1、FileWriter类

FileOutputStream 用于写入诸如图像数据之类的原始字节的流。要写入字符流,请考虑使用 FileWriter。构造方法如下:
这里写图片描述

5.1、FileWriter类写入中文到文件中

写入字符到文件中,先进行流的刷新,再进行流的关闭。

//演示FileWriter 用于操作文件的便捷类。
FileWriter fw = new FileWriter("d:\\text\\fw.txt");
fw.write("你好谢谢再见");//这些文字都要先编码。都写入到了流的缓冲区中。
fw.flush();
fw.close();

5.2、flush()和close()的区别?

这里写图片描述
flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用。
close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由close完成刷新并关闭。

猜你喜欢

转载自blog.csdn.net/weixin_41835916/article/details/80557062