三、节点流的使用
使用的基本的流程:
提供File类对象,指明要操作的文件路径
提供流对象,FileRead或FileWrite流节点流对象,直接作用于文件
执行读取或写出的操作,利用流对象的read或write方法
关闭流对象,防止内存泄漏资源浪费
- 字符输入流FileReader
字符输入流FileReader属于节点流,直接作用于源文件,用于文本数据的读取操作。
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
//将对应路径下的hello.txt文件打开,并读取其中的内容输出到控制台
//读取文件,前提是要求所读取的文件一定要存在,文件不存在,则流对象实例化的时候就会出现FileNotFound异常
public class Demo02 {
public static void main(String[] args){
FileReader fr = null;
//为了保证流资源一ing可以执行关闭操作,需要使用try-catch-finally处理
//finally里放流的关闭操作,当流对象创建完成在读取文件时出现异常,则会关闭流然后抛出异常;
try {
//1. 实例化File类的对象,指明要操作的文件
File file = new File(“F:\project\code\Filetest\hello.txt”);
//2. 提供具体的流,执行操作
fr = new FileReader(file);
//3. 执行数据的读入操作,调用流中的read方法
//read():返回读入的一个字符的编码值(返回值类型是int,因此是字符的编码值),若达到文件末尾,返回-1
//read的重载方法的使用
//read(char[] cbuf):返回每次读入cbuf数组的字符的个数,如果到达文件末尾,则返回-1
//read()空参构造器相当于每次读取一个字符,read(char[] cbuf):相当于有一个数组“小车”,每次读取多个字符
char[] chcar = new char[4];
int len;
/*
//运行结果为:helloworldor,这是因为数组每次读取都是固定值,当下一次读取的字符为填满数组时,剩余字符长度中的元素依旧保留上一次读取的内容,这样以数组长度为条件进行遍历就会出现问题。
while((len= fr.read(chcar)) != -1) {
for (int i = 0; i < chcar.length; i++) {
System.out.print(chcar[i]);
}
}
/
//以每次读取到数组中的字符个数为遍历条件就可以解决上述问题
while((len = fr.read(chcar)) != -1) {
for (int i = 0; i < len; i++) {
System.out.print(chcar[i]);
}
}
System.out.println();
//除了使用for循环遍历字符数组输出,还可以使用字符串String,将字符数组转为字符串进行输出
/
//运行结果:helloworldldor,这种方式和上面第一种方式一样,最后一次的字符数组未填满,其中就可能保留有上一次读取的字符值,转为字符串输出也是同样的错误
while ((len = fr.read(chcar)) != -1) {
String str = new String(chcar);
System.out.print(str);
}
/
//使用String带限制条件的构造器,每次将字符数组中指定位置的元素转为字符串,类似于上面的第二种方式
fr = new FileReader(file); // 上面的读取已完成一次,fr.read已经读到末尾,这里直接再次使用fr将什么也不输出,因此需要重新实例化流对象
while ((len = fr.read(chcar)) != -1) {
String str = new String(chcar,0, len);
System.out.print(str);
}
/
int data= fr.read();
while(data != -1) {
System.out.print((char)data);
//继续读取下一个字符
data = fr.read();
}
System.out.println();
*/
} catch (IOException e) {
e.printStackTrace();
} finally {
//4. 注意对于数据库连接、IO流、Scanner类、Socket等,使用完要手动关闭,JVM的回收机制对其无效,无法自动关闭,将占用资源,容易引发内存泄漏等问题
//当在流对象创建时出现异常,此时流对象还未实例化,就不存在关闭操作,因此对finally里的流关闭操作也应该try-catch,且先进行判断,判断流对象的有无
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
运行结果:
helloworld
helloworld
注意:
读取文件,前提是要求所读取的文件一定要存在,文件不存在,则流对象实例化的时候就会出现FileNotFound异常
为了保证流资源一ing可以执行关闭操作,需要使用try-catch-finally处理。finally里放流的关闭操作,当流对象创建完成在读取文件时出现异常,则会关闭流然后抛出异常;
当在流对象创建时出现异常,此时流对象还未实例化,就不存在关闭操作,因此对finally里的流关闭操作也应该try-catch,且先进行判断,判断流对象的有无
注意对于数据库连接、IO流、Scanner类、Socket等,使用完要手动关闭,JVM的回收机制对其无效,无法自动关闭,将占用资源,容易引发内存泄漏等问题
更常用的是read的重载方法的使用,即带参的流构造器,注意每次输出应该是读取到的字符数,而不是完整的字符数组长度
一次读取完成后,流对象就在文件的末尾;当下一次再次直接使用时就会立刻返回文件末尾标记-1;这里的文件内容是包含空格、回车等空白的。即到达的是文件最终的末尾(含空格、空行等),而不只是文本数据的末尾。
2. 字符输出流FileWriter
字符输入流FileWriter属于节点流,直接作用于源文件,用于文本数据的写出到硬盘文件中的操作。
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
//从内存中写出数据到硬盘中的hewllo.txt文件中
public class Demo03 {
public static void main(String[] args) {
FileWriter fw = null;
try {
//1. 提供File类对象,指明写出到的文件
//对于写入操作,不要求提供的路径下要有对应的文件,如果没有,写入操作时会自动新建一个对应的文件
File file = new File(“F:\project\code\Filetest\hello.txt”);
//2. 提供FileWriter的对象,用于数据的写出
//FileWriter流对象有两种构造方法:提供的append参数的给定,
//不设定该参数时默认为false,则写入操作时若有原同名文件,则对该同名文件进行替换,替换所有内容为流对象执行写入操作的内容,即写入直接替换原文件
//设定append参数的值为true,则写入操作时若有原同名文件,则会在同名文件内容的后面添加流对象执行写入操作的内容,即在原文件的基础上写入
fw = new FileWriter(file,true);
//fw = new FileWriter(file,false);
//3. 执行写出的操作
fw.write(“I have a dream!”);
fw.write(“sa”);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fw != null) {
try {
//4. 流对象的关闭
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3. 字符I/O流实现文本数据的复制
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//使用FileWriter和FileReader实现文本数据的赋值
//1. 创建File对象,指明读取和写出的文件路径;读取要求路径下必须有该文件,写出则没有要求
//2. 创建输入流和输出流对象
//3. 执行数据的读入和写出操作
//4. 关闭流对象
public class Demo04 {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
//1. 创建File对象,指明读取和写出的文件路径;读取要求路径下必须有该文件,写出则没有要求
//src.txt为要读取的文件,需要在路径下存在,应该有内容
//des.txt为要写出的文件,不需要在路径下已经存在
File srcfile = new File(“F:\project\code\Filetest\src.txt”);
File desfile = new File(“F:\project\code\Filetest\des.txt”);
//2. 创建输入流和输出流对象
fr = new FileReader(srcfile);
fw = new FileWriter(desfile);
//3. 执行数据的读入和写出操作
char[] chcar = new char[5];
int len;
while((len = fr.read(chcar)) != -1) {
fw.write(chcar,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4. 关闭流对象
try {
if (fr != null) {
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fw != null) {
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4. 字节I/O流实现非文本数据的复制
字节输入流FileInputStream属于节点流,直接作用于源文件,用于非文本数据的读取操作。
字节输入流FileOutputStream属于节点流,直接作用于源文件,用于非文本数据的写出操作。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//使用FileWriter和FileReader实现文本数据的赋值
//1. 创建File对象,指明读取和写出的文件路径;读取要求路径下必须有该文件,写出则没有要求
//2. 创建输入流和输出流对象
//3. 执行数据的读入和写出操作
//4. 关闭流对象
public class Demo05 {
public static void main(String[] args) {
FileInputStream fr = null;
FileOutputStream fw = null;
try {
//1. 创建File对象,指明读取和写出的文件路径;读取要求路径下必须有该文件,写出则没有要求
//src.png为要读取的文件,需要在路径下存在,应该有内容
//des.pngt为要写出的文件,不需要在路径下已经存在
File srcfile = new File(“F:\project\code\Filetest\src.png”);
File desfile = new File(“F:\project\code\Filetest\des.png”);
//2. 创建输入流和输出流对象
fr = new FileInputStream(srcfile);
fw = new FileOutputStream(desfile);
//3. 执行数据的读入和写出操作
byte[] chcar = new byte[5];
int len;
while((len = fr.read(chcar)) != -1) {
fw.write(chcar, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4. 关闭流对象
try {
if (fr != null) {
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fw != null) {
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行后的结果:
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明,KuangStudy,以学为伴,一生相伴!
本文链接:https://www.kuangstudy.com/bbs/1383780885324636162