IO流:字节流和字符流(Java SE第三阶段5)

目录

IO结

流的分类

本章所用方法 

字节流

使用文件输出流写出文件数据

使用文件输入流读取文件数据

使用文件输入和输出流复制文件

使用缓冲流复制文件

使用缓冲流写出数据的缓冲区问题

对象流的读写操作

对象输入流

字符流

使用转换流读取文本数据

缓冲字符流

缓冲字符输入流

自行使用流连接完成对文件的按行写出操作

练习:完成简易记事本


IO结构

流的分类

/**
 * java标准的IO:输入与输出
 * 标准IO是让我们可以用相同的读写方式读写一切需要读写的外界设备。
 * 
 * jav.io.InputStream和OutputStream
 * 他们是所有输入流和输出流的超类,并且他们是抽象类自身是不能被实例化的,但是规定了所有流都必须具备的读写方法。、
 * 
 * java将流按照方想划分为输入与输出,输入流用于读数据,输出流用于写数据。(参照物为程序)
 * 
 * java将流分为两类:节点流和处理流
 * 节点流也称低级流,是实际连接程序与数据源的管道,负责实际读写数据的流。读写数据一定是建立在节点流的基础上进行的。
 * 
 * 处理流也称高级流,不能独立存在,必须连接在其他流上,目的是当数据流经当前流时可以对数据进行加工处理,简化我们对数据的相关操作工作。

节点流:可以从或向一个特定的地方(节点)读写数据。

处理流:是对一个已存在流的连接和封装,通过所封装流的功能调用实现数据读写。
 * 
 * 串联一组高级流并最终连接到低级流上,使得读写数据以流水线式的方式进行,这种操作称为流的连接。这也是学习IO的精髓所在。
 * 
 * 流读写数据时是顺序读写的,即:读写只能顺序向后进行,不能回退。


         * 常用构造方法
         * FileOutputStream(File file)
         * FileOutputStream(String path)
         * 以上两种创建方式为覆盖写模式,即:若创建文件流时发现该文件已经存在,则会先将该文件原有数据清除,
         * 然后通过该流写出的数据会作为文件数据保存。
         * 
         * FileOutputStream(File file, boolean append)
         * FileOutputStream(String path, boolean append)
         * 文件流构造器有一个重载,就是再传入一个boolean类型的参数,若该值为true,则是追加模式。即:
         * 原有数据保留,写出的内容会被追加到文件中。
         

本章所用方法 

字节流

使用文件输出流写出文件数据

package io;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class FOSDemo {
	public static void main(String[] args) 
throws UnsupportedEncodingException, IOException {
		FileOutputStream fos = new FileOutputStream("fos.txt",true);
		
		String str = "呦~";
		fos.write(str.getBytes("GBK"));
				
		System.out.println("写出完毕!");
		fos.close();
		
	}
}

使用文件输入流读取文件数据

package io;

import java.io.FileInputStream;
import java.io.IOException;

/**
 * 文件输入流,用于读取文件数据
 * 
 * @author Jack
 *
 */
public class FISDemo {
	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream("fos.txt");

		byte[] data = new byte[100];
		int len = fis.read(data);
		System.out.println("实际读取了" + len + "个字节");
		String str = new String(data, 0, len, "GBK");
		System.out.println(str);
		fis.close();
	}
}

使用文件输入和输出流复制文件

package io;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 使用文件流完成文件的复制
 * 
 * @author Jack
 *
 */
public class CopyDemo {

	public static void main(String[] args) throws IOException {
		/**
		 * 1.创建文件输入流用于读原文件 
		 * 2.创建文件输出流用于写复制文件 
		 * 3.循环利用文件输入流读取原文件中的字节,通过文件输出流写出到复制文件中完成工作。
		 */
		FileInputStream fis = new FileInputStream("fos.txt");
		FileOutputStream fos = new FileOutputStream("fos_cp1.txt");

		int len = -1;
		byte[] data = new byte[1024 * 10];
		while ((len = fis.read(data)) != -1) {// len = fis.read(data)必须放里边,读一次写一次,放外边死循环
			fos.write(data, 0, len);
		}
		System.out.println("复制完毕!");
		fis.close();
		fos.close();
	}

}

使用缓冲流复制文件

package io;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 使用缓冲流完成文件复制
 * 
 * 缓冲流:
 * java.io.BufferedOutputStream
 * java.io.BufferedInputStream
 * 缓冲流是一对高级流,作用是提高数据的读写效率。
 * @author Jack
 *
 */
public class CopyDemo2 {

	public static void main(String[] args) throws IOException{
		FileInputStream fis = new FileInputStream("1.jpg");
		BufferedInputStream bis = new BufferedInputStream(fis);

		FileOutputStream fos = new FileOutputStream("1_cp1.jpg");
		BufferedOutputStream bos = new BufferedOutputStream(fos);

		int d = -1;
		long start = System.currentTimeMillis();
		/**
		 * 缓冲流内部有一个字节数组作为缓冲区,默认为8k.
		 * 缓冲流会将读写数据统一转换为块读写操作,因此可以提高读写效率。
		 */
		while ((d = bis.read()) != -1) {
			bos.write(d);
		}
		long end = System.currentTimeMillis();
		System.out.println("复制完毕!耗时:" + (end - start) + "ms");

		bis.close();// 里面会把fis.close先运行
		bos.close();
		
	}

}

