Java IO流--字节流、File类

字节流

OutputStream
InputStream
基本操作与字符流类相同。
特点演示
import java.io.*;

class Demo1FileStream {

	public static void main(String[] args) throws IOException {

		FileOutputStream ops = new FileOutputStream("out.txt");  //创建字节输出对象
		
		ops.write("abc".getBytes());  //把字符串转换成字节型,再写入
		ops.close();
		
		userReader_1();
		System.out.println("------------------------");
		userReader_2();
		System.out.println("------------------------");
		userReader_3();
		
	}
	
	public static void userReader_1() throws IOException {
		
		FileInputStream fis = new FileInputStream("out.txt");//创建一个字符输入流对象
		
		
	//使用read()方法一次读取一个字节	
		int num = 0;
		
		while((num = fis.read()) != -1) {
			
			System.out.println((char)num);
			
		}
		
		fis.close();
		
	}
	
	public static void userReader_2() throws IOException {
		
		FileInputStream fis = new FileInputStream("out.txt");
		
		byte[] buf = new byte[1024];  //定义一个数组
		
		int len = 0;
		while((len = fis.read(buf)) != -1) {  //把字节存入数组
			
			System.out.println(new String(buf,0,len));
			
		}
		
		fis.close();
		
	}
	
	public static void userReader_3() throws IOException {
		
		FileInputStream fis = new FileInputStream("out.txt");  //创建字节输入流对象
		
		byte[] buf = new byte[fis.available()];  //available()可以打印文件里面字节大小,当文件太大时不能使用,因为默认的内存不够
		
		fis.read(buf);
		
		System.out.println(new String(buf));
		
	}
	

}

字节流缓冲区

同样是提高了字节流的读写效率BufferedOutputStream、BufferedInputStream
演示mp3的复制,通过缓冲区
import java.io.*;

class Test2CopyMp3 {

	public static void main(String[] args) {
  //            创建字节流缓冲区引用
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		
		try {
			
			//创建字节流缓冲区对象,并把字节流对象传入
			bis = new BufferedInputStream(new FileInputStream("C:\\Users\\Loppz\\Documents\\Tongbu\\Ringtone\\Minions Hello!.mp3"));
			bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\Loppz\\Documents\\Tongbu\\Ringtone\\Minions.mp3"));
			
			//读取数据并写入数据
			int num = 0;
			while((num = bis.read()) != -1) {
				
				bos.write(num);
				
			}
			
		}
		catch(IOException e) {
			
		}
		finally{
			if(bis != null) {
				try {
					
					bis.close();
					
				}
				catch(IOException e) {
					
				}
			}
			if(bos != null) {
				try {
					
					bis.close();
					
				}
				catch(IOException e) {
					
				}
			}
		}
		
	}

}
缓冲区中无非就是封装了一个数组,并对外提供了更多的方法对数组进行访问,其实这些方法最终操作的都是数组的角标。
原理:
其实就是从源中获取一批数据到缓冲区中,再从缓冲区中不断地取出一个一个数据,在此次取完后,再从源中继续取一批数据进缓冲区,当源中的数据取完时,用-1作为结束标记。
import java.io.*;

class UserBufferedInputStream {

	private InputStream in;  //定义一个InputStream类的引用
	
	private int pos = 0,count = 0;  //定义两个变量pos用于操作数组中的元素,count记录缓冲区数据个数
	
	private byte[] buf = new byte[1024*4];  //定义一个数组作为缓冲区
	
	UserBufferedInputStream(InputStream in) {
		this.in = in;
	}
	
	//一次读一个字节,从缓冲区(字节数组)获取。
	public int userRead() throws IOException {
		
  //从源中获取一批数据到缓冲区中,需要先做判断,只有计数器为0时,才需要从源 中获取数据 
		if(count == 0 ) {
			
			count = in.read(buf);
			
			if(count < 0)
				return -1;
			
			pos = 0;
			byte b = buf[pos]; //获取缓冲区的数据
			
			count--;  //没获取完一次里面的数据就少一个,所以count--
			pos++;  //依次获取后面的数据
			
			return b&255;  //保留有效位
		}
		
		//如果count大于0就直接获取缓冲区里面的数据了
		else if(count > 0) {
			
			byte b = buf[pos];
			
			count--;
			pos++;
			
			return b&0xff;
			
		}
		return -1;
		
		
	}
	
	public void myClose()throws IOException
	{
		in.close();
	}
	

}

转换流

读取键盘录入

System.out:对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。
通过键盘录入数据,当录入一行数据后,就将该行数据进行打印,如果录入的数据是over,那么停止录入。
import java.io.*;

class Demo3ReadIN {

