黑马程序员----IO流(中)

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


IO流

1.File类

对文件和文件夹进行封装得到的类,我们知道在IO流中,文件或者文件夹是比较复杂的对象,如果不封装成对象的话,我们自己操作起来很费力,不过值得庆幸的是java把他们封装成了对象--File,使用该对象我们可以创建、删除、获取、判断等对文件或者文件夹进行一系列操作,而这些操作都是文件和文件夹最清楚,因此定在在File类中。

小知识点:

  separator字段:跟系统相关的名称分隔符(windows下就是\),使用这个字段代替"\\",具有跨平台特性
new出来的File对象还不是一个硬盘上的文件或者文件夹,而是存在于内存中的,只有当我们创建之后才会出现在硬盘上。


常用方法:

创建:
boolean createNewFile();在File对象路径属性指定位置创建文件,如果已有文件,则创建失败
不同于输出流对象,输出流对象一创建,则文件也被创建
boolean mkdir();创建一级文件夹。
boolean mkdirs();创建多级文件夹。
删除:
boolean delete();删除当前对象表示的文件。
void deleteOnExit();jvm退出时删除文件
判断:
boolean exists();文件或文件夹是否存在存在表示存在于硬盘上),该方法是很多其他判断方法的前提方法,也就是说例如我们判断一个File对象是否为文件,使用isFile()方法,但是之前我们应该先判断该文件或文件夹是否存在于硬盘,如果不存在,不管它是文件还是文件夹总是,isFile总是返回false
boolean isDirectory();判断对象是否为一个文件夹
boolean isFile();判断对象是否为一个文件
boolean isHidden();判断对象是否为隐藏文件或文件夹
进行这些判断前,先判断其是否存在。
boolean isAbsolute();
该判断不需要文件存在。
获取:
getName();获取对象名
getPath();封装什么路径就返回什么
getParent();在封装时如果没明确指定文件或文件夹的父目录,那么就返回null,例如:File("a.txt").parent();返回null。
getAbsolutePath();不管封装什么路径,都是返回绝对路径
length();返回文件大小
lastModified();最后一次修改时间
修改:
renameTo(File dest);用dest对当前File对象进行重命名(如果路径有变化,那么就会有移动文件的效果)。
例如:new File("c:\\a.txt").renameTo(new File("d:\\b.txt"));就是将C盘下的a.txt移动到D盘,并改名为b.txt
文件列表:
String[] list();列出当前对象下所有文件和文件夹,如果当前对象为文件,返回null
String[] list(FilenameFilter filter);文件名过滤。accept(dir,name):dir表示当前目录,name表示其中所有文件名
*File[] listFiles();
*File[] listFiles(FilenameFilter filter);与list相比,返回的是文件和文件夹对象,而不只是名称
开发中常用listFiles,因为它
返回的是File对象,而File对象 功能更强大,能对文件进行更多的操作
File[] listRoots();列出系统根目录。


File类练习:

/*
测试File类方法
小练习:取出指定目录下指定后缀名的所有文件
*/
import java.io.*;
class FileDemo 
{
	public static void main(String[] args) throws IOException
	{
		listFiles_demo();
	}
	private static void create_demo()throws IOException
	{
		//File f1 = new File("ccc\\file.txt");
		File f1 = new File("file.txt");//此时f1还是不存在的
		f1.createNewFile();//执行这句后,f1出现在硬盘上,会报异常,当路径不存在时

		File f2 = new File("file\\file.txt");
		f2.mkdir();//创建目录,也就是文件夹,有后缀名的不一定是文件,还是需要判断的

		File f3 = new File("file\\temp\\temp\\temp\\file.txt");
		f3.mkdirs();//mkdir只能创建一级目录,而mkdirs可以创建多级目录
	}
	private static void delete_demo()throws IOException
	{
		File f=new File("delete.txt");
		//sop(f.mkdir());
		sop(f.createNewFile());//既调用了创建文件,又创建文件夹的话,只有第一句成功,其他失败
		sop("delete:"+f.delete());
		sop("delete:"+f.delete());//失败

		File f2=new File("deleteOnExit.txt");
		f2.mkdir();
		f2.deleteOnExit();
		try{Thread.sleep(3000);}catch(Exception e){}//使得jvm延迟3秒关闭,我们可以看到deleteOnExit.txt是先创建了,3秒后被删除
	}
	private static void judge_demo()throws IOException
	{
		File f=new File("temp");
		sop("exists:"+f.exists());
		f.createNewFile();
		sop("exists:"+f.exists());//判断是文件还是文件夹前,需要先判断是否存在,如果不存在,则怎么判断都是返回false
		sop("directory:"+f.isDirectory());
		sop("file:"+f.isFile());
		sop("hidden:"+f.isHidden());
	}
	private static void get_demo()
	{
		File f1 = new File("file.txt");
		File f2 = new File("e:\\JavaProgram\\day20\\file2.txt");
		sop("f1 name:"+f1.getName());
		sop("f2 name:"+f2.getName());
		sop("f1 path:"+f1.getPath());
		sop("f2 path:"+f2.getPath());
		sop("f1 abspath:"+f1.getAbsolutePath());
		sop("f2 abspath:"+f2.getAbsolutePath());
		sop("f1 parent:"+f1.getParent());
		sop("f2 parent:"+f2.getParent());
		sop("f1 length:"+f1.length());
		sop("f2 length:"+f2.length());
		sop("f1 lastModified:"+f1.lastModified());
		sop("f2 lastModified:"+f2.lastModified());
	}
	private static void renameTo_demo()
	{
		File f1=new File("rename1.txt");
		File f2=new File("rename2.txt");
		f1.renameTo(f2);
	}
	private static void listRoots_demo()
	{
		for(File f : File.listRoots())//静态方法,列出所有可用盘符
		{
			sop(f);
		}
	}
	private static void list_demo_1()
	{
		File dir=new File("c:\\");
		for(String name : dir.list())//列出所有文件文件夹,包括隐藏的
		{
			sop(name);
		}
	}
	private static void list_demo_2()
	{
		//获取指定目录下所有.java文件
		File dir=new File("E:"+File.separator+"JavaProgram"+File.separator+"day19");
		String[] names=dir.list(new FilenameFilter(){
			public boolean accept(File dir,String name)
			{
				if(name.endsWith(".java"))return true;
				//文件以.java结尾,并且该对象是文件而不是文件夹,就返回真
				//小问题:如果一个文件夹名为xxx.java,那么也会被认为是一个java文件返回
				return false;
			}
		});
		for(String name : names)
		{
			sop(name);
		}
	}
	private static void listFiles_demo()
	{
		File dir=new File("d:\\");
		for(File file : dir.listFiles())
		{
			sop("name:"+file.getName()+"...length:"+file.length()+"...parent:"+file.getParent());
		}
	}
	private static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
运行图:

列出目录下所有内容,包括子目录中的内容(递归解决):

//需求:获取到当前目录及其子目录下所有文件
//思路:递归
import java.io.*;
class FileTest 
{
	public static void main(String[] args) 
	{
		File root=new File("e:\\斗兽棋\\");
		//File root=new File("e:\\");
		printDir(root,1);
	}
	private static void printDir(File dir,int c)//目录名
	{
		System.out.println(dir.getName()+":");
		File[] files=dir.listFiles();
		if(files.length<=0)
		{
			for(int j=0;j<c;j++)//每一行打印几个\t是不确定的,由c决定,c其实也就是递归深度。
				System.out.print("    ");
			System.out.println("|--空");
		}
		for(int i=0;i<files.length;i++)
		{
			for(int j=0;j<c;j++)//每一行打印几个\t是不确定的,由c决定,c其实也就是递归深度。
				System.out.print("    ");
				//System.out.print("\t");
			if(files[i].isFile())
				System.out.println("|--"+files[i].getName());
			if(files[i].isDirectory())
			{
				printDir(files[i],c+1);
			}
		}
	}
}
运行图:

删除一个有内容的目录(递归):

思路:windows规定,不能直接删除一个有内容的文件夹,而是需要先将里面的所有文件都删除,这里我们就来使用递归来删除里面的所有内容。
//删除带内容的目录
/*
原理:从内往外删除
*/
import java.io.*;
class FileTest2 
{
	public static void main(String[] args) 
	{
		
		//System.out.println(new File("E:\\listFilesTest\\").delete());
		//直接删除失败,因为windows规定,如果文件夹不为空,不能直接删除
		//而是将其中内容全部删除后,再删除掉该文件夹

		deleteDir(new File("E:\\listFilesTest\\"));
	}
	private static void deleteDir(File dir)
	{
		if(dir.isHidden())return;//隐藏文件不删除
		for(File f : dir.listFiles())
		{
			if(f.isDirectory())
				deleteDir(f);//如果为文件夹,那么就调用本方法,传入该文件夹
			else
				f.delete();//删除一个文件夹中的文件
		}
		dir.delete();//删掉已经删掉所有内容的空文件夹,如果没有这句,那么删掉的只是文件,而文件夹被保留了下来
	}
}
运行图:



我们可以看到,listFilesTest文件夹已经不存在了,删除成功。


2.Properties类

HashTable的子类。
集合中与IO技术相结合的集合容器。该集合特点:可以用于操作硬盘上的键值对形式的配置文件
用法:与流结合,操作配置文件。从流中获取键值对,或者将一堆键值对存放到流中

常用方法:

setProperty(),getProperty();这里的设置只是改变了内存中的键值对内容,而不是硬盘上的,如果也要改变硬盘上的,那么需要使用store方法
load(InputStream)从流中获取键值对
list(PrintStream)将键值对写入打印流中
store(OutputStream,String注释)
store(Writer,String注释)将集合中键值对写入输出流中


Properties类小练习:

//测试Properties常用方法
import java.io.*;
import java.util.*;
class PropertiesTest2 
{
	public static void main(String[] args)throws IOException 
	{
		method();
	}
	private static void method()throws IOException
	{
		//获取配置信息,更改后,打印,并将更改内容作用于硬盘的配置文件上
		Properties prop=new Properties();
		prop.load(new FileReader("info.txt"));
		prop.list(System.out);

		prop.setProperty("helong","22");//修改了helong的值
		prop.setProperty("zhaoliu","77");//增加了一对键值对

		prop.list(System.out);//我们发现,改变并没有体现在info.txt文件上,这是因为setProperty的修改只是针对内存而言

		prop.store(new FileWriter("info.txt"),"修改");//将集合内容写到输出流中,也就是硬盘上的文件上,"修改"为注释,不影响配置内容
		//会自动加上时间为注释
		//以#开头的一行在配置文件中为注释行,不会被加载到集合中
		//发现:无法识别中文
	}
}
运行图:



//将info.txt文件中的键值对存放到集合中
/*
思路:
1.使用流与info关联
2.使用=切割info
3.将切割后数据存放到Properties中
*/
import java.io.*;
import java.util.*;
class PropertiesTest 
{
	public static void main(String[] args) throws IOException
	{
		BufferedReader bufr=new BufferedReader(new FileReader("info.txt"));
		Properties prop=new Properties();
		for(String line=bufr.readLine();line!=null;line=bufr.readLine())
		{
			String[] strs=line.split("=");
			if(strs.length==2)
				prop.setProperty(strs[0],strs[1]);
			else
				prop.setProperty(strs[0],"");
		}
		System.out.println(prop);

		Properties prop2=new Properties();
		prop2.load(new FileInputStream("info.txt"));//load用于从流中取出键值对
		prop2.list(System.out);//将集合中键值对写入流中
	}
}
运行图:


记录程序运行次数,如果达到10次,则给出注册信息,并不能使用程序

/*
需求:记录程序运行次数,如果达到10次,则给出注册信息,并不能使用程序
*/
import java.io.*;
import java.util.*;
class PropertiesTest3 
{
	public static void main(String[] args) throws IOException
	{
		Properties prop=new Properties();//用于操作配置文件
		File file=new File("count.ini");//ini后缀名为windows配置文件后缀名
		if(!file.exists())//第一次运行程序时,配置文件不存在
		{
			file.createNewFile();
			prop.load(new FileReader(file.toString()));
			prop.setProperty("times","1");
			prop.store(new FileWriter(file.toString()),"used");
			System.out.println("程序正常运行.....");
		}
		else
		{
			prop.load(new FileReader(file.toString()));
			int value = Integer.parseInt(prop.getProperty("times"));
			if(value>=10)
				register();
			else
			{<span style="white-space:pre">	</span>System.out.println("您还能试用"+(10-value-1)+"次!");
				prop.setProperty("times",value+1+"");
				prop.store(new FileWriter(file.toString()),"used");
				System.out.println("程序正常运行.....");
			}
		}
	}
	private static void register()
	{
		System.out.println("请前往官网注册,获取注册码!!www.helong.com");
		System.out.println("注册码:......");
	}
}
运行图:




3.打印流

该流提供打印方法,可以将各种类型数据原样打印。
PrintStream:
构造函数接收参数类型:File,String字符串路径,OutputStream字节输出流
非常常用PrintWriter:
构造函数接收参数类型:File,String字符串路径,OutputStream字节输出流,Reader字符输出流

4.序列流

合并流--多个读取流对应一个输出流
SequenceInputStream:从第一个串联的流文件开头读取,知道串联的最后一个流文件的结尾为止
两个构造函数,如果合并两个流,使用SequenceInputStream(InputStream,InputStream)
如果合并多个流,使用SequenceInputStream(Enumeration<? extends InputStream> en)通常使用这个,由于使用到了Enumeration,因此是使用集合中的Vector类来存放多个流

序列流练习:

//测试使用SequenceInputStream来将多个文件合并到一个新文件中
import java.io.*;
import java.util.*;
class SequenceDemo 
{
	public static void main(String[] args) throws IOException
	{
		Vector<FileInputStream> v=new Vector<FileInputStream>();
		v.add(new FileInputStream("1.txt"));
		v.add(new FileInputStream("2.txt"));
		v.add(new FileInputStream("3.txt"));

		SequenceInputStream sis=new SequenceInputStream(v.elements());

		FileOutputStream fos=new FileOutputStream("123.txt");
		for(int b=sis.read();b!=-1;b=sis.read())
		{
			fos.write(b);
		}
		fos.close();
		sis.close();

	}
}
运行图:





5.切割组合文件

可以自己指定大小,每当读到足够大小时,写入文件,然后打开一个新的文件,这就是切割的原理。
/*
需求:切割一个bmp文件,按照1M,放到parts文件夹中
以碎片文件形式存放。
将多个碎片文件合并成原来的bmp文件,也放到parts文件夹中,
并能使用。
*/
import java.io.*;
import java.util.*;
class SplitMergeTest 
{
	public static void main(String[] args) throws IOException
	{
		//splitDemo();
		merge();
	}
	private static void merge()throws IOException
	{
		/*//使用Vector效率太低,因为它线程同步
		Vector<FileInputStream> v=new Vector<FileInputStream>();
		File f=new File("parts");
		for(File temp : f.listFiles())//取出文件夹中所有文件,放到集合中
			v.add(new FileInputStream(temp.getAbsolutePath()));
		SequenceInputStream sis=new SequenceInputStream(v.elements());
		*/
		
		ArrayList<FileInputStream> arr=new ArrayList<FileInputStream>();
		File f=new File("parts");
		for(File temp : f.listFiles())//取出文件夹中所有文件,放到集合中
			arr.add(new FileInputStream(temp.getAbsolutePath()));
		final Iterator<FileInputStream> it=arr.iterator();//it作为局部变量,被内部类访问,需要final修饰,当然JDK1.8后会自动加上final
		Enumeration<FileInputStream> en=new Enumeration<FileInputStream>(){
			public boolean hasMoreElements()
			{
				return it.hasNext();
			}
			public FileInputStream nextElement()
			{
				return it.next();
			}
		};
		SequenceInputStream sis=new SequenceInputStream(en);

		FileOutputStream fos=new FileOutputStream("merge.jpg");
		byte[] by=new byte[1024];
		for(int len=sis.read(by);len!=-1;len=sis.read(by))
		{
			fos.write(by,0,len);
		}
		fos.close();
		sis.close();
	}
	private static void  splitDemo()throws IOException
	{
		FileInputStream fis=new FileInputStream("split.jpg");
		FileOutputStream fos=null;
		byte[] by=new byte[1024];
		out:for(int count=0,len=0;len!=-1;)
		{
			fos=new FileOutputStream("parts\\"+(++count)+".part");
			for(int i=0;i<300;i++)
			{
				len=fis.read(by);
				if(len==-1){fos.close();break out;}
				fos.write(by,0,len);
			}
			fos.close();
		}
		fis.close();
	}
}<strong style="color: rgb(0, 0, 153);">
</strong>
运行图:








------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值