使用缓冲流写出数据的缓冲区问题

package io;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 缓冲流写出数据的缓冲区问题
 * 
 * @author Jack
 *
 */
public class FlushDemo {

	public static void main(String[] args) throws IOException {
		FileOutputStream fos = new FileOutputStream("bos.txt");
		BufferedOutputStream bos = new BufferedOutputStream(fos);

		String str = "hello";
		bos.write(str.getBytes("GBK"));
		/**
		 * void flush() 强制将缓冲流的缓冲区中已经缓存的数据写出.
		 */
		bos.flush();
		
		System.out.println("写出完毕!");
		// 缓冲流close时会会自动调用一次flush()
		bos.close();
	}

}

对象流的读写操作

 * 写出的对象所属的类必须实现可序列化接口,否则会抛出NotSerializableException
         * 对象经过oos写出时,oos首先将该对象按照其结构转换为了一组字节,这个过程称为: 对象序列化。
         * 序列化后的字节再经过fos写入文件(写入磁盘)做长久保存,这个过程称为: 数据持久化。

 * 被transient修饰的属性在序列化时会被忽略,忽略不必要的属性可达到对象序列化瘦身操作。

package io;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/**
 * 对象流
 * java.io.ObjectOutputStream 
 * java.io.ObjectInputStream
 * 
 * 对象流是一对高级流,作用是方便读写java对象,他们可以负责将对象与字节进行相互转换。
 * 
 * @author Jack
 *
 */
public class OOSDeo {

	public static void main(String[] args) throws IOException{
		String name = "苍老师";
		int age = 18;
		String gender = "女";
		String[] otherInfo = { "是一名演员", "来自岛国", "已婚", "促进中日文化交流", "广大男性同胞的启蒙老师" };
		
		Person p = new Person(name, age, gender, otherInfo);
		System.out.println(p);
		
		FileOutputStream fos = new FileOutputStream("person.obj");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		/**
		 * 写出的对象所属的类必须实现可序列化接口,否则会抛出NotSerializableException
		 * 
		 * 对象经过oos写出时,oos首先将该对象按照其结构转换为了一组字节,这个过程称为: 对象序列化。
		 * 序列化后的字节再经过fos写入文件(写入磁盘)做长久保存,这个过程称为: 数据持久化。
		 */
		oos.writeObject(p);
		
		System.out.println("写出完毕!");
		oos.close();
	}

}
package io;

import java.io.Serializable;
import java.util.Arrays;

/**
 * 使用当前类实例测试对象流的对象读写操作。
 * 
 * @author Jack
 *
 */
public class Person implements Serializable{
	
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	private String gender;
	/**
	 * 被transient修饰的属性在序列化时会被忽略,忽略不必要的属性可达到对象序列化瘦身操作。
	 */
	private transient String[] otherInfo;

	public Person(String name, int age, String gender, String[] otherInfo) {
		super();
		this.name = name;
		this.age = age;
		this.gender = gender;
		this.otherInfo = otherInfo;
	}

	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;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String[] getOtherInfo() {
		return otherInfo;
	}

	public void setOtherInfo(String[] otherInfo) {
		this.otherInfo = otherInfo;
	}

	@Override
	public String toString() {
		return name + "," + age + "," + gender + "," + Arrays.toString(otherInfo);
	}

}

对象输入流

 对象输入流: 工作是进行对象的反序列化
对象输入流在还原对象时要求读取的字节必须是通过对象输出流写出对象所序列化的一组字节,
否则会抛出异常ClassNotFoundException.

package io;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/**
 * 对象输入流: 工作是进行对象的反序列化
 * 
 * @author Jack
 *
 */
public class OISDemo {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		FileInputStream fis = new FileInputStream("person.obj");
		ObjectInputStream ois = new ObjectInputStream(fis);

		/**
		 * 对象输入流在还原对象时要求读取的字节必须是通过对象输出流写出对象所序列化的一组字节,
		 * 否则会抛出异常ClassNotFoundException.
		 * 
		 */
		Person p = (Person) ois.readObject();
		System.out.println(p);

		ois.close();
	}
}

字符流

