FileReader
字符输入流+访问文件==FileReader
当我们要对文件进行读入操作时,我们可以使用FileReader进行操作。
具体的操作的步骤用代码来一步步介绍:
为了完成操作,我们要事先再相对路径创建一个txt文件(我创建了一个hello.txt)
hello.txt内容是:HelloWorld123
1,File file=new File("hello.txt");
2,FileReader fr = new FileReader(file);
3,int data;
while((data=fr.read())!=-1){
System.out.print((char)data);
}
4,fr.close();
上面的编号是大致的步骤:
我们可以将其归纳为:
1,实例化File对象,指明要操作的文件
2,提供具体的流
3,数据的读入
4,流的关闭
接下来来看完整的代码:
public void textFileReader() {
FileReader fr= null;
try {
//1,实例话File对象,指明要操作的文件
File file=new File("hello.txt");
//2,提供具体的流
fr = new FileReader(file);
//3,数据的读入
//read():返回读入的一个字符。如果达到文件末尾,返回-1
int data;
while((data=fr.read())!=-1){
System.out.print((char)data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4,流的关闭操作
try {
if (fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
上面代码有写要注意的点:
1,写代码时,会有多处会报异常,当我们写到一定步骤时,先把异常往上抛(等等讲原因)。
2,第三步骤:我们要知道,当我们文件读入到文件末尾时,会返回-1;while括里的意思是:我们先将读到的信息赋值给data(注意是int型的),之后判断是否到达文件末尾(返回-1)。之后打印(将其转化为字符型)
(System.out.print():表示输出不换行。若我们使用的时println,将每一行打印一个字符)
3,记住:要关闭流(java对物理的垃圾不会自回收,比如:socket)
4,把具体步骤写完后,因为我们之前是把异常往上抛了,现在要将throws改为try-catch-finally。不能使用throws,如果我们使用的是throws,比如当我们第三个步骤出现异常,下面的代码就不会运行了,我们就少了关闭流的操作,会导致资源的浪费。(前面将异常往上抛是因为:写的时候会出现多处异常,为了方便)
(将整个代码块try的快捷键:Ctrl+alt+t)
5,finally:if语句:如果步骤二(一)就报异常,所以就不会创建流对象,就不需要关闭流。
由上面的代码,我们可以总结几点:
1,read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1
2,异常处理:为了保证资源一定可以执行关闭操作。需要使用try-catch-finally来处理
3,读入的文件一定要存在,否者就会报异常(FileNotFoundException)
我们也可以发现一个问题,也就是我们打印是一个一个打印的,对此我们一般使用read的重载方法
代码如下:
@Test
public void textFileReader2() {
FileReader fr= null;
try {
//1,File类的实例化
File file=new File("hello.txt");
//2,FileReader流的实例化
fr = new FileReader(file);
//3,读入的操作
//read(char[] cbuf):返回每次读入cbuf数组中的字符个数,如果达到文件末尾,返回-1
char[] cbuf=new char[5];
/**
* 重点难点:
*/
int len;
while((len=fr.read(cbuf))!=-1){
// 错误写法:
// for(int i=0;i<cbuf.length;i++){
// System.out.print(cbuf[i]);
// }
// 正确写法:
for(int i=0;i<len;i++){
System.out.print(cbuf[i]);
}
String str=new String(cbuf,0,len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4,资源的关闭
try {
if(fr!=null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
相比第一个方法,只有在第三步骤上做了修改,其余步骤和第一个方法一致。
所以我们将第三步骤拿出来,单独分析:
//3,读入的操作
//read(char[] cbuf):返回每次读入cbuf数组中的字符个数,如果达到文件末尾,返回-1
char[] cbuf=new char[5];
/**
* 重点难点:
*/
int len;
while((len=fr.read(cbuf))!=-1){
// 错误写法:
// for(int i=0;i<cbuf.length;i++){
// System.out.print(cbuf[i]);
// }
// 正确写法:
for(int i=0;i<len;i++){
System.out.print(cbuf[i]);
}
// String str=new String(cbuf,0,len);
// System.out.print(str);
}
第三个步骤的意思是:创建一个char数组(相当于车的容量);用int来记录char数组的长度(相当于记录这辆车装了多少东西);
点进去read():
可以看出返回的是一个int类型,返回的是参数的长度。
错误写法:
for(int i=0;i<cbuf.length;i++){
System.out.print(cbuf[i]);
}
因为"cbuf.length"是“车的容量”,所以你打印的时:HelloWorld123ld。
只是把前三个字符覆盖了
同理,不能使用 String(char)这个方法,而是使用String(char,0,len)这个方法。
FileWriter
从内存中写出数据到硬盘中
说明:
(1)输出操作,对应File可以不存在
(2)File对应硬盘中的文件如果不存在,在输出过程中,会自动创建文件
- 如果存在:
1,如果流的使用构造器是:FileWriter(file,false)/FileWriter(file):对原有文件的覆盖
2,如果流的使用构造器是:FileWriter(file,true):不会对原有文件内容覆盖,而是在原有文件内容基础上追加内容
@Test
public void MyFileWriter1() {
FileWriter fw= null;
try {
//File类实例化
File file=new File("hello.txt");
//提供具体的类
fw = new FileWriter(file,true);
//写出数据。如果对应的文件不存在,会自动创建文件
fw.write("\nI love you");
fw.write("在吗asd");
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
try {
if(fw!=null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
过程大致和FileReader相同。
接下来我们要做一件事:将一个文件的内容复制到另一个文件里。
代码的解释就不写了
@Test
public void ReaderWriter() {
String str=null;
//File实例化
File file=new File("hello.txt");
File file1=new File("hello1.txt");
//提供输入流
FileReader fr= null;
FileWriter fw= null;
try {
fr = new FileReader(file);
fw = new FileWriter(file1);
//读入操作,将数据从硬盘中读到内存中
char[] cbuf=new char[5];//车的容量
int len;
while((len=fr.read(cbuf))!=-1){
fw.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
try {
if(fr!=null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fw!=null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
首先,我个人的想法原本是值操作一个文件,也就是将一个文件的内容提取出来,再复制回去。之后发现试了好多种方法都不行,文件内容会变成空。所以,最后还是用了两个文件进行操作。(如果有大佬看到的话,还望多多指点,谢谢)