I/O流(3)

三、字符流

1.Reader和Writer抽象类

   字节流提供处理任何类型输入/输出操作的足够功能,但不能直接操作Unicode字符,因而需要字符流(主要用于查看文件内容),字符流层次结构的顶层是Reader和Writer抽象类。

(1)Reader是定义Java流式字符输入模式的抽象类,Reader抽象类中的方法:

     ① public int read(charBuffer target) throws IOException;

     ② public int read();

     ③ public int read(char[] cbuf);

     ④ public abstract int read(char[] cbuf, int off, int len);

     ⑤ public abstract void close();

(2)Writer是定义流式字符输出的抽象类,该类的方法都返回void值并在出错条件下抛出IOException异常,Writer抽象类中的方法:

     ① public void write();

     ② public void write(char[] cbuf);

     ③ public abstract void write(char[] cbuf, int off, int len);

     ④ public void write(String str) throws IOException;

     ⑤ public void write(String str, int off, int len);

     ⑥ public Writer append();

     ⑦ public abstract void flush();

     ⑧ public abstract void close();

2.FileReader和FileWriter

(1)FileReader类表示可以读取文件内容的Reader类,构造方法:

       public FileReader(String filePath);

       public FileReader(File fileObj);

(2)FileWriter类可以表示写文件的Writer类,构造方法:

       public FileWriter(String filePath);

       public FileWriter(String filePath, boolean append);

       public FileWriter(File fileObj);

字符输出流有一个默认大小为8K的缓冲区(8192KB)。

