一、IO流概述
概述:
IO流简单来说就是Input和Output流,IO流主要是用来处理设备之间的数据传输,java对于数据的操作都是通过流实现,而java用于操作流的对象都在IO包中。
分类:
按操作数据分为:字节流和字符流。 如:Reader和InpurStream
按流向分:输入流和输出流。如:InputStream和OutputStream
IO流常用的基类:
* InputStream , OutputStream
字符流的抽象基类:
* Reader , Writer
由上面四个类派生的子类名称都是以其父类名作为子类的后缀:
如:FileReader和FileInputStream
二、字符流
1. 字符流简介:
* 字符流中的对象融合了编码表,也就是系统默认的编码表。我们的系统一般都是GBK编码。
* 字符流只用来处理文本数据,字节流用来处理媒体数据。
* 数据最常见的表现方式是文件,字符流用于操作文件的子类一般是FileReader和FileWriter。
2.字符流读写:
注意事项:
* 写入文件后必须要用flush()刷新。
* 用完流后记得要关闭流
* 使用流对象要抛出IO异常
* 定义文件路径时,可以用“/”或者“\\”。
* 在创建一个文件时,如果目录下有同名文件将被覆盖。
* 在读取文件时,必须保证该文件已存在,否则出异常
示例1:在硬盘上创建一个文件,并写入一些文字数据
- class FireWriterDemo {
- public static void main(String[] args) throws IOException {
-
-
-
-
- FileWriter fw = new FileWriter("F:\\1.txt");
-
-
- fw.write("hello world!");
-
-
- fw.flush();
-
-
- fw.write("first_test");
- fw.close();
-
-
- }
- }
示例2:FileReader的reade()方法.
要求:用单个字符和字符数组进行分别读取
- class FileReaderDemo {
- public static void main(String[] args) {
- characters();
- }
-
-
-
- private static void characters() {
-
- try {
-
- FileReader fr = new FileReader("Demo.txt");
- char [] buf = new char[6];
-
- int num = 0;
- while((num = fr.read(buf))!=-1) {
-
-
- sop(new String(buf,0,num));
- }
- sop('\n');
- fr.close();
- }
- catch (IOException e) {
- sop(e.toString());
- }
- }
-
-
-
-
-
-
-
- private static void singleReader() {
-
- try {
-
-
-
- FileReader fr = new FileReader("Demo.txt");
-
-
-
-
- int ch = 0;
- while ((ch=fr.read())!=-1) {
- sop((char)ch);
- }
- sop('\n');
- fr.close();
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- catch (IOException e) {
- sop(e.toString());
- }
-
- }
-
-
-
- private static void sop(Object obj) {
- System.out.print(obj);
- }
-
- }
示例3:对已有文件的数据进行续写
- import java.io.*;
-
- class FileWriterDemo3 {
- public static void main(String[] args) {
-
- try {
-
- FileWriter fw = new FileWriter("F:\\java_Demo\\day9_24\\demo.txt",true);
- fw.write(" is charactor table?");
- fw.close();
- }
- catch (IOException e) {
- sop(e.toString());
- }
-
- }
-
-
- private static void sop(Object obj)
- {
- System.out.println(obj);
- }
- }
练习:
将F盘的一个文件复制到E盘。
思考:
其实就是将F盘下的文件数据存储到D盘的一个文件中。
步骤:
1.在D盘创建一个文件,存储F盘中文件的数据。
2.定义读取流和F:盘文件关联。
3.通过不断读写完成数据存储。
4.关闭资源。
源码:
- import java.io.*;
- import java.util.Scanner;
-
- class CopyText {
- public static void main(String[] args) throws IOException {
- sop("请输入要拷贝的文件的路径:");
- Scanner in = new Scanner(System.in);
- String source = in.next();
- sop("请输入需要拷贝到那个位置的路径以及生成的文件名:");
- String destination = in.next();
- in.close();
- CopyTextDemo(source,destination);
-
- }
-
-
- private static void CopyTextDemo(String source,String destination) {
-
- try {
- FileWriter fw = new FileWriter(destination);
- FileReader fr = new FileReader(source);
- char [] buf = new char[1024];
-
- int num = 0;
- while((num = fr.read(buf))!=-1) {
-
- fw.write(new String(buf,0,num));
- }
- fr.close();
- fw.close();
- }
- catch (IOException e) {
- sop(e.toString());
- }
- }
-
-
-
-
- private static void sop(Object obj) {
- System.out.println(obj);
- }
- }
三、缓冲区
1. 字符流的缓冲区:BufferedReader和BufferedWreiter
* 缓冲区的出现时为了提高流的操作效率而出现的.
* 需要被提高效率的流作为参数传递给缓冲区的构造函数
* 在缓冲区中封装了一个数组,存入数据后一次取出
BufferedReader示例:
读取流缓冲区提供了一个一次读一行的方法readline,方便对文本数据的获取。
readline()只返回回车符前面的字符,不返回回车符。如果是复制的话,必须加入newLine(),写入回车符
newLine()是java提供的多平台换行符写入方法。
- import java.io.*;
-
-
- class BufferedReaderDemo {
- public static void main(String[] args) throws IOException {
-
-
- FileReader rw = new FileReader("buf.txt");
-
-
- BufferedReader brw = new BufferedReader(rw);
-
-
- for(;;) {
- String s = brw.readLine();
- if(s==null) break;
- System.out.println(s);
- }
-
- brw.close();
-
- }
- }
BufferedWriter示例:
- import java.io.*;
-
-
- class BufferedWriterDemo {
- public static void main(String[] args) throws IOException {
-
-
- FileWriter fw = new FileWriter("buf.txt");
-
-
-
- BufferedWriter bfw = new BufferedWriter(fw);
-
-
-
-
- for(int x = 1; x < 5; x++) {
- bfw.write("abc");
- bfw.newLine();
- bfw.flush();
- }
-
-
-
- bfw.flush();
- bfw.close();
-
-
- fw.close();
-
- }
- }
2.装饰设计模式
装饰设计模式::::
要求:自定义一些Reader类,读取不同的数据(装饰和继承的区别)
MyReader //专门用于读取数据的类
|--MyTextReader
|--MyBufferTextReader
|--MyMediaReader
|--MyBufferMediaReader
|--MyDataReader
|--MyBufferDataReader
如果将他们抽取出来,设计一个MyBufferReader,可以根据传入的类型进行增强
class MyBufferReader {
MyBufferReader (MyTextReader text) {}
MyBufferReader (MyMediaReader media) {}
MyBufferReader (MyDataReader data) {}
}
但是上面的类拓展性很差。找到其参数的共同类型,通过多态的形式,可以提高拓展性
class MyBufferReader extends MyReader{
private MyReader r; //从继承变为了组成模式 装饰设计模式
MyBufferReader(MyReader r) {}
}
优化后的体系:
|--MyTextReader
|--MyMediaReader
|--MyDataReader
|--MyBufferReader //增强上面三个。装饰模式比继承灵活,
避免继承体系的臃肿。降低类与类之间的耦合性
装饰类只能增强已有的对象,具备的功能是相同的。所以装饰类和被装饰类属于同一个体系
MyBuffereReader类: 自己写一个MyBuffereReader类,功能与BuffereReader相同
- class MyBufferedReader1 extends Reader{
- private Reader r;
- MyBufferedReader1(Reader r){
- this.r = r;
- }
-
-
- public String myReaderline() throws IOException {
-
-
- StringBuilder sb = new StringBuilder();
- int ch = 0;
- while((ch = r.read()) != -1)
- {
- if(ch == '\r')
- continue;
- if(ch == '\n')
- return sb.toString();
- else
- sb.append((char)ch);
- }
- if(sb.length()!=0)
- return sb.toString();
- return null;
- }
-
-
-
- public void close()throws IOException {
- r.close();
- }
-
- public int read(char[] cbuf,int off, int len)throws IOException {
- return r.read(cbuf,off,len);
- }
-
- public void myClose() throws IOException{
- r.close();
- }
-
-
- }