/**
 * 字符流
 * java将流按照读写单位划分为:字节流与字符流。
 * 字节流:InputStream,OutputStream作为超类,读写数据是以字节为单位读写的。
 * 
 * 字符流:Reader,Writer作为超类
 * 读写数据是以字符为单位读写的,因此字符流天生是具有编解码能力,只适合读写文本数据!

字符流是以字符(char)为单位读写数据的,一次处理一个uicode。

字符流的底层仍然是基本的字节流。

字符流封装了字符的编码解码算法。
 * 
 * 转换流:InputStreamReader和OutputStreamWirter
 * 他们是字符流中非常常用的一套实现类,在流连接中是非常重要的一环,但是我们很少直接操作这两个流。
 * 
 * 其他的字符流在流连接中使用时有一个要求,只能连接在其他字符流上,但是我们常用的低级流通常都是字节流,这会导致不能串联在一起,
 * 而转换流的意义就在这里,它们是可以连接在字节流上的字符流,而其他的字符流又可以连接在他们上面,因此起到“转换器”的作用。

package io;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class OSWDemo {
	public static void main(String[] args) throws IOException {
		FileOutputStream fos = new FileOutputStream("osw.txt");
		OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");// GBK不写就会按照系统默认字符集输出
		
		/**
		 * 通过转换流写出的文字,会按照创建转换流时指定的字符集转化为字节后写出。
		 */
		osw.write("来了老弟~");
		System.out.println("写出完毕!");
		osw.close();
	}
}

使用转换流读取文本数据

package io;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 使用转换流读取文本数据
 * 
 * @author Jack
 *
 */
public class ISRDemo {
	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream("./src/io/ISRDemo.java");
		InputStreamReader isr = new InputStreamReader(fis, "GBK");

		int d = -1;
		while ((d = isr.read()) != -1) {
			char c = (char) d;
			System.out.print(c);
		}
		isr.close();
	}
}

缓冲字符流

/**
 * 缓冲字符流
 * java.io.BufferedWriter
 * java.io.BufferedReader
 * 缓冲字符流读写文本数据效率高,并且可以按行读写文本数据。
 * 
 * java.io.PrintWriter
 * 具有自动行刷新新功能的缓冲字符输出流(内部连接了BufferedWriter作为缓冲功能)。

         * PrintWriter提供了对文件写操作的构造方法
         * PrintWriter(File file)
         * PrintWriter(String path)
         * 
         * 重载的构造方法可以指定写出的字符集
         * PrintWriter(File file,String csn)
         * PrintWriter(String path,String csn)
         * csn:charset name 字符集的名字
         */

package io;

import java.io.IOException;
public class PWDemo1 {

	public static void main(String[] args) throws IOException{
		PrintWriter pw = new PrintWriter("pw.txt","GBK");
		
		pw.println("艾维巴蒂嗨起来!");
		pw.println("动次打次~动次打次~");
		System.out.println("写出完毕!");
		pw.close();
	}

}

缓冲字符输入流

package io;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 缓冲字符输入流:BufferedReader
 * 块读,并且可以按行读取字符串
 * 
 * @author Jack
 *
 */
public class BRDemo {
	public static void main(String[] args) throws IOException{
		FileInputStream fis = new FileInputStream("./src/io/BRDemo.java");
		InputStreamReader isr = new InputStreamReader(fis,"GBK");
		BufferedReader br = new BufferedReader(isr);
		
		/**
		 * String readLine() 
		 * 连续读取若干字符串,直到换行符为止,然后将换行符之前的字符以一个字符串形式返回。
		 * 若返回值为null,则表示流读取到了末尾。
		 */
		String line = null;
		while((line=br.readLine())!= null) {
			System.out.println(line);
		}
		br.close();
	}
	
}

自行使用流连接完成对文件的按行写出操作

package io;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

/**
 * 自行使用流连接完成对文件的按行写出操作。
 * @author Administrator
 *
 */
public class PWSDemo2 {

	public static void main(String[] args) throws IOException{
		FileOutputStream fos = new FileOutputStream("pw.txt");
		OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
		BufferedWriter bw = new BufferedWriter(osw);
		PrintWriter pw = new PrintWriter(bw);
		
		pw.println("你好吗你妹的");
		pw.println("n你大爷");
		System.out.println("写出完毕!");
		pw.close();
		
	}

}

练习:完成简易记事本

 * PrintWriter的构造方法如果第一个参数是流,那么就有一个boolean类型的第二个参数,若该值为true时就具有了自动行刷新功能,每当调用println方法时会自动flush。

package io;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Scanner;

/**
 * 完成简易记事本
 * 
 * @author Jack
 *
 */
public class PWDemo3 {
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入文件名:");
		String fileName = sc.nextLine();

		FileOutputStream fos = new FileOutputStream(fileName);// 流连接
		OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
		BufferedWriter bw = new BufferedWriter(osw);
		/**
		 * PrintWriter的构造方法如果第一个参数是流,那么就有一个boolean类型的第二个参数,若该值为true时就具有了自动行刷新功能,
		 * 每当调用println方法时会自动flush
		 */
		PrintWriter pw = new PrintWriter(bw,true);

		System.out.println("请输入内容:");
		while (true) {
			String line = sc.nextLine();
			if ("exit".equals(line)) {
				break;
			}
			pw.println(line);
		}
		System.out.println("程序终止!");
		sc.close();
		pw.close();
	}
}

越努力,越幸运!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值