public class FileReaderWriterDemo {
	public static void main(String[] args) {
		
		try {
			FileReader fr = new FileReader("f:\\a.txt");
			FileWriter fw = new FileWriter("e:\\c.txt");
			
			char[] buff = new char[100];
			// 保存实际读到的字符个数
			int len = 0;
			while((len = fr.read(buff)) != -1) {
				fw.write(buff, 0, len);
				// 强制刷新缓冲区
				fw.flush();
			}
			fr.close();
			// 关闭此流,但要先刷新它
			fw.close();
			System.out.println("复制完成");
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

3.BufferedReader和BufferedWriter

    (1)BufferedReader通过缓冲输入提高性能,两个构造方法:

         ① BufferedReader(Reader inputStream);

         ② BufferedReader(Reader inputStream, int bufSize);

(3)BufferedWriter通过缓冲输出提高性能,两个构造方法:

        ① BufferedWriter(Writer outputStream);

        ② BufferedWriter(Writer outputStream, int bufSize);

public class BufferedReaderWriterDemo {
	public static void main(String[] args) {
		try {
			FileReader fr = new FileReader("f:\\a.txt");
			BufferedReader br = new BufferedReader(fr);
			
			FileWriter fw = new FileWriter("e:\\e.txt");
			BufferedWriter bw = new BufferedWriter(fw);
			// 保存读到的字符串
			String line = null;
			while((line = br.readLine()) != null) {
				System.out.println(line);
				bw.write(line);
				// 换行
				bw.newLine(); 
				// bw.flush();
			}
			br.close();
			bw.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
public class Demo {
	public static void main(String[] args) {
		try {
			FileReader fr = new FileReader("f:\\a.txt");
			BufferedReader br = new BufferedReader(fr);
			String line = br.readLine();
			while(line != null) {
				System.out.println(line);
				line = br.readLine();
			}
			br.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}	

四、其他流

1.ObjectIutputStream/ObjectOutputStream

(1)ObjectInputStream/ObjectOutputStream分别与FileInpputStream/FileOutputStream一起使用时,可以为应用程序提供对对象的持久存储。我们把对象以某种特定的编码格式写入称之为"序列化"。把写入的编码格式内容还原成对象称之为"反序列化"。被序列化的对象必须实现Serializable接口。

public class ObjectInputOutputDemo {
	public static void main(String[] args) {
		Student student = new Student("zhangsan", "10");
		
		try {
			ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e:\\x.txt"));
			// 把对象序列化到指定的文件输出流中
			oos.writeObject(student);
			// 释放资源
			oos.close();
			
			// 反序列化对象
			ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e:\\x.txt"));
			Student stu = (Student)ois.readObject();
			System.out.println(stu);
			ois.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

class Student implements Serializable {

	private static final long serialVersionUID = -2970811277559210577L;
	
	private String name = "";
	
	private String age = "";
	
	public Student(String name, String age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}
	
	@Override
	public String toString() {
		return super.toString();
	}
	
}

2.InputStreamReader和OutputStreamWriter

       转换流是指字节流与字符流之间的转换。转换流的出现方便了对文件的读写,它在字符流与字节流之间架起了一座桥梁,使原本毫无关联的两种流操作能够进行转化,提高了程序的灵活性。字节流中的数据都是字符时,转成字符流操作更高效。如果使用非默认编码保存文件或读取文件时,需要用到转换流,因为字节流的重载构造方法中有指定编码格式的参数,而FileReader和FileWriter是默认编码的文本文件.

(1)常见的编码表

      ① ASCII:美国标准信息交换码,用一个字节的7位可以表示。

      ② ISO8859-1:拉丁码表,欧洲码,用一个字节的8位表示。

      ③GB2312:中国的中文编码表

      ④ GBK:中国的中文编码表升级,融合了更多的中文文字符号。

      ⑤ Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode.

      ⑥ UTF-8:最多用三个字节来表示一个字符。

InputStreamReader是字节流通向字符流的桥梁,OutputStreamWriter是字符流通向字节流的桥梁。

public class InputStreamWriterReaderDemo {
	// 以指定的编码方式来进行文件读写
	public static void main(String[] args) {
		try {
			OutputStreamWriter osw = new OutputStreamWriter(
					new FileOutputStream("e:\\test.txt"), "UTF-8");
			BufferedWriter bw = new BufferedWriter(osw);
			bw.write("今天是祖国的生日!");
			bw.close();
			
			// 读文件(GB2312)
			BufferedReader br = new BufferedReader(new FileReader("e:\\x.txt"));
			String line = null;
			while((line = br.readLine()) != null) {
				System.out.println(line);
			}
			br.close();
			
			// 读文件(GBK)
			BufferedReader bReader = new BufferedReader(
					new InputStreamReader(
							new FileInputStream("e:\\a.txt"), "GBK"));
			String lineString = null;
			while((lineString = bReader.readLine()) != null) {
				System.out.println(lineString);
			}			
			bReader.close();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

3.RandomAccessFile随机访问文件流

       支持对随机访问文件的读取和写入,随机访问文件的行为类似存储在文件系统中的一个大型byte数组。存在指向该隐含数组的光标或索引,称为文件指针。(也就是说RandomAccessFile这个类内部有一个大型byte数组,数据都存放在byte数组中,可以通过数组的文件指针来获取byte数组里面的值也可以通过文件指针来对byte数组的任一位置来写入相应的数据)。输入操作从文件指针开始读取字节,随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,随着对字节的写入而前移此文件指针。写入隐含数组末尾之后的输出操作导致该数组扩展。该文件指针可以通过getFilePointer方法读取,通过seek方法设置。

public class RandomAccessFileDemo {
	public static void main(String[] args) {
		People[] persons = {new People("test01", 10), 
				new People("test02", 20),
				new People("test03", 30)};
		try {
			RandomAccessFile randomAccessFile = new RandomAccessFile("e:\\f.txt", "rw");
			
			// 写入数据到RandomAccessFile这个对象中
			for (People person : persons) {
				randomAccessFile.writeChars(person.getName());
				randomAccessFile.writeInt(person.getAge());
			}
			randomAccessFile.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
 class People {
	 
	 private String name = "";
	 
	 private int age;
	 
	 public People(String name, int age) {
		 this.name = name;
		 this.age = age;
	 }

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
 }

猜你喜欢

转载自blog.csdn.net/weixin_42051619/article/details/82873699