IO流

萝らか妹 提交于 2019-11-29 12:09:13

流的概念
数据的传输称为流,流的本质是数据传输。
流是一组有序的,有起点和终点的字节集合,是对计算机中数据传输的总称或者抽象。
流序列中的数据可以是没有进行加工的原始数据(二进制字节数据),也可以是经过编码的符合某种格式规定的数据,Java中提供了不同的流类对它们进行处理。

流有两个端点,起始位置 —> 目的地。
一端发送,另外一端接收。
输入流/输出流:都是从jvm角度来讲的。

把任何外界数据读到java中,这就是输入流。
把任何java中的数据写到外界,都是输出流。

输出流代表:System.out.print;
起点:jvm
终点:控制台

输入流代表:new Scanner(System.in);
起点:键盘->电脑操作系统
终点:jvm

------------------------------------------------------------------------------------------------------------------------------

流的分类
按照流传输方向不同:
输入流(InputStream)
输出流(OutputStream)

按照处理数据类型的不同:
字节流
字符流

按照流的基本功能不同:
节点流(基本流,传输最基本的字节或字符)
过滤流(对节点流的扩展,传对象,传double,传String等等)

------------------------------------------------------------------------------------------------------------------------------
字节流

FileInputStream读取文件
FileInputStream常用方法:
构造方法:
FileInputStream(String filename)
FileInputStream(File file)

常用方法:
close()
int read() (没有参数,返回值是byte值)
int read(byte[ ] b) (有参数,返回的是本次读取的长度)
int read(byte[ ] bs,int off,int len)

package demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Input {
	public static void main(String[] args) {
		File file = new File("D:/abc/book.txt");
		
		try {
			//建立一条从文件到程序(jvm)的管道
			FileInputStream in = new FileInputStream(file);
			
			//声明一个空的比特数组,用于存放数据
			byte[] bs = new byte[128];
			
			//从文件中读取数据,填充数组,返回读取到的长度
			//int len = in.read(bs);
			
			//读取数据,放入数组中的指定位置
			int len = in.read(bs,5,30);
			System.out.println("读到长度:"+len);
			
			String data = new String(bs);
			System.out.println(data);

			in.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

运行结果:
在这里插入图片描述

package demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class FileTest1 {
	public static void main(String[] args) {
		
		File file = new File("D:/abc/book.txt");
		
		try {
			FileInputStream in = new FileInputStream(file);
			
			byte[] bs = new byte[2];
			for(int i = 0;i < (file.length()/bs.length);i++)
			{
				in.read(bs);
				String str = new String(bs);
				System.out.println(str);
			}
			
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
	}

}

运行结果:
在这里插入图片描述

------------------------------------------------------------------------------------------------------------------------------

字节流

FileOutputStream写文件
FileOutputStream常用方法:
构造方法:
FileOutputStream(String path)
FileOutputStream(File file)
FileOutputStream(String path,boolean append)
FileOutputStream(File file,boolean append)

常用方法:
close()
void write(int v)
void write(byte[ ] bs)
void write(byte[ ] bs,int off,int len)

package demo;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class OutputTest {
	public static void main(String[] args) {
		
		File file = new File("D:/abc/输出流测试.txt");
		
		if(!file.exists()){
			try {
				file.createNewFile();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		try {
			//java连接文件,从java到目标文件的管道
			FileOutputStream out = new FileOutputStream(file);
			
			String str = "无敌是多么寂寞~";
			
			out.write(str.getBytes());
			
			out.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	
	}

}

运行结果:
在这里插入图片描述

------------------------------------------------------------------------------------------------------------------------------

用流复制文件-通用全能方案

package demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class FileCopy {
	public static void main(String[] args) {
		/**
		 * 把src赋复制到local
		 */
		File src = new File("D:/MyWeb/images/表情包.jpg");
		File local = new File("D:/abc/"+src.getName());
		
		try {
			//建立连接管道
			FileInputStream in = new FileInputStream(src);
			FileOutputStream out = new FileOutputStream(local);
			
			byte[] bs = new byte[256];
			
			/*
			while(true){
				int len = in.read(bs);
				if(len != -1){
					out.write(bs,0,len);
				}
				else {
					//结束循环
					break;
				}
			}
			*/
			
			for(int len=0;(len=in.read(bs)) != -1;){
				out.write(bs,0,len);
			}
			
			//释放资源
			in.close();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

------------------------------------------------------------------------------------------------------------------------------

断点续传-制造断点文件

package demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class BreakPoint {
	public static void main(String[] args) {
		File src = new File("D:/MyWeb/images/表情包.jpg");
		File local = new File("D:/abc/"+src.getName());
		
		try {
			//建立连接管道
			FileInputStream in = new FileInputStream(src);
			FileOutputStream out = new FileOutputStream(local);
			
			byte[] bs = new byte[256];
			
			long over = 0;
			for(int len=0;(len=in.read(bs)) != -1;){
				out.write(bs,0,len);
				
				//文件传一半,断掉
				over += len;
				if(over > src.length()/2) {
					System.out.println("出现断点");
					break;
				}
			}
			
			//释放资源
			in.close();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

运行结果:
在这里插入图片描述

在这里插入图片描述

------------------------------------------------------------------------------------------------------------------------------

断点续传-实现续传功能
断点续传核心技术点:输出流设置追加,输入流设置跳过

package demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class BreakPointResume {
	public static void main(String[] args) {
		/**
		 * 把src赋复制到local
		 * 支持断点续传(核心技术点:输出流设置追加,输入流设置跳过)
		 */
		File src = new File("D:/MyWeb/images/表情包.jpg");
		File local = new File("D:/abc/"+src.getName());
		
		//文件开始位置
		long start = 0;
		
		if(src.length() == local.length()) {
			System.out.println("文件已经存在,无需复制");
		}
		else if(src.length()> local.length()) {
			System.out.println("断点文件,需要续传");
		    start = local.length();
		}
		else if(local.length() == 0) {
			System.out.println("文件不存在,开始复制");
		}
		
		try {
			//建立连接管道
			FileInputStream in = new FileInputStream(src);
			FileOutputStream out = new FileOutputStream(local,true);
			
			byte[] bs = new byte[256];
			
			//设置输入流起始位置
			in.skip(start);
			for(int len=0;(len=in.read(bs)) != -1;){
				out.write(bs,0,len);

			}
			
			//释放资源
			in.close();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

------------------------------------------------------------------------------------------------------------------------------

编写文件工具类
如果我们想要复制多个文件的话,就需要编写文件工具类。

package demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class MyFileUtil {
	
	public static void copy(String src,String target) throws FileNotFoundException {
		File f1 = new File(src);
		File f2 = new File(target);
		copy(f1,f2);
	}
	
	public static void copy(File src,File target) throws FileNotFoundException {
		InputStream in = new FileInputStream(src);
		OutputStream out = new FileOutputStream(target);
		copy(in,out);
	}
	
	public static void copy(InputStream in,OutputStream out) {
		
		try {
			byte[] bs = new byte[2048];
			
			for(int len=0;(len=in.read(bs)) != -1;) {
				out.write(bs,0,len);
			}
			
			out.close();
			in.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

}
package demo;

import java.io.File;
import java.io.FileNotFoundException;

public class MyFileUtilTest {
    public static void main(String[] args) {
    	File file1 = new File("D:/abc/book.txt");
    	File file2 = new File("D:/abc/MyUtilTest.txt");
    	
    	try {
    		MyFileUtil.copy("D:/abc/book.txt","D:/abc/MyUtilTest.txt");
    		MyFileUtil.copy(file1,file2);
    		
		} catch (FileNotFoundException e) {
			System.out.println("复制文件的时候发生异常,此处可以编写各种代码");
			e.printStackTrace();
		}
    	
	}

}

运行结果:
在这里插入图片描述

------------------------------------------------------------------------------------------------------------------------------

java测试字符集
常见的编码规范(字符集):
ASCII
ISO-8859-1
GBK
UTF-8

乱码问题

package demo;

import java.io.UnsupportedEncodingException;

public class Test2 {
	public static void main(String[] args) throws UnsupportedEncodingException {
		
		String str = "小奶狗";
		byte[] bs = str.getBytes("GBK");
		byte[] bs2= str.getBytes("UTF-8");
		
		for(byte b : bs) {
			System.out.println(b);
		}
		
		System.out.println("—————" + bs.length);
		System.out.println("=====" + bs2.length);
		
		String str2 = new String(bs2, "UTF-8");
		System.out.println(str2);
		
		byte[] little = new byte[] {-48,-95};
		String xiao = new String(little,"GBK");
		System.out.println(xiao);
	}

}

运行结果:
在这里插入图片描述

------------------------------------------------------------------------------------------------------------------------------

字符流
字符流用于处理文字传输,涉及到字符集的内容。
字节流用于处理文件传输。

– 底层也是比特流,只是经过了字符编码的处理。
– 可以认为 R/W 就是字符转换器。

FileReader常用方法:
FileReader(String fileName)
close()
int read(char[ ] ch)

FileWriter常用方法:
FileWriter(String fileName)
close()
void write(String value)

FileReader和FileWriter只用于连接文件,通用性不强,因为大多数时候我们都是通过网络传输。其次,它们不能设置字符集。

package demo;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Test1 {
	public static void main(String[] args) throws IOException {
		
		FileReader fr = new FileReader("D:/abc/book.txt");
		FileWriter fw = new FileWriter("D:/abc/new.txt");
		
		String value = "纵情山河万里!";
		char[] val = value.toCharArray();
		fw.write(val);
		fw.flush();
		
		char[] ch = new char[256];
		int n = fr.read(ch);
		String str = new String(ch,0,n);
		
		System.out.println(n);
		System.out.println(str);
		
		fr.close();
		fw.close();
		
	}

}

运行结果:
在这里插入图片描述

在这里插入图片描述

InputStreamReader和OutputStreamWriter特点:
1.可以把一个字节流转换成一个字符流。
2.在转换时可以指定字符集。

InputStreamReader常用方法:
InputStreamReader(InputStream in)
InputStreamReader(InputStream in,String charSet)
int read(char[] cbuf)

OutputStreamWriter常用方法:
OutputStreamWriter(OutputStream out)
OutputStreamWriter(OutputStream out,String charSet)
void write(String value)

package demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Test3 {
	public static void main(String[] args) {
		
		try {
			File file = new File("D:/abc/book.txt");
			
			InputStream in = new FileInputStream(file);
			
			InputStreamReader isr = new InputStreamReader(in,"UTF-8");
			
			char[] val = new char[16];
			
			int len = isr.read(val);
			
			System.out.println("长度:"+len);
			System.out.println(val);
			
			isr.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}

运行结果:
在这里插入图片描述

package demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

public class Test4 {
	public static void main(String[] args) {
		File file = new File("D:/abc/book2.txt");
		
		String str = "流光容易把人抛,红了樱桃,绿了芭蕉";
		
		try {
			
			OutputStream out = new FileOutputStream(file);//会创建新文件
			
			OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
			
			osw.write(str);;
			
			osw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}

运行结果:
在这里插入图片描述

------------------------------------------------------------------------------------------------------------------------------

过滤流
过滤流的开发步骤:
1.创建节点流。
2.基于节点流创建过滤流。
3.读/写数据。
4.关闭外层流。

DataOutputStream过滤流演示:

package demo;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class Test5 {
	public static void main(String[] args) {
		
		File file = new File("D:/abc/book3.txt");
		try {
			//因为只有最基本的读写功能,所以叫节点流
			//因为是用来处理字节的流,所以叫字节流
			OutputStream out = new FileOutputStream(file);
			
			//基于节点流创建过滤流,是个高级流
			DataOutputStream dos = new DataOutputStream(out);
			
			//调用过滤流中的高级方法书写数据
			dos.writeDouble(3.1415926);
			dos.writeInt(99);
			dos.writeChars("HelloWorld!");
			
			//关闭最外层流即可
			dos.close();
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
	}

}

运行结果(能够读出来即可):
在这里插入图片描述

DataInputStream过滤流演示

package demo;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class Test6 {
	public static void main(String[] args) {
		
		File file = new File("D:/abc/book3.txt");
		
		try {
			InputStream in = new FileInputStream(file);
			
			DataInputStream dis = new DataInputStream(in);
			
			double num1 = dis.readDouble();
			int num2 =  dis.readInt();
			String str = dis.readUTF();

			System.out.println(num1);
			System.out.println(num2);
			System.out.println(str);
			
			dis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}

运行结果:
在这里插入图片描述

------------------------------------------------------------------------------------------------------------------------------

BufferedStream:带有缓冲区,用法同上。
BufferedInputStream
BufferedOutputStream

------------------------------------------------------------------------------------------------------------------------------

对象流与对象序列化
ObjectInputStream常用方法:
readObject()
ObjectOutputStream常用方法:
writeObject()

Serializable接口不需要实现任何方法,实现这个接口之后这个类就可以被序列化,可以通过流进行传输。
transient代表某项属性不参与序列化活动。
transient关键字需要注意:如果一个对象的属性又是一个对象,则要求这个属性对象也实现了Serializable接口。

package demo;

import java.io.Serializable;

public class Player implements Serializable {
	private String name;
	transient private String level;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getLevel() {
		return level;
	}
	public void setLevel(String level) {
		this.level = level;
	}
	
	public Player(String name,String level)
	{
		this.name = name;
		this.level = level;
	}
	

}
package demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class Test7 {
	public static void main(String[] args) {
		Player girl = new Player("小奶狗","最强王者");
		Player boy = new Player("小狼狗","倔强青铜");
	
	    File file = new File("D:/abc/introduce.txt");
	    
		try {
			 OutputStream out = new FileOutputStream(file);
		     ObjectOutputStream oos = new ObjectOutputStream(out);
		     
		     oos.writeObject(girl);
		     oos.writeObject(boy);
		     
		     oos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	    
	}

}

package demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;

public class Test8 {
	public static void main(String[] args) {
		
		File file = new File("D:/abc/introduce.txt");
		
		try {
			InputStream in = new FileInputStream(file);
			
			ObjectInputStream ois = new ObjectInputStream(in);
			
			Player p1 = (Player) ois.readObject();
			Player p2 = (Player) ois.readObject();
			
			System.out.println(p1.getName()+":"+p1.getLevel());
			System.out.println(p2.getName()+":"+p2.getLevel());
			
			ois.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
	}

}

运行结果:

在这里插入图片描述

------------------------------------------------------------------------------------------------------------------------------

总结:
字符过滤流:
readLine() 读取一行。
writeLine() 写一行。

各种过滤流都是基本流的扩展。

共有方法:
write
read

独有方法:
DataStream:基本数据类型的直接读写。
BufferedStream:带有缓冲区,看起来速度好快。
ObjectStream:对象读写。

对象序列化:实现Serializable接口。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!