JavaSE总结(三)IO流

JavaSE总结(三)IO流


在这里插入图片描述

一.File类

作用:文件和目录路径名的抽象表示。

二.IO原理

Java中的IO是阻塞式IO,是五种IO模型中的阻塞式IO模型,首先是用户线程发起IO请求,内核去查看数据是否就绪,如果数据没有就绪,用户线程就会一直等待着,移交出CPU.一旦数据就绪,数据会读到内核缓冲区,再从内核缓冲区拷贝到用户缓冲区。

三.流的分类

根据处理的数据类型不同可以分为字节流和字符流;

根据流的方向不同可以分为输入流和输出流

1.字节流和字符流:
1)字节流

InputStream(读取操作)、OutputStream(输出写操作)是java中按照最小字节单位读取的流,字节流是直接连接到数据源的流;

2)字符流

是一字符为单位进行数据处理的流,Reader,Write,本质上是基于字节流查找时去查找编码表

3)字节流和字符流的区别

1.处理的对象不同,字节流可以处理所有的数据类型的对象,而字符流只可以处理字符类型的对象;

2.读写的单位不同,字节流以字节为读写的单位(8位二进制),字符流以字符为单位(一次可能读写多个字节);

3.每次读取的大小不同:字节流一次读取8位二进制,字符流一次读取16位二进制;

结论:只要是纯文本数据优先使用字符流,除此之外都使用字节流。

2.输入流和输出流:
1)输入流(Input)

是指从数据源中进行读取操作,仅仅进行读操作;

2)输出流(Outpu)

是指将数据写到指定文件中;

结论:输入流和输出流都是针对文件,输入流就是去读文件中的数据源,输出流就是将数据写到指定文件。输入流:从文件读取数据到程序中;输出流:从程序将数据写到指定文件中

3.输入字节流(InputStream)与输出字节流(OutputStream)
InputStream:

1.InputStream是一个抽象类,是所有输入字节流的父类。

2.ByteArrayInputStream、StringBufferInputStream、FileInputStream是三中基本的介质流,他们分别从数组、StringBuffer、和本地文件中读取数据。

3.PipedInputStream是从与其它线程共用的管道中读取数据。

4.ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。

===================================================================================================

OutputStream:

1.OutputStream 是所有的输出字节流的父类,它是一个抽象类。

2.ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。

3.PipedOutputStream 是向与其它线程共用的管道中写入数据。

4.ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。

4.输入字符流(Reader)和输出字符流(Write)
Reader:

1.BufferReader:输入缓冲流

2.InputStreamReader :转换流,实现了字符流和字节流之间的转换

3.FileReader:字符读取的文件流

Write:

1.WriteReader:输出缓冲流

2.OutputStreamReader:转换流,实现了字符流和字节流之间的转换

3.FileWrite:按字符写入的文件流

5.节点流和处理流

在这里插入图片描述

节点流:直接连接到数据源进行读写
  1. 父 类 :InputStream 、OutputStream、 Reader、 Writer
  2. 文 件 :FileInputStream 、 FileOutputStrean 、FileReader 、FileWriter 文件进行处理的节点流
  3. 数 组 :ByteArrayInputStream、 ByteArrayOutputStream、 CharArrayReader 、CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
  4. 字符串 :StringReader、 StringWriter 对字符串进行处理的节点流
  5. 管 道 :PipedInputStream 、PipedOutputStream 、PipedReader 、PipedWriter 对管道进行处理的节点流
处理流:在节点流的基础上再套一层

因为节点流处理数据不方便,所以才有了处理流,处理流要和节点流一起使用,在节点流的基础上再套一层,这就是处理流,处理流的构造函数总是要带一个其他流对象作为参数,一个流对象经过其他流的多次包装,称之为流的连接;

  • 缓冲流:BufferedInputStrean 、BufferedOutputStream、 BufferedReader、 BufferedWriter 增加缓冲功能,避免频繁读写硬盘。
  • 转换流:InputStreamReader 、OutputStreamReader实现字节流和字符流之间的转换。
  • 数据流: DataInputStream 、DataOutputStream 等-提供将基础数据类型写入到文件中,或者读取出来。

四.几个特殊的流

1.转换流

实现从字节流到字符流的转换

InputStreamReader 、OutputStreamWriter 要InputStream或OutputStream作为参数,实现从字节流到字符流的转换。

①InputStreamReader(InputStream); //通过构造函数初始化,使用的是本系统默认的编码表GBK。

②InputStreamReader(InputStream,String charSet); //通过该构造函数初始化,可以指定编码表。

③InputStreamReader(OutputStream); //通过该构造函数初始化,使用的是本系统默认的编码表GBK。

④OutputStreamwriter(OutputStream,String charSet); //通过该构造函数初始化,可以指定编码表。

2.对象流

序列化:将对象的信息存储到文件中的过程(ObjectOutputStream , writerObject(Object obj))

反序列化:将文件中的信息返回给类的对象的过程(ObjectInputStream,readObject())

//先写先读(第一次读的就是第一次写的)

注:如果要将某个类的对象进行序列化操作,必须对该类实现Serializable接口

transient和static修饰过的数据不能序列化,序列化和反序列化有一个相同的serialVersionUID才可以序列化成功,保证了数据的1一致性。

序列化:

