@[toc]
节点流(文件流)——字符流
字符:FileReader(读入数据)
:o::FileReader
说明(用read())
- read()的理解:返回读入的一个字符,如果达到文件末尾,返回1
- 异常处理注释:为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally
- 读入的文件一定要存在,否则就报异常:FileNotFoundException
- 具体过程在代码注释里面看
- FileReader中使用read(char[] cbuf)读入数据(将字符读入数组。如果已到达流的末尾,则返回 -1。否则返回本次读取的字符数。)
代码部分
注意:代码的内容都是先写主体再去try-catch-finally处理异常的(步骤即思路过程和编写过程)
/*
操作目的:将IoDay01下的hello.tet文件内容读入程序中,并输出到控制台
注:hello.tet文件内容:hello world!
*/
@Test
public void test() {
FileReader fr = null;
try {
//1.实例化File类的对象,指明要操作的文件
//相较于当前Module(这里是在单元测试里面写的代码,假如在main方法中写的,就是相较于当前工程)
File file = new File("hello.txt");//这里的hello文件我是创建在当前Module的,内容仅仅为:hello world!
//main方法中写法: File file = new File("(Module文件名)\\hello.txt");
//2.提供具体的流
fr = new FileReader(file);//当上面实例化File类的时候如果找不到该文件,就会报异常FileNotFoundException
//3.数据读入过程
//方式一:
/*
//read():返回读入的一个字符,如果达到文章末尾,返回-1;
int date = fr.read();
while (date!=-1){
System.out.print((char) date+" ");//返回的值需要转为char型
date = fr.read();//读完一个元素了得再读一个元素
}
//4.流的关闭操作
fr.close();
*/
//方式二:(语法上的修改)
int date;//定义date
while ((date=fr.read())!=-1){
System.out.println((char)date);
}//这样的好处是不用读完了再去读一个元素,把炒作放到了while判断中
} catch (IOException e) {
e.printStackTrace();
} finally {
//5.流的关闭操作
try {
if(fr!=null)
//这里是因为如果一开始提供具体流的时候就报异常(为什么会出异常看该段代码注释),
//直接跳到finally,那么还会报空指针异常,所以需要判断
fr.close();//fr不为空才进行关闭操作
} catch (IOException e) {
e.printStackTrace();
}
}
}
对read()操作升级:使用read的重载方法
@Test
public void test2() {
FileReader fr = null;
try {
//1.File类的实例化
File file = new File("hello.txt");
//2.FileReader流的实例化
fr = new FileReader(file);
//3。读入的操作
//read(char[] cubf):返回每次读入cbuf数组中的字符的个数,如果达到文章末尾,返回-1;
char[] arr = new char[5];//定义一个char型数组,长度为5(一次读入5个元素)
int len;//定义一个变量
//fr.read(arr);//以整数形式返回实际读取的数。
while ((len = fr.read(arr)) != -1) {
/*for (int i = 0; i <len; i++) {//长度为len,读入几个就遍历几次
System.out.println(arr[i]);
}*/
String str = new String(arr, 0, len);//char数组到String的转换
//上一行代码解释:如果形参直接写arr,那么最后一次取出来的如果小于len,答案又会错,所以取0到len
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fr != null)
//4.资源的关闭
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符:FileWriter
:o::FileWriter:从内存中写出数据到硬盘的文件里
说明
- 输出操作,对应的File可以不存在的并不会报异常
File对应的硬盘文件如果不存在:在输出的过程中,会自动创建此文件。
File对应的硬盘文件如果存在:
- 如果使用的构造器是FileWriter(file,fales)/FileWriter(file):对原有文件的覆盖
- 如果使用的构造器是FileWriter(file,true):不会对原文件覆盖,而是在原有基础上往后继续写
代码部分
@Test
public void test1() {
FileWriter fw = null;
try {
//1.提供File类对象,指明写出到的文件
File file = new File("hello2.txt");//该文件不存在,则新建一个,如果存在,就覆盖该文件
//2.提供FileWriter的对象,用于数据的写出
fw = new FileWriter(file);
//3.写出的操作
fw.write("I am KingsMan!");
fw.write("I have a dream!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.流的关闭
try {
if(fw!=null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
节点流(文件流)——字节流
注:使用FileInputStream和FileOutputStream的读入和输出,和前面字符的读入和输出是一模一样的,只是名字换一下,一个针对字符,一个针对字节,具体内容看总结部分
- 对于文本文件,使用字符流处理:.txt 、.java、.c 、.cpp等
- 对于非文本文件,使用字节流处理:.jpg、.mp3、.mp4、.avi、.doc等
测试部分
使用FileReader和FileWriter实现文本文件的复制
步骤
//1.创建File类的对象,指明读入和写出的文件
//2.创建输入流和输出流的对象
//3.数据的读入和写出操作
//4.关闭流资源
代码
@Test
public void test2() {
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
//1.创建File类的对象,指明读入和写出的文件
File infile = new File("hello.txt");
File outfile= new File("hello1.txt");
//2.创建输入流和输出流的对象
fileReader = new FileReader(infile);
fileWriter = new FileWriter(outfile);
//3.数据的读入和写出操作
char[] chars = new char[5];
int len;//记录每次读入到chars数组中的字符的个数
while ((len=fileReader.read(chars))!=-1){
fileWriter.write(chars,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流资源
try {
if (fileWriter!=null)
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fileReader!=null)
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结:
- 字符流不能处理图片文件,因为底层是字节而不是字符,具体参考下面部分:节点流(文件流)——字节流
使用FileInputStream和FileOutputStream实现对图片的复制操作
/*
实现对图片的复制操作
*/
@Test
public void test2() {
//
FileInputStream fis = null;
FileOutputStream fos = null;
try {
File infile = new File("柯基壁纸.jpg");
File outfile = new File("柯基壁纸2.jpg");
fis = new FileInputStream(infile);
fos = new FileOutputStream(outfile);
//复制的过程
byte[] bytes = new byte[5];
int len;
while ((len=fis.read(bytes))!=-1){
fos.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis!=null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fis!=null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用FileInputStream读取文本的测试
代码
@Test
public void test1(){
FileInputStream fis = null;
try {
File file = new File("hello.txt");
fis = new FileInputStream(file);
byte[] bytes = new byte[5];
int len;
while((len=fis.read(bytes))!=-1){
String s = new String(bytes,0,len);
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis!=null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结论
- 这里使用FileInputStream读取文本的操作,如果内容是英文字母和阿拉伯汉字,就没影响,如果是中文就会乱码,因为中文是三个字节一个汉字,总的来说,就是不可以用FileInputStream读取文本
使用FileReader和FileWriter去复制图片
注:字符流不能复制图片,这里就不用代码尝试了,结果是无法显式图片
总结
- 在写入一个文件时,如果使用构造器FileOutputStream(file),则目录下有同名文 件将被覆盖。
- 如果使用构造器FileOutputStream(file,true),则目录下的同名文件不会被覆盖, 在文件内容末尾追加内容。
- 在读取文件时,必须保证该文件已存在,否则报异常。
- 字节流操作字节,比如:.mp3,.avi,.rmvb,mp4,.jpg,.doc,.ppt
- 字符流操作字符,只能操作普通文本文件。最常见的文本文件:.txt,.java,.c,.cpp 等语言的源代码。尤其注意.doc,excel,ppt这些不是文 本文件。
- 定义文件路径时,注意:可以用“/”或者“\”。