秃头星人进化记(IO流学习总结)

开始

(以下内容为听网课学习的总结见解,若有bug还请包涵指教,)
IO流说白了就是像在搬家,从老家(源头)搬到新家(目的地),当然你绝对不会把整栋房子地基平移过去,你会叫搬家公司或者自个把家具等重要的东西一点点运到新家,就相当于数据被当成无结构的字节或字符序列,以流的形式传递,进行输入输出…
注(*代表星级)

基本概念

流的意思:流动,从一端移动到另一端,源头与目的地
程序与文件|数组|网络连接|数据库,以程序为中心
流的方向:
输入流inputStream Reader
输出流outputSream writer
处理数据单元(节点流):
字节流:二进制,可以一切文件包括纯文本doc音频视频等
字符流:文本文件,只能处理纯文本
功能不同:
节点流:可以直接从数据源或目的地读写数据
处理流:不直接连接到数据源或目的地,是处理流的流,通过对其他的处理提高程序的性能 ,就相当于对节点流的修饰。

File类(*****)

构造方法

File(String pathname)这个pathname就是指路径 也是最常用的
例如:`File src = new File(“D:/1.txt”);
File (String parent,String child)这就相当于把上面那个肢解了
例如:

    String parentPath="D:/";
	String name="1.txt";
	File src=new File(parentPath, name) ;

这里值得注意的是路径表示有三种:

//路径表示形式
		String path1="‪D:\\1.txt";
		String path2="‪D:"+File.separator+"1.txt";//中间这个separator是名称分隔符“/”;而pathSeparator则是路径分隔符“;”
		String path3="‪D:/1.txt";

注意:路径名称不能直接复制电脑上的,D:\1.txt 这样会报错1
报错1

常用方法

getName() 返回文件或目录的名称
getPath() 返回路径名字字符串
isFile() 判断是否是一个文件
isDirectory()判断是否是一个目录

import java.io.File;
import java.io.IOException;

public class Demo03 {
	public static void main(String[] args) throws IOException {
		File src = new File("D:/1.txt");
		System.out.println(src.getName());//返回名称
		System.out.println(src.getPath());//如果是绝对路径的话返回完整路径,否则相对路径
		System.out.println(src.getAbsolutePath());//返回绝对路径
		System.out.println(src.getParent());//返回上一级目录
		//System.out.println(src.get);
		System.out.println("文件是否存在"+src.exists());
		System.out.println("是否可读可写"+src.canWrite()+src.canRead());
		System.out.println("");
		if(src.isFile()) {
			System.out.println("文件");//存在
			
		}else {
			System.out.println("文件夹");//不存在
		}
		//创建新的文件 ,要是已经有了就不新建了 返回失败
		File src2=new File("D:/1.txt");
		if(!src2.exists()) {
			boolean flog=src2.createNewFile();
			System.out.println(flog?"成功":"失败");
		}
		//删除文件
		boolean flog=src2.delete();
		System.out.println(flog?"成功":"失败");
		
	}
 

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

字节流(*****)

一:读取文件
1:建立联系 File对象 源头(老家)
2:选择流 文件输入流 inputstream Fileinputstream
3:操作: byte[] x=new byte[10] + read()+读取大小
输出
4:释放资源:关闭 .close()

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
//读取文件
public class inputstream {
	public static void main(String[] args) {
		//1:建立联系 File对象
		File src=new File("D:/1.txt");
		//2:选择流
		InputStream is=null;
		try {
			 is=new FileInputStream(src);
			 //3:操作不断读取,缓冲数组
			 byte[] x=new byte[1024];
			 int cr=0;//接收实际读取大小
			    try {
				    //循环读取
				    while(-1!=(cr=is.read(x))) {
					String y=new String(x, 0, cr);
					System.out.println(y);
				       }
			       } catch (FileNotFoundException e) {
				e.printStackTrace();
				 System.out.println("文件不存在");
			}	
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("读取文件失败");
		}finally {
			if(is!=null) {
				try {
					is.close();
				} catch (IOException e) {
					System.out.println("无法关闭");
					e.printStackTrace();
				}
			}
		}
	}
}

二:写出文件
1:建立联系 File对象 目的地(新家)
2:选择流 文件输出流 outputstream Fileoutputstream
3:操作: write()+flush
输出
4:释放资源:关闭 .close()

//写入数据
public class outputstream {
	public static void main(String[] args) {
		//1:建立连接  file  目的地
		File src= new File("D:/1.txt");
		//2:选择流
		OutputStream os=null;
		//以追加形式写出文件
		try {
			os=new FileOutputStream(src,true);//注意了 这里的true是说  你第一次写入数据后 如果再执行若你不写true或者写flase就会覆盖上一次的结果,但是若是true则会追加,在后面继续添加
			//3:操作
			String x="1234567你好呀";
			//字符串转字节数组
			byte[] data=x.getBytes();
			try {
				os.write(data, 0, data.length);
				os.flush();//强制刷新出去
			} catch (IOException e) {
				System.out.println("文件写出失败");
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			System.out.println("文件不存在");
			e.printStackTrace();
		}finally {
			if(os!=null) {
				try {
					os.close();
				} catch (IOException e) {
					System.out.println("关闭失败");
					e.printStackTrace();
				}
			}
		}
	}
}

三:文件|文件夹的拷贝 程序为桥梁,就是把读取的内容拷贝到写出的目的地里面,两个不同的路径,也就是把前两个结合起来了
1:建立联系 File对象 源头和目的地
2:选择流 文件输入流 inputstream Fileinputstream 文件输出流 outputstream Fileoutputstream
3:操作: byte[] x=new byte[10] + read()+读取大小
write()+flush

4:释放资源:关闭 .close()
文件的拷贝

//复制文件 就是将前两个合并  先读取后合并
public class copy {
	public static void main(String[] args) throws IOException {
		String srcpath="D:/1.JPG";
		String destpath="D:/4.JPG";
		try {
			copyfile(srcpath, destpath);
		} catch (FileNotFoundException e) {
			 e.printStackTrace();
			 System.out.println("404NotFound");
		}catch (IOException e) {
			 e.printStackTrace();
			 System.out.println("复制失败,关闭流失败");
		}
	}
	public static void copyfile(String srcpath,String destpath)  throws IOException{
		File src=new File(srcpath);
		File dest= new File(destpath);
		if(!src.isFile()) {
			System.out.println("只能拷贝文件");
		}
		InputStream is=null; 
		is=new FileInputStream(src);
		OutputStream os=null;
		os=new FileOutputStream(dest,true); 
		 //读取1.txt(必须存在且为文件)
		 byte[] x=new byte[1024];
		 int cr=0; 
			while(-1!=(cr=is.read(x))) {
				 os.write(x,0,cr); 
			}
			//2:copy 将上面读取的写入到3.txt(可以不存在)
			os.flush();//强制刷新出去
			os.close();
			is.close();			 
	}
	}
 

文件夹的拷贝(如果将父目录复制到子目录会报错):

//复制文件夹
public class copydir {
	public static void main(String[] args) throws IOException {
		String srcpath="G:/1";
		String destpath="F:/1";
		File src=new File(srcpath);
		File dest=new File(destpath);
		if(src.isDirectory()) {
			dest=new File(destpath,src.getName());
		}
		copyDirDetail(src, dest);
	}
	public static void copyDirDetail(File src,File dest) throws IOException {
		if(src.isFile()) {//如果是文件 则直接读取复制
			 FileUtil.copyfile(src, dest);
		}else if(src.isDirectory()) {//如果是文件夹
			//确保目标文件夹存在
			dest.mkdirs();
			//这里有一个bug解决   
			if(dest.getAbsolutePath().contains(src.getAbsolutePath())) {
				System.out.println("父目录不能拷贝到子目录中");
				return;
			}
			//获取下一级目录文件
			for(File sub:src.listFiles( )) {
				copyDirDetail(sub, new File(dest,sub.getName()));
			}
		}
	}
}

字符流(*****)

                                          字符流(只能处理纯文本,全部为可见字符 .txt .html)

一:纯文本读取
1:建立联系
2:选择流 Reader FlieReader
3: 执行操作
4:关闭流

//字符流读取
public class reader {
	public static void main(String[] args) {
		
		//建立连接
		String path="D:/1.txt";
		File src=new File(path);
		//选择流
		Reader r=null;
		try {
			r=new FileReader(src);
			char[] cr=new char[1024];//这里不是byte 是char
			int len=0;
			try {
				while(-1!=(len=r.read(cr))) {
					String s=new String(cr,  0, len);
					System.out.println(s);
				}
			} catch (IOException e) {
				 System.out.println("文件读取失败");
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			System.out.println("文件找不到404");
			e.printStackTrace();
		}finally {
			if(r!=null) {
				try {
					r.close();
				} catch (IOException e) {
					 System.out.println("关闭流失败");
					e.printStackTrace();
				}
			}
		}
	}
}

二:纯文本写出
1:建立联系
2:选择流
3:读取write(字符数组,0,长度)+flush
write(字符串)
write(字符|字符串)
4:关闭流

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
//纯文本写出
public class writer {
	public static void main(String[] args) {
		String path="D:/1.txt";
		File dest =new File(path);
		Writer wt=null;
		try {
			wt=new FileWriter(dest,true);
			String s="java";
			wt.write(s);
			wt.append("123");
			wt.flush();
		} catch (IOException e) {
			System.out.println("404");
			e.printStackTrace();
		}
	}
}

三:纯文本拷贝:

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
//只能拷贝纯文本
public class copytxt {
	public static void main(String[] args) {
		String srcpath="D:/1.txt";
		String destpath="D:/4.txt";
		try {
			copy(srcpath,destpath);
		} catch (IOException e) {
			System.out.println("拷贝失败");
			e.printStackTrace();
		}
	}
	public static void copy(String srcpath,String destpath) throws IOException {
		File src=new File(srcpath);
		File dest=new File(destpath);
		Reader r=null;
		r=new FileReader(src);
		Writer w=null;
		w=new FileWriter(dest,true);
		char[] c=new char[1024];
		int len=0;
		while(-1!=(len=r.read(c))) {
			w.write(c, 0, len);
			 w.flush();
		}
		 r.close();
		 w.close();
	}
}

处理流(*****)

                                                   处理流:增强性能、提供性能,节点流之上

一:缓冲流
1:字节缓冲流
BufferedinputStream
BufferedoutputStream
没有新增的方法

//		InputStream is=null; 
//		is=new FileInputStream(src);
//		OutputStream os=null;
//		os=new FileOutputStream(dest,true); 
		InputStream is=null; 
		is=new BufferedInputStream(new FileInputStream(src));
		OutputStream os=null;
		os=new BufferedOutputStream(new FileOutputStream(src)); 
		/*
		 * 注意这里加了缓冲流
		 */

2:字符缓冲流
Bufferedreader
Bufferedwriter
有新增的方法

	//注意这里加了缓冲流,新增了两个方法
		r=new BufferedReader(new FileReader(src));
		BufferedWriter w=null;
		w=new BufferedWriter(new FileWriter(dest,true));
//		char[] c=new char[1024];
//		int len=0;
//		while(-1!=(len=r.read(c))) {
//			 
//			w.write(c, 0, len);
//			 w.flush();
//			
//		}
		String line=null;
		while(null!=(line=r.readLine())) {
			w.write(line);
			w.newLine();
			w.flush();
		}

二:转换流
字节流(byte)转为字符流(char) 处理乱码(编码集,解码集)
1:编码与解码的概念
编码 字符 —>编码字符集—>二进制
解码 二进制 —>解码字符集—> 字符
2:乱码问题:
编码和解码的字符集不统一;字节缺少,长度丢失
例如:

import java.io.UnsupportedEncodingException;

public class conver {
	public static void main(String[] args) throws UnsupportedEncodingException {
		//解码
		String str="你好呀";//gbk字符集
		//编码 char---byte
		byte[] data=str.getBytes();
		//默认情况下编码与解码字符集相同
		System.out.println(new String(data));
		
		//不相同的情况
		try {
			byte[] data2 =str.getBytes("utf-8");
			System.out.println(data2);
		} catch (UnsupportedEncodingException e) {
			System.out.println("字符集不相同");
			e.printStackTrace();
		}
		
		//修改方法
		//编码
		byte[] data3 = str.getBytes("utf-8");
		//解码
		System.out.println( new String(data3,"utf-8"));
		//就是这俩地都得设置成一样的
	
	
		//还有一种错误乱码的情况就是字节丢失缺少
		String str2="你好呀";
		byte[] data4=str2.getBytes();
		System.out.println(new String(data4,0,3));
	
	
	}
}

3:转换流:字节转为字符
输出流OutputStreamWriter 编码
输入流InputStreamReader 解码

     BufferedReader   r=null;
        r=new BufferedReader(new InputStreamReader( new FileInputStream(src),"utf-8"));
     BufferedWriter w=null;
		w=new BufferedWriter(new OutputStreamWriter( new FileOutputStream(dest),"utf-8"));

关闭流(***)

由于每次都要.close(),太麻烦了
因此编写工具类,实现关闭功能

public class FileUtil {
	/*一:
	 * 工具类关闭流
	 * 可变参数:...   只能放在形参的最后一个位置,处理方式与数组一致
	 */
	public static void close( Closeable ... io) {
		for(Closeable temp:io) {
			if(null!=temp) {
				try {
					temp.close();
				} catch (IOException e) {
					 
					e.printStackTrace();
				}
			}
		}
		
	}//所以在is.close();  os.close(); 这样的关闭方法中  可以用FileUtil.close(is,os);
	
	/*二:
	 * 使用泛型方法
	 */
	public static <T extends Closeable> void closseall(T ... io) {
		for(Closeable temp:io) {
			if(null!=temp) {
				try {
					temp.close();
				} catch (IOException e) {
					 
					e.printStackTrace();
				}
			}
		}
	}//所以在is.close();  os.close(); 这样的关闭方法中  可以用FileUtil.closseall(is,os);
}
               /*三:
               * try {声明}{操作}这是Jdk1.7以后新出的
               */
 

打印流(***)

                                        PrintStream

一:先了解一下这三个常量

  • 1:system.in 输入流 默认键盘输入
  • 2: system.out 输出流 默认控制台输出 ,一般用于测试或者写日志 , 在system 源码中可以看到 控制台的地址是 FileDescriptor.in/on/err
  • 3: system.err 错误输出流 会和out是不一样的颜色 运行一下就看出来了
  • 如果想要打印输出外面的文件就涉及到 -->重定向 就是说用上面的控制文件 而不是输出输入在控制台 因此就可用到setErr() setIn() setOut()
    看下面演示代码
public class Systemio {
	public static void main(String[] args) throws FileNotFoundException {
		System.out.println("out");
		System.err.println("err");
		//键盘输入
		//Scanner sc=new Scanner(System.in);也就是下面这个
//		InputStream is=System.in;
//		Scanner sc=new Scanner(is);
//		System.out.println(sc.nextLine());
	    //text2();
	    //控制台--->文件
	    System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream("D:/5.txt",true)),true));//第一个true早就知道了是每次输入都不覆盖的意思(每次输入追加);所以这里的第二个true 就是让他自动刷新,要不然没内容
	    System.out.println("aaaaaaaa");//此时运行你会发现5.txt里面木有东西  是因为没有刷新  .flush()
	    //回到控制台
	    System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)),true));
	    System.out.println("back.......");
	}
	public static void text2() throws FileNotFoundException {
		//也可以从文件输出输入
				InputStream is2=System.in;
				is2=new BufferedInputStream(new FileInputStream("D:/5.txt"));
				Scanner sc2=new Scanner(is2);
				System.out.println("请输入:");
				System.out.println(sc2.nextLine());
	}
}

二:PrintStream打印输出流练习:

public class PrintStreamio {
	public static void main(String[] args) throws FileNotFoundException {
		System.out.println("text");
	  PrintStream ps=System.out;
	  ps.println("sjw");//这就是把上面的分解了
	  
	  //输出到文件
	  File src=new File("D:/5.txt");
	  ps=new PrintStream(new BufferedOutputStream(new FileOutputStream(src)));
	 ps.println("123456"); 
	 FileUtil.closseall(ps);//看这个就调用了咱们的工具类  关闭流方法
	}
}

其他流(**)

一:节点流

1:字节数组 节点流

输入流:ByteArrayInputStream  read(byte[]b,int off,int len)+close()
输出流:ByteArrayInputStream  write(byte[]b,int off,int len)+toByteArray()  不要使用多态

文件---程序---字节数组
文件输入流
字节数组输出流

字节数组---程序---文件
字节数组输入流
文件输出流
public class byteArrayfile {
	public static void main(String[] args) throws IOException {
		byte[] data=getBytesFromFile("D:/1.jpg");
		toFileFromByteArray(data, "D:/7.jpg");
	}
	/*
	 * 文件---程序---字节数组
	文件输入流
	字节数组输出流
	 */
	public static byte[]  getBytesFromFile(String path) throws IOException {
		File src=new File(path);
		byte[] dest=null;
		InputStream is=new BufferedInputStream(new FileInputStream(src));
		//字节数组输出流不能使用多态
		ByteArrayOutputStream bos= new ByteArrayOutputStream() ;
		byte[] flush=new byte[1024];
		int len=0;
		while(-1!=(len=is.read(flush))){
			dest=bos.toByteArray();//转为字节数组
		}
		
		return dest;
		
	}
	/*
	 * 字节数组---程序---文件
	字节数组输入流
	文件输出流
	 */
	public static void toFileFromByteArray(byte[] src,String destPath) throws IOException {
		//创建源
		//目的地
		File dest =new File(destPath);
		//选择流
		//字节数组输入流
		InputStream is=new BufferedInputStream(new ByteArrayInputStream(src));
		//文件输出流
	 OutputStream os=new BufferedOutputStream(new FileOutputStream(dest));
		//操作不断读取数组
		byte[] by=new byte[1024];
		int len=0;
		while(-1!=(len=is.read(by))) {
			os.write(by,0,len);
		}
		os.flush();
		os.close();
	
	}
}

二:处理流

2:基本数据类型+String 保留数据+类型

输出流:DataInputStream  readxxx
输入流:DataOutputStream writexxx
一般可以结合节点数组使用
注意:所读取的数据类型和顺序必须与目标相同
若不同会报错*EOFException*  意思是说已经读取到末尾 没读取到你指定类型的数据
public class Data {
	public static void main(String[] args) throws IOException {
		datain("D:/7.txt");
		//dataout("D:/7.txt");
	}
	//读取
	public static void datain(String srcpath) throws IOException {
		//创建源
		File src=new File(srcpath);
		//选择流
		DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream(src)));
		//操作读取的顺序与写出一致,必须存在才能读取
		dis.readDouble();
		dis.readInt();
		dis.readUTF();
		System.out.println(dis.readUTF());
		dis.close();
	}
	
	
	public static void dataout(String destpath) throws IOException {
		
		Double y=1.2;
		int z=100;
		String x="你好";
		
		File dest=new File(destpath);
		DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
		dos.writeDouble(y);
		dos.writeInt(z);
		dos.writeUTF(x);
		dos.flush();
		dos.close();
	}
}

3:引用类型(对象)保留数据类型

反序列化:输入流 ObjectInputStream readObject
序列化: 输出流:ObjectOutputStream writeObject
先序列化后反序列化 反序列化必须与序列化顺序一致
java.io.NotSerializableException报错 解决方法implements java.io.Serializable
不是所有的属性都需要序列化 若加了transient 此属性就不会被序列化
注意 数组也可以序列化 跟对象一样

```java
public class Objectio {
	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		//seri("D:/4.txt");
		datain("D:/4.txt");
	}
	//反序列化
	public static void datain(String srcpath) throws IOException, ClassNotFoundException {
		//创建源
		File src=new File(srcpath);
		//选择流
		ObjectInputStream dis=new ObjectInputStream(new BufferedInputStream(new FileInputStream(src)));
		Object obj=dis.readObject();
		if(obj instanceof Demo4 ) {
			Demo4  de=(Demo4 )obj;
			System.out.println(de.getName());//他输出来不会是你好,会是null,  因为他加了transient没有序列化
			System.out.println(de.getx());
		}
		obj=dis.readObject();
		int[] arr=(int[])obj;
		System.out.println(Arrays.toString(arr));
		 
		dis.close();
	}
	//序列化
	public static void seri(String destPath) throws FileNotFoundException, IOException {
		Demo4  de=new Demo4 ("你好",100000.2);
		int[] arr= {1,2,3};
		File dest=new File(destPath);
		ObjectOutputStream dos=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
	    dos.writeObject(de);
	    dos.writeObject(arr);
		dos.flush();
		dos.close();
	}
}        

附:

 
public class Demo4 implements java.io.Serializable{
    //不需要序列化就加transient
	private transient String name;
	private double x;
	public Demo4() {
		
	}
	public Demo4(String name,double x) {
		super();
		this.name=name;
		this.x=x;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getx() {
		return x;
	}
	public void setx(double x) {
		this.x = x;
	}
	
}

结束…

此次学习是对IO流的初步理解,具体的深水区会慢慢探索,若文章笔记内容有错,还请提出指教。。。

发布了1 篇原创文章 · 获赞 5 · 访问量 45

猜你喜欢

转载自blog.csdn.net/s10110110000111/article/details/105616348