public static void main(String[] args) {
		
		//序列化
		Persion p1=new Persion("张三", "男", 12);
		Persion p2=new Persion("李四", "男", 22);
		ObjectOutputStream os=null;
		FileOutputStream fo=null;
		try {
			fo=new FileOutputStream("C:\\Users\\11295\\Desktop\\aa.txt");
			os=new ObjectOutputStream(fo);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try {
			os.writeObject(p1);
			os.flush();
			os.writeObject(p2);
			os.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if (os!=null) {
				try {
					fo.close();
					os.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

反序列化

//反序列化
		ObjectInputStream os=null;
		FileInputStream fs=null;
		
		try {
			fs=new FileInputStream("C:\\Users\\11295\\Desktop\\aa.txt");
			os=new ObjectInputStream(fs);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try {
			Persion o1=(Persion)os.readObject();
			Persion o2=(Persion)os.readObject();
			System.out.println(o2+"====="+o1);
		} catch (ClassNotFoundException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (os!=null) {
			try {
				os.close();
				fs.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
3.打印流(PrintStream )
  • Syetem.out是它的一个对象;
  • 文件不要求事先存在,要是文件存在且有内容,则会覆盖内容,要是文件不存在的话,则新创建文件将内容写进去。
PrintStream p=null;
		try {
			p=new PrintStream("C:\\Users\\11295\\Desktop\\aa.txt");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		p.print("周六的下午,阳光明媚,hhh");
		
		if (p!=null) {
			p.close();
		}
4.随机访问流

(即可以作为输入流,也可以作为输出流)

RandomAccessFile 类的实例支持读取和写入随机访问文件

public class TestRandomAccessFile {
	// 读取文件信息
	@Test
	public void test1() throws IOException {
		// 读文件
		RandomAccessFile raf = new RandomAccessFile("print.txt", "r");
		// 类型Stream操作类似
		byte[] bytes = new byte[20];
		int len;
		while ((len = raf.read(bytes)) != -1) {
			String s = new String(bytes, 0, len);
			System.out.println(s);
		}
		raf.close();
	}

	// 复制
	@Test
	public void test2() throws IOException {
		// 读文件
		RandomAccessFile raf = new RandomAccessFile("print.txt", "r");
		// 写文件
		RandomAccessFile rw = new RandomAccessFile("print1.txt", "rw");
		// 类型Stream操作类似
		byte[] bytes = new byte[20];
		int len;
		while ((len = raf.read(bytes)) != -1) {
			rw.write(bytes, 0, len);
		}

		rw.close();
		raf.close();
	}

	// 指定下标位置覆盖替换写入
	@Test
	public void test3() throws IOException {
		// 写文件
		RandomAccessFile rw = new RandomAccessFile("print1.txt", "rw");
		rw.seek(2); // 从第三个位置写入 替换从此处的开始往后的内容
		rw.write("AB".getBytes()); // 字符串转为字节数组
		rw.close();
	}

	// 指定下标位置插入写入
	@Test
	public void test4() throws IOException {
		// 写文件
		RandomAccessFile rw = new RandomAccessFile("print1.txt", "rw");
		rw.seek(2); // 从第三个位置写入
		String lint = rw.readLine(); // 从当前光标开始位置一直到这一行结束
		rw.seek(2); // 重新移动到插入点
		rw.write("123".getBytes()); // 字符串转为字节数组
		rw.write(lint.getBytes()); // 将插入前的内容拼接在后面
		rw.close();
	}
}

五.Java中标准输入输出流的重定向

一般来说System.in是键盘输入,System.out是输出到控制台,可以使用重定向,改变System.in和System.Out的输入输出位置;System类中提供了三个方法

static void setErr(PrintStream err)//错误输出流

Static void setIn(InputStream in)//输入流重定向

Static void setOut(PrintStream out)//输出流重定向

public class ReOut {
	/**
	* 重定向标准输出流
	* 1.初始化PrintStream对象
	* 2.调用System.setOut()方法,将标准输出流重定向到PrintStraem对象
	* 3.操作System.out流
	*/
	public void testSetOut(String file) {
		//1.创建输出流对象和打印流对象
		PrintStream p1=null;
		FileOutputStream fos=null;
		try {
			//2.根据文件地址初始化输出流
			fos=new FileOutputStream(file);
			//3.根据输出流初始化打印流
			p1=new PrintStream(fos);
			//4.使用System.setOut()方法将打印流重定向,定向到文件输出
			System.setOut(p1);
			//5.验证是否重定向成功
			System.out.print("重定向成功!");
			System.out.println(new ReOut());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if (p1!=null) {
				p1.close();
				try {
					fos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	/**
	* 重定向标准输入流
	* 1.有一个已经初始化的输入流InputStream
	* 2.调用System.setIn()方法,将标准输入流重定向到目的输入流
	* 3.对System.in进行读取操作
	 * @throws IOException 
	*/
	@Test
	public void testSetIn() throws IOException {
         //1.创建一个文件输入流对象
		FileInputStream fis=null;
		try {
          //2.根据即将读取的文件的地址初始化输入流
			fis=new FileInputStream("C:\\Users\\Administrator\\Desktop\\gg.txt");
           //3.调用System.setIn()方法重定向输入流
			System.setIn(fis);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String line=null;
		while((line = br.readLine()) !=null){
			System.out.println(line);
			}
		br.close();
		fis.close();
	}
}

更简单的方法

@Test
	public void setOutInTest() throws FileNotFoundException {
		//保留原始的输入输出流
		InputStream in=System.in;
		PrintStream out=System.out;
		
		//将标准输入流重定向到in.txt
		System.setIn(new DataInputStream(new FileInputStream("C:\\Users\\Administrator\\Desktop\\in.txt")));
		Scanner input=new Scanner(System.in);
		String str="";
		//将标准输出流定义到out.txt
		System.setOut(new PrintStream(new DataOutputStream(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\out.txt"))));
		while(input.hasNextLine()) {
			str=input.nextLine();
			System.out.println(str);
		}
		
		//将标准输入流定义到控制台
		System.setIn(in);
		//将标准输出流定义到控制台
		System.setOut(out);
		
		System.out.println("输入输出流已经恢复");
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值