FileReader、FileWriter
- 字符流:顾名思义读取的是字符
- 常用于处理文本文件
1. FileReader
- 读取方法 read( )
int read()
//读取单个字符。将读取的字符转换成整数并返回(范围在 0 到 65535 之间),如果已到达流的末尾则返回 -1
int read(char[] cbuf) //将字符读入数组。如果已到达流的末尾,则返回 -1。否则返回本次读取的字符数
int read(char[] cbuf,int off,int len) //将字符读入数组的某一部分。存到数组cbuf中,从off处开始存储,最多读len个字符。如果已到达流的末尾,则返回 -1。否则返回本次读取的字符数
对读取方法read( )的说明:每次读取1个字符,并不一定每次都读取2Byte,与编码方式有关。比如文件中有内容 “Hello世界” 。
若采用GBK编码,则 " Hello “共读取5次,每次读取1Byte,” 世界 “共读取2次,每次读取2Byte。
若采用UTF-8编码,则” Hello “共读取5次,每次读取1Byte,” 世界 "共读取2次,每次读取3Byte。
相关编码方式请点击此处查看
char字符解析请点击此处查看
- 代码示例
" HelloWorld.txt " 文件内容如下 ( 采用UTF-8编码 )
//调用read()方法
File file = new File("HelloWorld.txt"); // 1.创建File对象
FileReader fr = null;
try
{
fr = new FileReader(file); // 2.实例化FileReader
int data;
while ((data = fr.read()) != -1) // 3.调用read()方法
System.out.print((char) data);
} catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
} finally
{
try
{
if (fr != null) // 此处判断的目的是防止2处实例化FileReader失败导致对象引用为空
fr.close(); // 4.关闭资源
} catch (IOException e)
{
e.printStackTrace();
}
}
//Hello World!!! 你好 世界!!!
//Hello World!!! 你好 世界!!!
Q:char 底层是2Byte,为何能将读取的3Byte正确解码
A:char本质上是一个固定占用两个字节的无符号正整数( 0-65535 ),正整数对应于Unicode编号。文件中的中文对应的Unicode值在0-65535之间,所以可以正确解码。
// 调用read(char []) 方法
File file = new File("HelloWorld.txt"); // 1.创建File对象
FileReader fr = null;
try
{
fr = new FileReader(file); // 2.实例化FileReader
char[]cbuf=new char[5]; //每次读取5个字符
int len; //len保存每次实际在cbuf数组中装载的字符(若装满5个则len=5,没装满则返回实际装载的大小)
while ((len = fr.read(cbuf)) != -1) // 3.调用read()方法
{
for(int i=0;i<len;i++)
System.out.print(cbuf[i]);
}
} catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
} finally
{
try
{
if (fr != null) // 此处判断的目的是防止2处实例化FileReader失败导致对象引用为空
fr.close(); // 4.关闭资源
} catch (IOException e)
{
e.printStackTrace();
}
}
//Hello World!!! 你好 世界!!!
//Hello World!!! 你好 世界!!!
1.read(char[])方法的错误写法1(仅对上述代码修改部分)
while ((len = fr.read(cbuf)) != -1) // 3.调用read()方法
{
for(int i=0;i<cbuf.length;i++)//对i的循环条件进行更改
System.out.print(cbuf[i]);
}
//Hello World!!! 你好 世界!!!
//Hello World!!! 你好 世界!!!世
不难发现末尾多输出 "世" 。原因如下:文件中共有字符54个(英文字母20个,中文字母8个,感叹号12个,空格12个,换行符2个)
循环条件是i<cbuf.length即 i < 5
所以共进入while语句11次(添加相应的计数变量发现确实如此)
第10次在cbuf数组中装载的5个字符是 空格你好空格世
第11次只剩下4个字符 界!!! 第10次装载的第5个字符"世"没有被覆盖,所以最后多显示了"世"
2.read(char[])方法的错误写法2(原因同上)
while ((len = fr.read(cbuf)) != -1)
String str = new String(cbuf);
3.read(char[])方法的正确写法2
while ((len = fr.read(cbuf)) != -1)
String str = new String(cbuf,0,len);
2. FileWriter
- 写入方法 write( )
void write(String str)
void write(String str, int off, int len)
void write(char cbuf[])
void write(char cbuf[], int off, int len)
- 构造器
public FileWriter(File file)// 相当于调用第二个构造器,只不过boolen append=false(默认值)
public FileWriter(File file, boolean append)
public FileWriter(String fileName, boolean append)
- 代码示例
//HelloWorld1.txt在跑程序前没有被创建
public void test() throws IOException
{
File file = new File("HelloWorld1.txt"); // 1.创建File对象
FileWriter fw = new FileWriter(file); // 2.创建FileWriter对象
fw.write("Java Language");// 3.调用方法
fw.close(); // 4.关闭资源
}
运行后发现在对应的文件夹下自动创建了"HelloWorld1.txt"文件并将"Java Language"成功写入文件
//HelloWorld1.txt在跑程序前已经被创建,含有内容"Java Language"
public void test() throws IOException
{
File file = new File("HelloWorld1.txt"); // 1.创建File对象
FileWriter fw = new FileWriter(file); // 2.创建FileWriter对象
fw.write("Java Language Is Good");// 3.调用方法
fw.close(); // 4.关闭资源
}
运行后发现已经将"Java Language Is Good"成功写入文件并且只有"Java Language Is Good"
说明后来写入的新数据覆盖了原来的旧数据,结合对应的构造器不难理解其中原理
//HelloWorld1.txt在跑程序前已经被创建,含有内容"Java Language Is Good"
public void test() throws IOException
{
File file = new File("HelloWorld1.txt"); // 1.创建File对象
FileWriter fw = new FileWriter(file,true); // 2.创建FileWriter对象,允许在末尾添加
fw.write("Java Language Is Good");// 3.调用方法
fw.close(); // 4.关闭资源
}
运行后发现已经将"Java Language Is Good"成功写入文件并且有2个"Java Language Is Good"
说明后来写入的新数据添加在旧数据的末尾,结合对应的构造器不难理解其中原理
- File对应的文件如果在硬盘中不存在,则会自动创建此文件。
- 使用流的构造器:FileWriter(file,false) / FileWriter(file) 会对原有文件的覆盖
- 使用流的构造器:FileWriter(file,true) 会在原有文件基础上追加内容
3. 通过FileReader、FileWriter实现文本的复制
public void test5() throws IOException
{
File srcFile=new File("SrcTest.txt");
File destFile=new File("DestTest.txt");
FileReader fileReader = new FileReader(srcFile);
FileWriter fileWriter = new FileWriter(destFile,true);
int data;
while((data=fileReader.read())!=-1)
fileWriter.write(data);
fileReader.close();
fileWriter.close();
}
成功实现了文本的复制