IO流2--对文件内容的读写
前面讲述了,IO流中file对硬盘文件的一些基本操作,现在我们主要讲述的是IO流
对文件内容的一些基本操作。
一、流的分类
1.java.io包中的类对应两类流,一类流直接从指定的位置(如磁盘文件或内存区域)读或写,这类流称为结点流(node stream),
其它的流则称为过滤器(filters)。过滤器输入流往往是以其它输入流作为它的输入源,经过过滤或处理后再以新的输入流的形式提供给用户,
过滤器输出流的原理也类似。
2.Java的常用输入、输出流
java.io包中的stream类根据它们操作对象的类型是字符还是字节可分为两大类: 字符流和字节流。
•Java的字节流
InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先。
•Java的字符流
Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先。
* IO流:
* 字节流
* 字节输入流 读取数据 InputStream
* 字节输出流 写入数据 OutputStream
* 字符流
* 字符输入流 读取数据 Reader
* 字符输出流 写入数据 Writer
*
* 需求:我要把一句话:"hello,io,我来了。祝你元旦快乐。"写入一个test.txt中。
*
* 分析:
* A:由于我们是写数据,所以使用OutputStream或者Writer。
* B:由于我们要写入到一个文本文件中,所以最终选择了Writer。
*
* 通过查看API,我们发现,Writer是一个抽象类。那么,怎么办呢?
* 只能找子类使用。又由于我们是对文件操作,我们猜测了这个子类的名称是:FileWriter
*
* 去看FileWriter的构造方法:
* A:FileWriter(File file)
* B:FileWriter(String fileName)
public class FileWriterDemo {
public static void main(String[] args) throws IOException {
// 创建字符输出流对象
// Writer w = new FileWriter(); // 多态
// File file = new File("a.txt");
// if(!file.exists()){
// file.createNewFile();
// }
// FileWriter fw = new FileWriter(file);
FileWriter fw = new FileWriter("a.txt");
/*
* 创建字符输出流对象做了几件事情? A:调用系统功能创建了文件 B:创建字符输出流对象 C:把字符输出流对象指向创建的文件
*/
// 调用写数据的功能
// public void write(String str)
fw.write("hello,io,我来了。祝你元旦快乐。");
/*
* 字符流 1字符 = 2字节 文件数据底层单位是字节,而我们现在是字符,所以它不能直接把数据写入文件。 把字符输出存储到缓冲区里面。
*/
// 刷新缓冲区
// public void flush()
fw.flush();
// 释放资源
// public void close()
fw.close();
/*
* 为什么要close()呢?
* 1:让流对象变成垃圾。
* 2:通知系统去释放和文件相关的资源。
*/
//code
}
}
三、数据的写入
1:写入数据的方式,有5种。
* write(int ch)
* write(char[] chs,int index,int len)
* write(char[] chs)
* write(String str,int index,int len)
* write(String str)
*
* 2:为什么连续两次没有换号呢?如果想换行,怎么办呢?
* 因为你没有让他换行,所以没有换号。
* 那就给出换行符不就可以了吗。\n
*
* 不同的操作系统,对换行符的要求不一样:
* windows:\r\n
* linux:\n
* mac:\r
* 而有些软件,在制作的时候,为了通用,对任何换行符都是可以识别的。
*
* 3:数据没次都把以前的给覆盖了,如果我想追加写入,怎么办?
* 构造的时候,用带两个参数的。
* public FileWriter(String fileName,boolean append)
*
* 问题1:为什么FileWriter没有无参构造方法?
* 因为写数据的时候,一定要明确写道哪里去。
*
* 问题2:flush()和close()的区别?
* flush():只刷新缓冲区,流对象还可以继续使用。
* close():先刷新缓冲区,在关闭流对象。流对象不可以继续被使用。
public class FileWriterDemo3 {
public static void main(String[] args) throws IOException {
// 创建字符输出流对象
FileWriter fw = new FileWriter("c.txt",true);
// 写数据
// 一次写一个字符
// fw.write('a');
// fw.write(98);
// 一次写一个字符数组
// char[] chs = { 'a', 'b', 'c', 'd', 'e' };
// fw.write(chs);
// 一次写一个字符数组的一部分
// fw.write(chs, 0, 2);
// 一次写一个字符串
// fw.write("abcde");
// // 一次写一个字符串的一部分
// fw.write("abcde", 0, 3);
// fw.flush();
// 写数据
// fw.write("hello\r\n");
// fw.write("world\r\n");
// fw.write("java\r\n");
// fw.flush();
// 追加数据
fw.write("hello\r\n");
fw.write("world\r\n");
fw.write("java\r\n");
fw.flush();
// 释放资源
fw.close();
}
}
四、数据读取
字符输入流读取数据步骤:
A:创建字符输入流对象
B:调用读取数据功能,并显示
C:释放资源
方法一、一次读取一个字符
这里我们主要讲述FileReader从文件中读取,我们需要的数据到
流中。
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
// 创建字符输入流对象
// FileReader fr = new FileReader("a.txt");
FileReader fr = new FileReader("FileWriterDemo.java");
// 调用读取数据功能,并显示
// public int read()
// int ch = fr.read();
// // System.out.println(ch);
// System.out.print((char) ch);
//
// ch = fr.read();
// // System.out.println(ch);
// System.out.print((char) ch);
//
// // read()方法读取数据返回int类型,并自动移动到下一个数据位置等待读取。
// // 我们发现数据的读取和显示操作是重复的,所以我们决定用循环改进。
// // 关键是:循环的结束条件是什么
// ch = fr.read();
// System.out.println(ch);
//
// ch = fr.read();
// System.out.println(ch);
// 通过测试,我们发现,如果数据没有了,读取的时候,将返回-1
// int ch = fr.read();
// while (ch != -1) {
// System.out.print((char) ch);
// // 重新读取一次
// ch = fr.read();
// }
//开发写法
int ch = 0;
while((ch=fr.read())!=-1){
System.out.print((char) ch);
}
// 释放资源
fr.close();
}
}
方法二,一次读一个数组
public class FileReaderDemo2 {
public static void main(String[] args) throws IOException {
// 创建字符输入流
// FileReader fr = new FileReader("b.txt");
FileReader fr = new FileReader("FileWriterDemo.java");
// 读取数据
// char[] chs = new char[4];
// int len = fr.read(chs);
// System.out.println(new String(chs,0,len));
// System.out.println(len);
//
// // 再来一次
// len = fr.read(chs);
// System.out.println(new String(chs));
// System.out.println(len);
//
// // 再来一次
// len = fr.read(chs);
// System.out.println(new String(chs));
// System.out.println(len);
//
// // 再来一次
// len = fr.read(chs);
// System.out.println(new String(chs));
// System.out.println(len);
//
// // 再来一次
// len = fr.read(chs);
// System.out.println(new String(chs, 0, len));
// System.out.println(len);
//
// len = fr.read(chs);
// System.out.println(len);
//
// len = fr.read(chs);
// System.out.println(len);
// 如果实际读取长度是-1的情况,那么,说明已经读取到结尾了
// char[] chs = new char[4];
// int len = fr.read(chs);
// while (len != -1) {
// System.out.print(new String(chs, 0, len));
// len = fr.read(chs);
// }
// 开发的写法
// 数组的长度一般定义为1024的整数倍。
char[] chs = new char[1024];
int len = 0;
while ((len = fr.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
// 释放资源
fr.close();
}
}
六,文件的直接读取同时复制内容到另一文件
* 需求:我要把项目路径下的FileWriterDemo.java复制到d:\\Copy.java中
*
* 数据源:
* 读取数据:
* FileWriterDemo.java -- Reader -- FileReader
*
* 目的地:
* 写入数据:
* d:\\Copy.java -- Writer -- FileWriter
public class CopyFile {
public static void main(String[] args) throws IOException {
// 封装数据源
FileReader fr = new FileReader("FileWriterDemo.java");
// 封装目的地
FileWriter fw = new FileWriter("d:\\Copy.java");
// 读取数据
// int ch = 0;
// while ((ch = fr.read()) != -1) {
// fw.write(ch);
// // fw.flush();
// }
char[] chs = new char[1024];
int len = 0;
while ((len = fr.read(chs)) != -1) {
//写入数据.
fw.write(chs,0,len);
}
// 释放资源
fw.close();
fr.close();
}
}