您的位置:首页 > 职场人生

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

2015-07-16 09:22 495 查看
------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培训、期待与您交流! -------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: