字节流和字符流
1:背景
在java包里面File包中File类是唯一一个与文件本身有关的程序类,但是File只能够操作文件本身而不能操作文件的内容,或者说在实际的开发中IO操作的核心意义在于:输入和输出操作。
对于程序而言,输入和输出可能来自不同的环境,例如:通过电脑连接服务器上进行浏览的时候,实际上此时上客户端发出了一个信息,而服务器接收信息后进行回应处理。(如下图)
对于服务器或者是客户端实质上传递的就是一种数据流的处理形式,而所谓的数据流指的是字节数据,而对于流的处理形式在java.io包里面提供有两种支持:
字节处理流:OutputStream(输出字节流),InputStream(输出字节流)
字符处理流:Writer(输出字符流),Reader(输入字符流)
2:所有流操作统一步骤
以文件处理的流程为例:
*3:字节输出流 :OutputStream *
OutputStream类定义的是一个公共的输出标准操作,在这个操作标准里面一共定义有三个内容输出方法。
4:使用OutputStream类实现内容的输出
注意:OutputStream类是一个抽象类,要想实例化对象,应该通过子类实例化的向上转型完成。
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class Test {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "hello" +
File.separator + "mldn.txt"); // 1、指定要操作的文件的路径
if (!file.getParentFile().exists()) { // 文件不存在
file.getParentFile().mkdirs() ; // 创建父目录
}
OutputStream output = new FileOutputStream(file) ; // 2、通过子类实例化
String str = "www.mldn.cn" ; // 要输出的文件内容
output.write(str.getBytes()); // 3、将字符串变为字节数组并输出
output.close(); // 4、关闭资源
}
}//输出结果如下图
5:自动关闭处理
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); // 1、指定要操作的文件的路径
if (!file.getParentFile().exists()) { // 文件不存在
file.getParentFile().mkdirs(); // 创建父目录
}
try (OutputStream output = new FileOutputStream(file, true)) {
String str = "www.mldn.cn\r\n"; // 要输出的文件内容
output.write(str.getBytes()); // 3、将字符串变为字节数组并输出
} catch (IOException e) {
e.printStackTrace();
}
}
}//运行结果如下,每运行一次,多一条String内容
6:字节输入流:InputStream
7:InputStream读取数据
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class Test {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt");
InputStream input = new FileInputStream(file) ;
byte data [] = new byte [1024] ; // 开辟一个缓冲区读取数据
int len = input.read(data) ; // 读取数据,数据全部保存在字节数组之中,返回读取个数
System.out.println("【" + new String(data, 0, len) + "】");
input.close();
}
}
//输出结果
【www.mldn.cnwww.mldn.cn
www.mldn.cn
www.mldn.cn
www.mldn.cn
www.mldn.cn
】
对于字节输入流里面最麻烦的问题在于:使用read()方法读取的时候只能够以字节数组为主进行接收。
8:新方法
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class Test {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt");
InputStream input = new FileInputStream(file) ;
byte data [] = input.readAllBytes() ; // 读取全部数据
System.out.println("【" + new String(data) + "】");
input.close();
}
}//运行结果
【www.mldn.cnwww.mldn.cn
www.mldn.cn
www.mldn.cn
www.mldn.cn
www.mldn.cn
】
上述代码存在的问题:如果要读取的内容很大的时候,这种方法会搞死这种程序
9:字符输出流:Writer
使用OutputStream字节输出流进行数据输出的时候使用的都是字节类的数据,而很多的情况下字符串的输出是比较方便的,所以对于java.io包而言,在JDK1.1的时候又推出了字符输出流:
10:使用Writer输出
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
public class Test {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs(); // 父目录必须存在
}
Writer out = new FileWriter(file) ;
String str = "jiaowoxiaochaochao" ;
out.write(str);
out.close();
}
}
使用Writer输出的最大优势在于可以直接利用字符串完成。Writer是字符流,字符处理的优势在于中文数据上。
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
public class Test {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs(); // 父目录必须存在
}
Writer out = new FileWriter(file) ;
String str = "www.mldn.cn\r\n" ;
out.write(str);
out.append("不忘初心,方得始终") ; // 追加输出内容
out.close();
}
}
11:字符输入流:Reader
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
public class Test {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt");
if (file.exists()) { // 文件存在则进行读取
Reader in = new FileReader(file) ;
char data[] = new char[1024];
int len = in.read(data) ;
System.out.println("读取内容:" + new String(data,0,len));
in.close();
}
}
}
//读取内容:www.mldn.cn
//不忘初心,方得始终
字符流读取的时候只能够按照数组的形式来实现处理操作。
12:字节流和字符流的区别
a:不使用强制刷新。
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
public class Test {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs(); // 父目录必须存在
}
Writer out = new FileWriter(file) ;
String str = "你的多情出卖我的爱情,赔了我的命,我卖了一个世界却换来了灰烬" ;
out.write(str);
//out.flush(); // 强制性刷新
}
}
b:使用强制刷新
字节流在进行处理的时候并不会使用到缓冲区,而字符会使用到缓冲区。另外使用缓冲区的字符流更加适合于进行中文数据的处理,所以在日后的程序开发之中,如果要涉及到中文信息的输出一般会采用字符流处理,但是从另一方面来讲,字节流和字符流的基本处理形式是相似的,由于IO很多情况下都是进行数据的传输使用(二进制)。
13:转换流
所谓的转换流指的是可以实现字节流与字符流操作的功能转换,例如:进行输出的时候OutputStream需要将内容变为字节数组流后才可以输出,而Writer可以直接输出字符串,这一点是方便的,所以很多人就认为需要提供有一种转换机制,java.io包里面提供有两个类:InputStreamReader,OutputStreamWriter
通过类的继承结构与方法可以发现,所谓的转换处理就是将接收到的字节流对象通过向上转型变为字符流对象。
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class Test {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs(); // 父目录必须存在
}
OutputStream output = new FileOutputStream(file) ;
Writer out = new OutputStreamWriter(output) ; // 字节流变为字符流
out.write("烦死喽,面试还在实验室,不能自己找个地方,真是的!有些人的轻松真实令人捉急"); // 直接输出字符串,字符流适合于处理中文
out.close();
}
}
观察一下FileWriter,FileReader类