在程序中一个字符等于两个字节,那么 Java 提供了 Reader 和 Writer 两个专门操作字符流的类
一、字符输出流 Writer
Writer 本身是一个字符流的输出类,定义:
public abstract class Writer extends Object implements
Appendable,Closeable,Flushable
//Appendable 表示可以通过该接口向输出流中追加内容
此类本身也是一个抽象类,要使用该类,必须要使用其子类,如果要向文件中写入内容,应该使用 FileWriter 的子类。
1. 向文件中写入数据
这里与 OutputStream 的操作流程并没有什么太大的区别,唯一的好处是不用将字符串变为 byte 数组之后再输出,可以直接输出
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
public class Root{
public static void main(String[] args) throws Exception{
//异常抛出,不处理
// 第一步:使用File类找到一个文件
File f = new File("D:" + File.separator + "test.txt");
// 第二步:通过子类实例化父类对象
Writer out = new FileWriter(f);//通过对象多态性,进行实例化
// 第三步:进行写操作
String str = "Hello World !!!";
out.write(str);//将内容 输出
// 第四步:关闭输出流
out.close();
}
}
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
2. 使用 FileWriter 追加文件的内容
public class Root{
public static void main(String[] args) throws Exception{
//异常抛出,不处理
// 第一步:使用File类找到一个文件
File f = new File("D:" + File.separator + "test.txt");
// 第二步:通过子类实例化父类对象
Writer out = new FileWriter(f,true);//通过对象多态性,进行实例化
// 第三步:进行写操作
String str = "\r\n Java Hello World !!!";
out.write(str);//将内容 输出
// 第四步:关闭输出流
out.close();
}
}
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
二、字符输入流 Reader
Reader 是使用字符的方式从文件中取出数据,他也是抽象类通需要需要使用 FileReader 子类对其使用
1. 从文件中读取内容
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 f = new File("D:" + File.separator + "test.txt");
// 第二步:通过子类实例化父类对象
Reader reader = new FileReader(f);;
// 第三步:进行读操作
char c[] = new char[1024];//将所有内容读到此数组中
int len = reader.read(c);//将内容输出
// 第四步:关闭输入流
reader.close();
// 把char数组变为字符串输出
System.out.println("内容为:" + new String(c,0,len));
}
}
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
2. 使用循环的方式读取内容
如果此时不知道数据的长度,也可以使用循环的方式进行内容的读取
char c[] = new char[1024];//将所有内容读到此数组中
int len = 0;
int temp = 0;
while ((temp = reader.read()) != -1){
// 将每次的读取内容给temp变量,如果temp的值不是-1,则表示文件没有读完
c[len] = (char)temp;
len++;
}
// 第四步:关闭输入流
reader.close();
// 把char数组变为字符串输出
System.out.println("内容为:" + new String(c,0,len));
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
三、字节流和字符流的区别
字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件
进一步解释就是如果关闭字节或字符的操作(out.close()
),通过字节流依然会出现结果,因为字节流直接操作文件,但是如果是字符流操作,不关闭则不会出现效果,因为关闭字符流,才会强制性将缓存区的内容进行输出
使用字节流更好
因为所有的文件在硬盘或在传输时都是以字节的方式进行的,包括图片等都是按字节的方式进行的,包括图片等都是按照字节的方式存储的,而字符是只有在内存中才会形成,所以字节流的使用更为广泛
四、文件复制
程序运行时可以按照如下格式:
java Copy 源文件 目标文件
- 1
此时想要完成将D盘中的test.txt文件复制到D盘中的 demo.txt 文件
此时要完成这样的复制程序,可以用两种方式操作:
(1)将源文件中的内容全部读取到内存,并一次性写入到目标文件中:字符输入输出方式
(2)不讲源文件中的内容全部读取进来,采用边读边写的方式:字节输入输出方式
很明显,第(2)种方法更好合理,因为如果内容过多,则整个内存是无法装下的,程序肯定会出现异常,而如果采用边读边写的方式,肯定比全部读进来性能高很多
import java.io.*;
public class Copy {
public static void main(String[] args) throws Exception{
if (args.length != 2) {
// 判断是否是两个参数
System.out.println("输入的参数不正确!");
System.out.println("例:java Copy 源文件路径 目标文件路径");
System.exit(1);//系统退出
}
File f1 = new File(args[0]);//源文件的 File 对象
File f2 = new File(args[1]);//目标文件的File对象
if (!f1.exists()) {
System.out.println("源文件不存在!");
System.exit(1);
}
InputStream input = new FileInputStream(f1);//准备好输入流对象,读取源文件
OutputStream out = new FileOutputStream(f2);//准备好输出流对象,写入目标文件
if (input != null && out != null) {//判断输入或输出是否准备好
int temp =0;
try{
while ((temp=input.read())!=-1){//开始复制
out.write(temp);//边读边写
}
System.out.println("复制完成");
}catch (IOException e){
e.printStackTrace();
}
input.close();
out.close();
}
}
}
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33