java中的字节流与字符流

2.9.2 IO流

流:数据从源点传输到汇点的“管道”

I=Input O=Output

流的分类:字节流10个+字符流

  1. 按照方向分:输入流 输出流
  2. 按照单位分:字节流 字符流
  3. 按照功能分:节点流 过滤流(包装流、处理流)

类:

  1. InputStream:所有字节输入流统一的父类,抽象类

    int read()

    int read(byte[] data)

    int read(byte[] data,int offset,int len)

  2. OutputStream:所有字节输出流统一的父类,抽象类

    write(int data)

    write(byte[] data)

    write(byte[] data,int offset,int len)

  3. FileInputStream:输入流 字节流 节点流

  4. FileOutputStream: 输出流 字节流 节点流

注意:

*: 它们都是节点流 构造方法允许传入String路径 或者 File对象
*: 它们都是节点流 但是只能连接文件,不能连接目录,否则直接触发异常FileNotFoundException
*: FileInputStream 最常用的是read(byte[]) 无参read效率太低
*: FileOutputStream 最常用的却是write(byte[],int,int),如果不用三参的write 是会形成结尾的冗余数据的…

核心代码

		FileInputStream fis = new FileInputStream("源文件");
		FileOutputStream fos = new FileOutputStream("目标文件");
		byte[] data = new byte[65536];
		int len;
		while((len = fis.read(data))!=-1){
			fos.write(data,0,len);
		}
		fos.close();
		fis.close();

*: FileInputStream 以-1作为读取结束的标识
*: FileOutputStream 是节点输出流
节点输出流连接的文件,即便不存在也会在创建流的那一刻,自动创建出来,不需要手建
其实File类当中有个方法叫createNewFile()【 默认自动建】
但是 如果连接的目录结构都不存在,不但不建,还会异常
所以File类有个方法叫mkdirs() -> 一等优先级【第一时间先建文件夹】
*: FileOutputStream 是节点输出流,它是有极强的杀伤性的
它在创建对象的那一刻,如果连接的文件已经存在,也会被新的空白文件直接替换… (比delete()还可怕)
如果我们不想替换 想要在原有内容之后追加写出新内容,可以构造方法传参 指定追加模式开启
new FileOutputStream(“a.log”,true);
*: 学会使用TWR语法 在读写完成之后,关闭流【 Try-With-Resources => 带有资源控制的try catch语法】

TWR写法

		try(FileInputStream fis=new FileInputStream(src);FileOutputStream fos=new FileOutputStream(obj)){
		byte[] data=new byte[65536];
		int len;
		while((len=fis.read(data))!=-1){
			fos.write(data,0,len);
			}
		}catch(Exception e){
			e.printStackTrace();
			}

将C盘所有的照片复制到e盘photo文件夹中

import java.io.*;
public class BigOneAG{
	static int id;
public static void main(String[] args){
	new File("e:\\photo").mkdirs();
	kill(new File("c:\\"));

}
public static void kill(File f){
	File[] ds=f.listFiles((x)->x.isDirectory());
	File[] js=f.listFiles((y)->y.isFile()&&y.getName().toLowerCase().endsWith(".jpg"));
		if(ds==null)return;
		for(File d:ds){
			kill(d);
		}
		for(File j:js){
			String name=nextName();
			File t=new File("e:\\photo",name);
			copy(j,t);
			}
	}
	public static String nextName(){
		String name=String.valueOf(++id);
		while(name.length()<5){
			name="0"+name;
			}
			name+=".jpg";
			return name;
		}
	public static void copy(File src,File obj){
		try(FileInputStream fis=new FileInputStream(src);FileOutputStream fos=new FileOutputStream(obj)){
			byte[] data=new byte[65536];
			int len;
			while((len=fis.read(data))!=-1){
				fos.write(data,0,len);
				}
			}catch(Exception e){
				e.printStackTrace();
				}
		}
}
  1. BufferedInputStream:输入流 字节流 过滤流

  2. BufferedOutputStream:输出流 字节流 过滤流

    ​ *: 作为过滤流的它们是为了给原本的节点流添加缓冲空间【从而提高每次读写的吞吐量 进而提高效率】
    ​ *: 作为过滤流的它们 不能直接连接文件 只能连接其它的流
    ​ *: 它们构造方法第二个参数 都允许指定缓冲空间的大小
    ​ 默认只有8K = 1024x8 = 8192个字节
    ​ *: 在使用了BufferedInputStream 最常用的就是read()
    ​ *: 在使用了BufferedOutputStream 最常用的就是write(int data)

    核心代码

    		FileInputStream fis = new FileInputStream("源文件");//针头
    		BufferedInputStream bis = new BufferedInputStream(fis);//针管
    		FileOutputStream fos = new FileOutputStream("目标文件");
    		BufferedOutputStream bos = new BufferedOutputStream(fos);
    		int data;
    		while((data = bis.read())!=-1){
    			bos.write(data);
    		}
    		bos.close();
    		bis.close();
    

    TWR写法

    try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream("源文件"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("目标文件"))){
    			int data;
    			while((data = bis.read())!=-1){
    				bos.write(data);
    			}
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    

​ *: BufferedInputStream 同样以-1作为读取结束的标识
​ *: BufferedOutputStream 是一个带有缓冲区的输出流
​ 使用带缓冲的输出流的时候 务必注意及时清空缓冲
​ 防止数据滞留缓冲空间 而导致丢失…
​ 缓冲区如何才能清空:
​ 1.满了自动清空 无需操作
​ 2.关闭流的操作会触发清空缓冲的操作
​ 3.主动调用方法清空缓冲区 flush();

扫描全盘文件,复制修改时间在一天之内的.txt和.java文件到D盘的yesterday文夹中

import java.io.*;
public class TestBuufered{
	static final long Now=System.currentTimeMillis();
	static final long ONE_DAY=24L*3600000;
public static void main(String[] args){
 new File("d:\\yesterday").mkdirs();
	File[] dir=File.listRoots();
	for(File d:dir){
		kill(d);
		}

}
public static void kill(File f){
	File[] ds=f.listFiles((x)->x.isDirectory());
	File[] js=f.listFiles((x)->x.isFile()&&Now-x.lastModified()<ONE_DAY&&(x.getName().toLowerCase().endsWith(".txt")||x.getName().toLowerCase().endsWith(".java")));
	if(ds==null)return;
	for(File d:ds){
		kill(d);
		}
		for(File j:js){
			File t=new File("d:\\yesterday",j.getName());
			try(BufferedInputStream bis= new BufferedInputStream(new FileInputStream(j));BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(t))){
				int data;
				while((data=bis.read())!=-1){
					bos.write(data);

					}
				}catch(Exception e){
					e.printStackTrace();
					}
					System.out.println(j);
			}
	}
}
  1. DataInputSream: 输入流 字节流 过滤流

  2. DataOutputStream:输出流 字节流 过滤流

  • 作为过滤流的它们 是为了给原本的节点流添加读写
    基本数据类型的功能的…
  • 作为过滤流的它们 不能直接连接文件 只能连接其它的流
  • boolean char byte short int long float double

DataInputStream 提供的核心方法是 readXxxx() 有返回值

DataOutputStream 提供的核心方法是 writeXxxx() 要参数

  • ​ DataInputStream 不再以-1作为读取结束的标识了,如果一旦到达文件结尾 还继续尝试读取,将会直接触发:EOFException => End Of File

写基本数据类型的文件

import java.io.*;
  public class Test{
    public static void main(String[] args)throws Exception{
      int[] data=new int[]{15,23,56,9,45,33};
      DataOutputStream dos=new DataOutputStream(new FileOutputStream("数字.data"));
      dos.writeInt(data.length);//定义写入的长度
      for(int x:data){
        dos.writeInt(x);
      }
      dos.close();
    }
  }

读基本数据类型的文件

import java.io.*;
public class Test1{
  public static void main(String[] args)throws Exception{
    DataInputStream dis=new DataInputStream(new FileInputStream("数字.data"));
   int size= dis.readInt();//将读到的文件大小返回给size
    int[] data=new int[size];//定义一个size大小的数组
    for(int i=0;i<size;i++){
      data[i]=dis.readInt();//将读到的数字赋给数组
      System.out.println(data[i]);//打印数组

    }
    dis.close();

  }
}
  • available()判断是否有可读字节
  • 注意 DataOutputStream 是将基本数据类型的内存原型
    直接以2进制的形式写出到文件当中
    而文件内没有任何标志描述哪是一个数据
    也就是说 当我们写出一个int之后 事实上
    可以读回来4个byte 或者2个short
import java.io.*;
public class TestDataStream{
	public static void main(String[] args)throws Exception{
		/*
		int level = 655;

		FileOutputStream fos = new FileOutputStream("save.data");
		DataOutputStream dos = new DataOutputStream(fos);
		dos.writeInt(level);
		dos.close();
		*/

		FileInputStream fis = new FileInputStream("save.data");
		DataInputStream dis = new DataInputStream(fis);
		int ok = dis.readInt();
		dis.close();
		System.out.println(ok);
	}
}
  1. ObjectInputStream:输入流 字节流 过滤流
  • 它们都是过滤流 是为了给原本的节点流添加读写对象的功能的

  • 它们都是过滤流 不能直接连接文件 只能连接其它的流

  • ObjectInputStream 提供的核心方法 readObject() 有返回值

  • ObjectOutputStream 提供的核心方法 writeObject() 需要参数

  • ObjectInputStream 同样不能以-1作为读取结束的标识
    如果一旦到达文件结尾还继续尝试读取
    将同样会触发EOFException…TWR写法即可

  • 想要持久化 首先需要序列化
    想要被持久化保存到磁盘上的对象 ,它的类必须实现序列化接口 implements Serializable
    而且 如果这个类型当中有其它引用类型的属性,就连这些属性的类也必须要实现序列化接口
    如果某些属性无关紧要 不需要参与持久化,可以使用transient修饰符修饰
    transient => 短暂的 : 不参与持久化的…

  • 如果要持久化的是一个集合对象
    集合当中的元素类型也必须实现序列化接口

  • 如果要持久化的是一个使用了比较器的TreeSet或者TreeMap
    就连比较器的类型也必须实现序列化接口(比较器是TreeSet或者TreeMap的一个属性…)

    import java.io.*;
    import java.util.*;
    public class TestObjectStream{
    	public static void main(String[] args)throws Exception{
    		/*
    		Date today = new Date();
    		FileOutputStream fos = new FileOutputStream("月光宝盒.data");
    		ObjectOutputStream oos = new ObjectOutputStream(fos);
    		oos.writeObject(today);
    		oos.close();
    		*/
    		FileInputStream fis = new FileInputStream("月光宝盒.data");
    		ObjectInputStream ois = new ObjectInputStream(fis);
    		Object obj = ois.readObject();
    		ois.close();
    		Date theDate = (Date)obj;//对象需要强转
    		System.out.println(theDate);
    	}
    }
    

    将对象序列化

    import java.io.*;
    public class TestObjectStreamPlus{
    	public static void main(String[] args)throws Exception{
    
    		Teacher tea = new Teacher("JayZhou",34);
    		//把周老师放进冰箱里要几步啊?
    		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("电冰箱.data"));
    		oos.writeObject(tea);
    		oos.close();
    		/*
    		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("电冰箱.data"));
    		Object obj = ois.readObject();
    		ois.close();
    		Teacher tea = (Teacher)obj;
    		System.out.println(tea.name + " : " + tea.age);
    		*/
    
    	}
    }
    class Computer{
    	String logo;
    	public Computer(String logo){
    		this.logo = logo;
    	}
    }
    class Teacher implements Serializable{
    	String name;
    	int age;
    	//transient => 短暂的 转瞬即逝的 : 不参与持久化的..
    	transient Computer pc;
    	public Teacher(String name,int age){
    		this.name = name;
    		this.age = age;
    		pc = new Computer("Lenovo");
    	}
    }
    

  1. Reader:所有字符输入流统一的父类,抽象类

    ​ int read()
    ​ int read(char[] data)
    ​ int read(char[] data,int off,int len)

  2. Writer:所有字符输出流统一的父类,抽象类

    ​ write(int data)
    ​ write(char[] data)
    ​ write(char[] data,int off,int len)

  3. FileReader:输入流 字符流 节点流

  4. FileWriter:输出流 字符流 节点流

  5. BufferedReader:输入流 字符流 过滤流

  6. BufferedWriter:输出流 字符流 过滤流

  • 作为过滤流的它们 给原本的节点流添加一个变长的缓冲空间
    从而实现以一行(hang)为单位的读写

  • 它们都是过滤流 不能直接连接文件 只能连接其它的流

  • BufferedReader 核心方法 String readLine()

  • BufferedWriter 核心方法 write(String) + newLine()

  • BufferedReader 不能以-1作为读取结束的标识 以null作为结束

    \r\n【txt中的换行】

PrintWriter 比 BufferedWriter 好在哪?

  1. PrintWriter 既可以当做节点流 又可以当做过滤流
    构造方法允许传入 String路径 / File 对象 / 流

  2. PrintWriter 既可以连接字节流 又可以连接字符流
    构造方法允许传入 OutputStream / Writer

  3. 当做节点流使用的时候 构造方法第二个参数可以指定字符集
    new PrintWriter(“abc.txt”,“utf-8”);

  4. 当做过滤流使用的时候 构造方法第二个参数可以指定自动清空缓冲
    new PrintWriter(new FileWriter(“abc.txt”,true),true);
    第二个true 代表 autoFlush

  5. println() = write() + newLine()

  6. 所有的Java程序员都对它非常熟悉 因为HelloWorld就在用它弟弟
    System.out的这个out属性 是PrintStream类型的
    PrintStream和PrintWriter用法完全相同…

综上所述: 在以行为单位的写出文本文件的时候,我们程序员不会使用BufferedWriter 而会使用更强大的PrintWriter

例题:请用程序统计 src目录当中,总共有多少个.java文件所有的.java文件总共有多少行,其中Josh Bloch开发的类有多少个,其中 关键字:public / void / return / class 出现的次数*: 请问所有的.java当中 有效代码多少行…将所有的统计结果 输出到:报告.txt 文件当中