	public static void main(String[] args) throws IOException {

		InputStream is = System.in;  //创建一个键盘录入对象
		StringBuilder sb = new StringBuilder();  //创建一个StringBuild对象,来缓冲键盘录入的数据
		
		while(true) {
			
			int num = is.read();
			
			if(num == '\r')  //键盘录入时候会有\r\n回车符,因此进行判断
				continue;
			if(num == '\n') {
				String s = sb.toString();
				
				if("over".equals(s))
					break;
				System.out.println(s);
				sb.delete(0, sb.length());
			} else {
				sb.append((char)num);
			}
			
			
		}
		
	}

}

转换流

字符流与字节流之间的桥梁,方便了字符流与字节流之间的操作。
InputStreamReader:字节到字符的桥梁
OutputStreamReader:字符到字节的桥梁
利用转换流,让键盘录入使用readLine()方法
import java.io.*;
class  TransStreamDemo
{
	public static void main(String[] args) throws IOException
	{
		//获取键盘录入对象。
		//InputStream in = System.in;

		//将字节流对象转成字符流对象,使用转换流。InputStreamReader
		//InputStreamReader isr = new InputStreamReader(in);

		//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader

		//BufferedReader bufr = new BufferedReader(isr);


		//键盘的最常见写法,这时简化上述代码后的写法
		BufferedReader bufr = 
				new BufferedReader(new InputStreamReader(System.in));





		
//		OutputStream out = System.out;  //System.out返回的类型是PrintStream,是OouPutStream子类
//		OutputStreamWriter osw = new OutputStreamWriter(out);
//		BufferedWriter bufw = new BufferedWriter(osw);
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));




		String line = null;

		while((line=bufr.readLine())!=null)
		{
			if("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}

		bufr.close();

	}
}
字符流与字节流的最大区别
Ì使用字节流读取一个中文字符需要读取两次,一个字符由两个字节而成,使用字符流只需一次。

流的操作规律

通过三个明确来完成,到底用哪个对象
1,明确源和目的。
源:输入流。InputStream  Reader
目的:输出流。OutputStream  Writer。
2,操作的数据是否是纯文本
是:字符流。
不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象
通过设备来进行区分:
源设备:内存,硬盘。键盘
目的设备:内存,硬盘,控制台。
例如
1、将一个文本文件中数据存储到另一个文件中,复制文件。
源:因为是源,所以使用读取流。InputStream Reader 
是不是操作文本文件。
是!这时就可以选择Reader
这样体系就明确了。
接下来明确要使用该体系中的哪个对象。
明确设备:硬盘。上一个文件。
Reader体系中可以操作文件的对象是 FileReader

是否需要提高效率:是!。加入Reader体系中缓冲区 BufferedReader.
FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);

目的:OutputStream Writer
是否是纯文本。
是!Writer。
设备:硬盘,一个文件。
Writer体系中可以操作文件的对象FileWriter。
是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter

FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fw);
2、将键盘录入的数据保存到一个文件中。
这个需求中有源和目的都存在。
那么分别分析
源:InputStream Reader
是不是纯文本?是!Reader

设备:键盘。对应的对象是System.in.
不是选择Reader吗?System.in对应的不是字节流吗?为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
所以既然明确了Reader,那么就将System.in转换成Reader。
用了Reader体系中转换流,InputStreamReader

InputStreamReader isr = new InputStreamReader(System.in);

需要提高效率吗?需要!BufferedReader
BufferedReader bufr = new BufferedReader(isr);

目的:OutputStream  Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
FileWriter fw = new FileWriter("c.txt");
需要提高效率吗?需要。
BufferedWriter bufw = new BufferedWriter(fw);

File类

File类用来将文件或者文件夹封装成对象,方便对文件夹的属性信息进行操作。
File对象可以作为参数传递给流的构造函数

常见方法

File类常见方法:
1,创建
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
      和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2,删除
boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。
3,判断
boolean exists() :文件是否存在.
isFile():
isDirectory();
isHidden();
isAbsolute();
4,获取信息
getName(): 获取文件名称
getPath():获取文件路劲
getParent():看示例
getAbsolutePath()   获取文件的绝对路径
long lastModified() 
long length()
class Demo1File {

	public static void main(String[] args) throws IOException {

		Method_3();
		
	}
	
	public static void Method_3() throws IOException {
		
		File f = new File("file.txt");
		
		System.out.println(f.getPath());
		System.out.println(f.getAbsolutePath());
		
	}
	
	public static void Method_2() throws IOException {
		
		File f = new File("D:\\Material\\Java\\JavaRoom\\day06_IO\\file.txt");
		
		System.out.println(f.exists());  //记住在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在。
		System.out.println(f.isFile());
		System.out.println(f.isDirectory());
		System.out.println(f.isAbsolute());
		
		
	}
	
	public static void Method_1() throws IOException {
		
		//将file.txt封装成file对象,可以将己有的和为出现的文件或者文件夹封装成对象
		File f1 = new File("file.txt");  
		
		System.out.println(f1.createNewFile());
	//	System.out.println(f1.delete());
		
		File f2 = new File("File");
		System.out.println(f2.mkdir());
		
	}

}

list()方法

File类里面的方法
listRoots():查询电脑有效的磁盘空间
list():获取指定目录下下的文件名,包括隐藏文件,里面封装的必须是目录,否则会产生NullPointerException异常,如果目录存在但是没内容,会返回一个 数组长度0.
list(FilenameFilter filter): 用来过滤指定的文件类型
listFile():类似于list()但是listFile()返回的是对象
import java.io.*;

class Demo2File {
	
	public static void listRootsDemo() {
		
		File[] files = File.listRoots();  //电脑有效的磁盘空间大小
		
		for(File f:files) {
			
			System.out.println(f);
			
		}
		
	}
	
	public static void listDemo() {
		
		File f = new File("D:\\Tools\\");   //获取D盘目录下Tools文件夹里的文件名
		
		System.out.println(f.isDirectory());
		
		String[] s = f.list();
		for(String o: s){
			
			System.out.println(o);
			
		}
		
	}
	
	//获取指定目录下所有.java文件
	public static void listTest() {
			
		File f = new File("D:\\Material\\Java\\源代码\\day02");
		
		
		//new FilenameFilter匿名内部类,重写accept方法,把不是.java文件过滤掉
		String[] arr = f.list(new FilenameFilter() {
				
			public boolean accept(File f,String name) {
					
				return name.endsWith(".java");
					
			}
				
	    });
			
			for(String o:arr) {
				
				System.out.println(o);
				
			}
			
			
			
		}
		
		
		
		

	public static void main(String[] args) {

		File f = new File("D:\\Tools");
		
		System.out.println(f.exists());
		System.out.println(f.isDirectory());
		
		File[] files = f.listFiles();  //此方法返回的是对象,所以还可以进行相应的操作
		
		for(File file : files) {
			
			System.out.println(file.getName()+"     "+file.length());
			
		}
		
		listTest();
		
	}
	
}

递归

 函数自身直接或者间接的调用到了自身。
 一个功能在被重复使用,并每次使用时,参与运算的结果和上一次调用有关。这时可以用递归来解决问题
注意:
1,限定条件。
2,要注意递归的次数。尽量避免内存溢出。
需求:列出指定目录下文件或者文件夹,包含子目录中的内容。
思路:
在列出过程中出现的还是目录的话,还可以再次调用本功能。只需定义一个获取功能的函数,这种方式用递归来完成。
class Demo3File {

	public static void main(String[] args) {

		File f = new File("C:\\Users\\Loppz\\Music\\iTunes");
		
		getList(f);
		
	}
	
	public static void getList(File f) {
		
		File[] files = f.listFiles();  //调用fistFiles方法返回一个数组
		
		for(int x = 0 ; x < files.length ; x++) {
			
			if(files[x].isDirectory())   //对遍历出的对象进行判断,如果是文件夹的话,则继续调用此函数
				getList(files[x]);
			else
				System.out.println(files[x].getName());
			
		}
		
	}

}

利用递归求1-10的和:
class TestWork {
	
	public static void main(String[] args) {
		
		System.out.println(getSum(10));
		
	}
	
	public static int getSum(int num) {
		
		if(num == 1)
			return 1;
		return num+getSum(num -1 );
		
	}
	
}
需求:删除一个带内容的目录
在window中,删除目录从里面往外删除,就需要用到递归。
import java.io.*;

class Test1Remove {

	public static void main(String[] args) {

		File dir = new File("D:\\Meterial\\Java\\Demo");
		
		removeDir(dir);
		
	}
	
	public static void removeDir(File dir) {
		
		File[] files = dir.listFiles();
		
		for(File file : files) {
			
			if(file.isDirectory())  //判断是否是文件夹
				removeDir(file);  //是的话则再次调用方法
			else 
				file.delete();  //不是的话则删除掉
			
		}
		
		dir.delete();  //删除最后的文件夹
		
	}

}

Properties集合

Properties是hashtable的子类。
特点:
1. 该集合中的键和值都是字符串类型
2. 集合中的数据可以保存到流中,或者从流中获取
3. 通常该集合用于操作以键值对形式存在的配置文件
常用方法演示:
import java.io.*;


class Demo4Properties {

	public static void main(String[] args) {

		setAndGet();
		
	}
	
	public static void setAndGet() {
		
		Properties prop = new Properties();
		
		prop.setProperty("Jack", "29");
		prop.setProperty("Nacy", "28");
		
		prop.setProperty("Jack", "41");  //setProperty方法既可以添加键值对,又可以修改。
//		String value = prop.getProperty("Jack");   //获取jack的年龄
		
//		System.out.println(value);
		
		Set<String> names = prop.stringPropertyNames();  //调用stringPropertyNames()方法返回一个装有key的set集合
		for(String name : names) {
			
			System.out.println(name);
			
		}
		
	}

将流中的数据存储到集合中,假如有一个文件info.txt,里面的数据为key = value格式
思路
1,用一个流和需要操作的文件文件关联。
2,读取一行数据,将该行数据用"="进行切割。
3,等号左边作为键,右边作为值。存入到Properties集合中即可。
import java.io.*;
import java.util.*;
class TestWork {
public static void main(String[] args) {
		
		BufferedReader br = null;
		
		try {
			
			br = new BufferedReader(new FileReader("info.txt"));
			Properties prop = new Properties();
			
			String line = null;
			while((line = br.readLine()) != null) {
				
				String[] arr = line.split("=");
				prop.setProperty(arr[0], arr[1]);
				
			}
			
			System.out.println(prop);
			
			
		}
		catch(IOException e) {
			
		}
		finally {
			
			if(br != null) {
				try {
					br.close();
				}
				catch(IOException e) {
					
				}
				
			}
			
		}
		
	}
}
用Properties中特有的方法:
public static void loadDemo() throws IOException {
		
		Properties prop = new Properties();
		FileInputStream fis = new FileInputStream("info.txt");
		
		prop.load(fis);  //把数据从输入流存入集合
		
		FileOutputStream fos = new FileOutputStream("info.txt");
		
		prop.store(fos, "aaaa");  //把集合中的数据存入输出流打印到本地
		
		prop.list(System.out);  //list集合方法列出集合中的数据
		
		fos.close();
		fis.close();
		
	}
 需求:限制程序运行次数。当运行次数到达5次时,给出,请您注册的提示。并不再让该程序执行。
  思路:
  1、建立一个配置文件,定义一个键值对用于记录该软件的使用次数。
  2、把键值对通过输入流加载到Properties集合中,判断使用次数
  3、如果使用次数已到,则给出提示,如果没到便让值+1通过输出流存入到配置文件
import java.io.*;
import java.util.*;

class Test3RunCount {

	public static void main(String[] args) throws IOException {

		Properties prop = new Properties();
		
               //创建一个File对象,对其进行判断存不存在
		File file = new File("count.ini");
		
		if(!file.exists())
			file.createNewFile();
		
		FileInputStream fis = new FileInputStream(file);
		
		prop.load(fis);
		
		int count = 0;  //定义一个变量用来记录次数
		
		String value = prop.getProperty("time");   //通过time获取次数
		if(value != null) {   //判断是否为空,不是的话则执行下面的语句把字符串转换成int型
			count = Integer.parseInt(value);
			if(count > 5) {  //限制使用次数
				System.out.println("使用次数已到");
				return;
			}
		}
		
		count++;  //使用一次加一次
		prop.setProperty("time",count+"");  //对键值对进行修改
		
		FileOutputStream fos = new FileOutputStream(file);
		
		prop.store(fos,"");
		
		fos.close();
		fis.close();
		
	}

}

将一个指定目录下的java文件的绝对路径,存储到一个文本文件中,建立一个java文件列表文件。
思路:
1,对指定的目录进行递归。
2,获取递归过程所以的java文件的路径。
3,将这些路径存储到集合中。
4,将集合中的数据写入到一个文件中。
import java.io.*;
import java.util.*;

class Test2FileList {

	public static void main(String[] args) {
                File file1 = new File("D:\\Material\\Java\\源代码");
		List<file> list = new ArrayList<file>();
	
		method(file1,list);
		
		File file2 = new File(file1,"java.txt");
		userWriter(list,file2.toString());
		
	}
	
	//顶一个函数接受File对象和数组
	public static void method(File dir,List<File> list) {
		
		File[] dirs = dir.listFiles();
		
		//File数组进行遍历,判断是否是文件夹
		for(File file : dirs) {
			
			if(file.isDirectory())  //如果是则继续,调用方法
				method(file,list);
			else {
				//如果不是则判断是不是.java文件,是就添加进集合
				if(file.getName().endsWith(".java"))
					list.add(file);
				
			}
			
		}
		
	}
	
	//定义一个函数用来接受,集合和要存储的文件名
	public static void userWriter(List<File> list,String name) {
		
		BufferedWriter buf = null;
		try {
			
			buf = new BufferedWriter(new FileWriter(name));
			
			for(File f : list) {
				
				String path = f.getAbsolutePath();
				
				buf.write(path);
				buf.newLine();
				buf.flush();
			}
			
		}
		catch(IOException e) {
			
		}
		finally {
			
			if(buf != null){
				
				try {
					buf.close();
				}
				catch(IOException e) {
					
				}
				
			}
			
		}
		
	}

}</file></file>












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值