import java.io.*;
import java.util.*;
public class BigThree{ 
	static int javacount;//java文件数量
	static int joshcount;//josh Bloch开发的类数量
	static int validcount;//有效代码行数(除了注释)
	static int linecount;//代码总行数
	static Map<String,Integer> map=new HashMap<>();//集合里面放关键词以及出现的数量
	static{
		map.put("public",0);//默认值都赋值为0
		map.put("void",0);
		map.put("class",0);
		map.put("return",0);
		}

public static void main(String[] args)throws Exception{
				File dir=new File("D:\\src");
				search(dir);

				try(PrintWriter pw=new PrintWriter("报告.txt")){
					pw.println("Java文件的数量:"+javacount);
					pw.println("代码总行数:"+linecount);
					pw.println("有效代码总行数:"+validcount);
					pw.println("Josh  Blosh开发的类有:"+joshcount);
					pw.println("你关心的关键字出现的次数如下:");
				  map.forEach((k,v)->pw.println(k+":"+v));
					}catch(Exception e){
						e.printStackTrace();
						}
}
//定义一个扫描文件的的方法
public static void search(File f){
	File[] ds=f.listFiles((x)->x.isDirectory());
	File[] js=f.listFiles((x)->x.isFile()&&x.getName().toLowerCase().endsWith(".java"));
	if(ds==null)return;
	for(File d:ds){
		search(d);
		}
		//Java文件的数量就等价于js数组的大小
		javacount+=js.length;
	for(File j:js){
		boolean isvalid=true;//定义一个布尔变量用来统计/*和*/
		try(BufferedReader br=new BufferedReader(new FileReader(j))){
			String str;
			while((str=br.readLine())!=null){
				//每读一行代码行数+1
				linecount++;
					if(str.contains("Josh Bloch")){
						//每一行包含Josh Boch 计数器+1
						joshcount++;
						}
						//排除空行和单行注释
					if(str.trim().startsWith("//")||str.trim().length()==0){
						continue;
						}
					if(str.trim().startsWith("/*")){
						isvalid=false;
						}
						//当布尔值为true时,即多行注释结束时,有效代码数量+1
					if(isvalid){
						validcount++;
						}
					if(str.trim().endsWith("*/")){
						isvalid=true;
						}
						//遍历map集合里面的主键,每当str包含主键,则改变他对应处出现的次数
					 Set<String> set=map.keySet();
					 for(String s:set){
						 while(str.contains(s)){
							 map.put(s,map.get(s)+1);
							 str = str.replaceFirst(s,"!");.//改变值之后将str中的关键字替换掉,避免一行出现多个关键词,漏记现象
							 }
						 }

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

在这里插入图片描述

import java.io.*;
/*
	2nd.你存所有的课件的目录知道在哪里hang
		请找出当中所有的focus.txt
		将其内容汇总写出到一个叫all.txt的文件中
*/
import java.io.*;
import java.util.*;
public class BigOne{
	public static void main(String[] args)throws Exception{
		File dir = new File("C:\\Users\\5v\\Desktop\\2106");
		File[] fs = dir.listFiles((x) -> x.isDirectory());

		List<File> list = new ArrayList<>();
		Collections.addAll(list,fs);

		Collections.sort(list,(a,b) -> {
			String name1 = a.getName();
			Integer i1 = getNumber(name1);
			String name2 = b.getName();
			Integer i2 = getNumber(name2);
			return i1.compareTo(i2);
		});

		PrintWriter pw = new PrintWriter("../all.txt");
		for(File d : list){
			pw.println("============= "+d.getName()+" ==============");
			File focus = new File(d,"focus.txt");
			if(focus.exists()){
				BufferedReader br = new BufferedReader(new FileReader(focus));
				String str;
				while((str = br.readLine())!=null){
					if(str.trim().length()!=0){
						pw.println(str);
					}
				}
				br.close();
			}
			pw.println("========================");
			pw.println();
			pw.println();

		}
		pw.close();
	}

	//我们想要这个方法传入
	//day22 [内部类]  返回22
	//day1 返回1
	public static Integer getNumber(String str){
		int end = str.length();
		if(str.contains(" "))
			end = str.indexOf(" ");
		String ok = str.substring(3,end);
		return Integer.parseInt(ok);
	}
}

URL:统一资源定位符

InputStreamReader:桥转换器

OutputStreamWriter:桥转换器

RandomAccessFile:随机访问文件

从网站上下载照片并重命名

import java.net.*;
import java.io.*;
public class TestURL2{
public static void main(String[] args)throws Exception{
	URL url=new URL("http://www.etoak.com/assets/images/wlcs.png");
	URLConnection uc=url.openConnection();
	InputStream in=uc.getInputStream();//得到数据流

   FileOutputStream fos=new FileOutputStream("wang.png");
	 byte[] data =new byte[65536];
	 int len;
	 while((len=in.read(data))!=-1){
		 fos.write(data,0,len);
		 }
		 in.close();
		 fos.close();


}
}

从网站上拔取数据,统计员工的平均工资

import java.net.*;
import java.io.*;
import java.util.*;
public class TestURL{
public static void main(String[] args)throws Exception{
	URL url=new URL("http://www.etoak.com/assets/etoak.json");
	URLConnection uc=url.openConnection();
	int total=uc.getContentLength();
	InputStream in=uc.getInputStream();//得到数据流
//桥转换器 = 字节流转换成字符流的工具
   InputStreamReader isr=new InputStreamReader(in,"utf-8");
   BufferedReader br=new BufferedReader(isr);
   String str;
   List<Integer> list=new ArrayList<>();
   while((str=br.readLine())!=null){
	   if(str.trim().length()>5){
		   String nohead=str.substring(str.indexOf("&yen;")+"&yen;".length());
		   String ok=nohead.substring(0,nohead.indexOf("\""));
		   //System.out.println(ok);
          if(ok.replaceAll("[0-9]","").length()==0){
			  int ok1=Integer.parseInt(ok);
			  list.add(ok1);
			  }else{
				  ok=ok.substring(0,ok.indexOf("/"));
				  int salary=Integer.parseInt(ok)*30;
				  list.add(salary);
				  }

}

	   }
        int sum=0;
       for(Integer i:list){
		   sum+=i;
		   }
			System.out.println(sum/list.size());
		in.close();


}
}

带进度条的下载

import java.net.*;
import java.io.*;
public class TestURL2{
	public static void main(String[] args)throws Exception{
		URL url = new URL("https://vue.etoak.com/static/video/video/four.mp4");
		URLConnection uc = url.openConnection();
		InputStream is = uc.getInputStream();
		FileOutputStream fos = new FileOutputStream("etoak.mp4");

		int total = uc.getContentLength();//资源的总共大小
		int current = 0;
		int last = -1;

		byte[] data = new byte[2<<20];
		int len;
		while((len = is.read(data))!=-1){
			fos.write(data,0,len);
			current += len;
			//current 占 total 的%
			int percent = (int)(current * 100L / total) ;
			if(last != percent){
				System.out.print("\r已经完成: "+percent+" %");
				last = percent;
			}
		}
		fos.close();
		is.close();
	}
}

把磁盘空间占满·

import java.io.*;
public class TestRandomAccessFile{
	public static void main(String[] args)throws Exception{
		File dir = new File("d:\\");
		long free = dir.getFreeSpace();

		RandomAccessFile raf = new RandomAccessFile("d:\\jay.mp4","rw");
		raf.setLength(free);
		raf.close();
	}
}

欢迎点赞与收藏,感谢支持!

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值