----------- android培训、java培训、期待与您交流! ------------
File类
文件是一类事物,它有自己的名字、属性、大小、位置、后缀名等属性信息,那么根据面向对象的思想,就可以把它封装描述为一个类,
这个类就java.io包中的File类。File类是文件和目录路径名的抽象表示形式,它可以方便的对文件与文件夹的属性信息进行操作,也可以作为参数传递给流对象。
它弥补了了流的不足,比如流只能操作数据,而不能操作文件的属性与文件夹。
java.lang.Object
java.io.File
文件和目录路径名的抽象表示形式。
构造方法摘要
File(File parent, String child)
File(String pathname)
File(String parent, String child)
File(URI uri)
//将存在或不存在的文件或文件夹封装成对象
File f1 = newFile("filedemo.txt");
//将目录和文件名分开存放
File f2 = newFile("c:\\bi\\day20", "filedemo2.txt");
//目录可以用File表示
File d1 = newFile("c:\\bi\\day20");
File f3 = new File(d1,"filedemo3.txt"); //将File传入构造器
File.toString()返回的是文件的路径,封装的是什么,返回的就是什么。如果封装的是相对路径,返回的也是相对路径。
关于目录分割符:
windows使用\作为目录分割符,/也可以用。
linux系统使用/作为分割符。
因为各个平台的目录分割符不统一,所以使用"c:\\bi"这种形式的定义方式不具备跨平台性,此时可以使用File文件的静态字段separator来标示一个与系统有关的默认名称分隔符。
static String separator
static char separatorChar
File类常用方法:
1.创建:
boolean createNewFile()
File f = new File("file.txt");
sop("create: " +f.createNewFile());
在指定位置创建文件,如果该文件已经存在,则不创建返回false。
如果文件不存在,则创建空文件,返回true。
注意:这里和输出流不一样,输出流与文件关联后,如果文件不存在直接创建文件,如果文件存在,则覆盖原文件。
//创建在默认临时文件目录中
static File createTempFile(String 前缀,String 后缀)
//创建在指定目录中
static File createTempFile(String 前缀,String 后缀, Filedirectory)
创建文件夹:
boolean mkdir() //直接创建目录
boolean mkdirs() //如果创建此目录所需的父目录不存在,则依次创建
2.删除:
boolean delete() //删除
void deleteOnExit() //在退出时删除
3.判断:
boolean exists()
boolean isDirectory()
boolean isFile()
boolean isHidden()
boolean canExecute() //文件是否可执行
boolean canRead()
boolean canWrite()
boolean isAbsolute()
boolean equals(Object obj)
intcompareTo(File pathname)
进行isDirectory和isFile判断之前,一定要先进行exists判断。
4.获取:
getName()
getParent() //返回指明了的父目录,如果未指明,返回null
getPath()
getAbsolutePath()
lastModified()
length() //目录的大小为0
String[] list()
String[] list(FilenameFilter filter)
File[] listFiles()
File[] ListFiles(FileFilter filter)
File[] ListFiles(FilenameFilter filter)
File[] listRoots()
5.重命名
boolean renameTo(File dest)
重命名操作无法将一个文件从一个文件系统移动到另一个文件系统
练习:
class FileDemo
{
public static void main(String[] args) throws IOException
{
method_4();
}
public static void method_4() throws IOException
{
File f1 = new File("c:\\Test.java");
File f2 = new File("c:\\haha.java");
System.out.println("rename:"+f1.renameTo(f2));//类似剪切,并修改文件名
}
public static void method_3() throws IOException
{
File f = new File("FileDemo.java");
System.out.println("path:"+f.length());
System.out.println("path:"+f.getAbsolutePath());
}
public static void method_2() throws IOException
{
File f = new File("file.txt");
f.mkdir();
//在判断文件对象是否是文件或者目录时,必须先判断该文件是否存在.
//通过exists()判断.
System.out.println("dir:"+f.isDirectory());
System.out.println("dir:"+f.isFile());
}
public static void method_1() throws IOException
{
File f = new File("file.txt");
System.out.println("create:"+f.createNewFile());//创建
System.out.println("delete:"+f.delete());//删除
System.out.println("execute:"+f.canExecute());//判断是否能执行
System.out.println("exist:"+f.exists());//判断文件是否存在
}
//创建File对象
public static void consMethod()
{
//将a.txt封装成file对象.可以将已有的和未出现的文件或者文件夹封装成对象.
File f1 = new File("c:\\abc\\a.txt");
//File.separator跨平台的分隔符类似newLine()
File f2 = new File("c:"+File.separator+"abc","b.txt");
File d = new File("c:\\abc");
File f3 = new File(d,"c.txt");
System.out.println("f1:"+f1);
System.out.println("f2:"+f2);
System.out.println("f3:"+f3);
}
}
class FileDemo2
{
public static void main(String[] args)
{
listFileDemo();
}
public static void listFileDemo()
{
File dir = new File("d:\\learn\\day19");
//获取当前目录下所有文件的对象.
File[] files = dir.listFiles();
for (File f : files )
{
System.out.println(f.getName()+"::"+f.length());
}
}
public static void listDemo()
{
File f = new File("D:\\learn\\day19");
//调用list方法的file对象封装的必须是一个目录,并且存在.
String[] names = f.list(new MyFilenameFileter());//传进一个过滤器
for(String s : names)
{
System.out.println(s);
}
}
public static void listRootsDemo()
{
//列出电脑中有效的盘符
File[] files = File.listRoots();
for(File f : files)
{
System.out.println(f);
}
}
}
//定义一个过滤器
class MyFilenameFileter implementsFilenameFilter
{
public boolean accept(File dir,String name)
{
return name.endsWith(".class");
}
}
递归--列出目录下所有内容:
/*
列出指定目录下文件或者文件夹,包含子目录中的内容.
也就是列出指定目录下所有内容.
因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可.
在列出过程中出现的还是目录的话,还可以再次调用本功能.
也就是函数自身调用自身.
这种表现形式,或者变成手法,称为递归.
递归要注意的:
1.一定要限定条件
2.要注意递归的次数,尽量避免内存溢出.
*/
import java.io.*;
class FileDemo3
{
public static void main(String[] args)
{
File f = new File("d:\\learn");
//showDir(f);
//toBin(6);
System.out.println(getSum(10));
}
public static int getSum(int n)
{
if (n==1)
return 1;
else
return n+getSum(n-1);
}
public static void toBin(int n)
{
if (n>0)
{
toBin(n/2);
System.out.print(n%2);
}
}
public static void showDir(File dir)
{
System.out.println(dir);
File[] files = dir.listFiles();
for(int x= 0; x<files.length; x++)
{
if(files[x].isDirectory())
showDir(files[x]);
else
System.out.println(files[x]);
}
}
}
列出目录下所有内容--带层级
import java.io.*;
class FileDemo4
{
public static void main(String[] args)
{
File f = new File("d:\\learn");
showDir(f,0);
}
//定义一个层级方法
public static String getLevel(int level)
{
StringBuilder sb = new StringBuilder();
for (int x = 1; x<level; x++)
{
sb.append(" ");
}
return sb.toString();
}
public static void showDir(File dir,int level)
{
System.out.println(getLevel(level)+dir);
level++;
File[] files = dir.listFiles();
for(int x= 0; x<files.length; x++)
{
if(files[x].isDirectory())
showDir(files[x],level);
else
System.out.println(getLevel(level)+files[x]);
}
}
}
删除带内容的目录
import java.io.*;
/*
删除原理:
在windows中,删除目录是从里面往外删除的.
既然是从里面往外删除,就需要用到递归.
*/
class RemoveDir
{
public static void main(String[] args)
{
File dir = new File("d:\\新建文件夹");
removeDir(dir);
}
public static void removeDir(File dir)
{
File [] files = dir.listFiles();
for (int x=0; x<files.length; x++ )
{
if(files[x].isDirectory())
removeDir(files[x]);
else
System.out.println(files[x]+"--file--"+files[x].delete());
}
System.out.println(dir+"==dir=="+dir.delete());
}
}
创建java文件列表
/*
练习
将一个指定目录下的java文件的绝对路径,存储到一个文本文件中
建立一个java文件列表文件.
思路:
1.对指定的目录进行递归.
2.获取递归过程所有的java文件路径
3.将这些路径存储到集合中.
4.将集合中的数据写入到一个文件中
*/
import java.io.*;
import java.util.*;
class JavaFileList
{
public static void main(String[] args) throws IOException
{
File dir = new File("d:\\learn");
List<File> list = new ArrayList<File>();
fileToList(dir,list);
File file = new File(dir,"javalist.txt");
writeTOFile(list,file);
}
public static void fileToList(File dir,List<File> list)
{
File[] files = dir.listFiles();
for (File f : files )
{
if (f.isDirectory())
fileToList(f,list);
else
{
if(f.getName().endsWith(".java"));
list.add(f);
}
}
}
public static void writeTOFile(List<File> list,File file)throwsIOException
{
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
for (File f : list )
{
bw.write(f.getAbsolutePath());
bw.newLine();
bw.flush();
}
}
}
Properties类
Properties是hashtable的子类.
也就是说它具备map集合的特点.而且它里面存储的键值对都是字符串.
是集合中和IO技术相集合的集合容器.
该对象的特点:可以用于键值对形式的配置文件
那么在加载数据时,需要数据有固定格式:键=值;
import java.io.*;
import java.util.*;
import java.util.*;
class PropertiesDemo
{
public static void main(String[] args) throws IOException
{
//setAndget();
//method_1();
loadDemo();
}
//Properties中提供了load方法来完成method_1
public static void loadDemo() throws IOException
{
Properties prop = new Properties();
FileInputStream fis = newFileInputStream("c:\\info.txt");
prop.load(fis);
prop.setProperty("zhangsan","88");
FileOutputStream fos = newFileOutputStream("c:\\info.txt");
prop.store(fos,"haha");
prop.list(System.out);
fis.close();
fos.close();
}
//演示,如何将流中的数据存储到集合中.
//想要将info.txt中键值数据存到集合中进行操作.
/*
1.用一个流和info.txt文件关联.
2.读取一个数据,将该数据用"="进行切割
3.等号左面作为键,右边作为值.存入到Properties集合中即可
*/
public static void method_1() throws IOException
{
BufferedReader br = new BufferedReader(newFileReader("c:\\info.txt"));
Properties prop = new Properties();
String line = null;
while ((line=br.readLine())!=null)
{
String[] arr = line.split("=");
prop.setProperty(arr[0],arr[1]);
}
br.close();
System.out.println(prop);
}
//设置和获取元素.
public static void setAndget()
{
Properties prop = new Properties();
prop.setProperty("zhangsan","39");
prop.setProperty("lisi","47");
System.out.println(prop);
System.out.println(prop.getProperty("lisi"));
prop.setProperty("lisi",90+"");
Set<String> names = prop.stringPropertyNames();
for (String s : names)
{
System.out.println(s+":"+prop.getProperty(s));
}
}
}
Properties练习--限定程序执行次数
import java.io.*;
import java.util.*;
/*
用于记录应用程序运行次数.
如果使用次数已到,那么给出注册提示.
很容易想到的是:计数器.
开始该计数器定义在程序中,随着程序的运行而存在的内存中,并进行字增
可是随着该应用程序的推出,该计数器也在内存中消失了.
下一次在启动该程序,又重新开始从0计数
这样就不是我们想要的.
程序即使结束,该计数器的值也存在.
下次程序启动会先家在该计数器的值并加1后在重新存储起来.
所以要建立一个配置文件,用于记录该软件的使用次数.
该配置文件使用键值对的形式.
这样便于阅读数据,并操作数据.
键值对数据是map集合
数据是以文件形式存储,用到IO技术.
那么map-->Properties + IO
配置文件可以实现应用程序数据的共享.
1.创建有给读取流关联配置文件
*/
class RunCount
{
public static void main(String[] args) throws IOException
{
File file = new File("c:\\property.ini");
if(!file.exists())
file.createNewFile();
Properties prop = new Properties();
FileInputStream fr = new FileInputStream(file);
prop.load(fr);
String value = prop.getProperty("count");
if(value==null)
prop.put("count","1");
else
{
System.out.println(value);
int count = Integer.parseInt(value);
if(count>=5)
{
System.out.println("您的使用次数已到");
return;
}
count++;
prop.setProperty("count",count+"");
}
FileOutputStream fw = new FileOutputStream(file);//输出流会覆盖原文件
prop.store(fw,"test");
fr.close();
fw.close();
}
}
打印流PrintWriter和PrintStream
打印流:
该流提供了打印方法,可以将各种数据类型的数据都原样打印.
字节打印流
PrintStream
构造函数可以接收的参数类型.
1.File对象.File
2.字符串路径.String
3.字节输出流.OutputStream
字符打印流
PrintWriter(常用)
构造函数可以接收的参数类型
1.File对象.File
2.字符串路径.String
3.字节输出流.OutputStream
4.字符输出流.Writer
import java.io.*;
class PrintStreamDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader br =
new BufferedReader(newInputStreamReader(System.in));
PrintWriter pw =
new PrintWriter(newFileWriter("c:\\demo.txt"),true);//可实现自动刷新
String line = null;
while ((line=br.readLine())!=null)
{
if(line.equals("over"))
break;
pw.println(line.toUpperCase());
}
br.close();
pw.close();
}
}
序列合并流
SequenceInputStream是能对多个流进行合并成一个读取流,它在构造时需要传入Enumeration,而这个只用Vector中有,所以这个多个读取流要加入Vector集合中。注意:它只是对读取流进行合并。
它使用步骤:
1.创建Vector<InputStream>
2.将要合并的InputStream加入Vector
3.通过Vector获取Enumeration
4.创建SequenceInputStream,将Enumeration作为参数传入。
import java.io.*;
import java.util.*;
class SequenceDemo
{
public static void main(String[] args) throws IOException
{
Vector<FileInputStream> v = newVector<FileInputStream>();
v.add(new FileInputStream("c:\\1.txt"));
v.add(new FileInputStream("c:\\2.txt"));
v.add(new FileInputStream("c:\\3.txt"));
Enumeration<FileInputStream> e = v.elements();
SequenceInputStream sis = new SequenceInputStream(e);
FileOutputStream fos = new FileOutputStream("c:\\4.txt");
byte[] bys = new byte[1024];
int len = 0;
while ((len = sis.read(bys))!=-1)
{
fos.write(bys,0,len);
}
fos.close();
sis.close();
}
}
文件的切割和合并
import java.io.*;
import java.util.*;
class SplitFile
{
public static void main(String[] args) throws IOException
{
//splitFile();
merge();
}
//合并
public static void merge() throws IOException
{
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
al.add(new FileInputStream("c:\\2.part"));
al.add(new FileInputStream("c:\\3.part"));
al.add(new FileInputStream("c:\\4.part"));
final Iterator<FileInputStream> it = al.iterator();
Enumeration<FileInputStream> en = newEnumeration<FileInputStream>()
{
public booleanhasMoreElements()
{
return it.hasNext();
}
public FileInputStreamnextElement()
{
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("c:\\0.jpg");
byte[] bys = new byte[1024];
int len = 0;
while ((len=sis.read(bys))!=-1)
{
fos.write(bys,0,len);
}
sis.close();
fos.close();
}
//切割
public static void splitFile() throws IOException
{
FileInputStream fis = new FileInputStream("c:\\1.jpg");
FileOutputStream fos = null;
byte[] bys = new byte[1024*50];
int len = 0;
int count = 2;
while ((len=fis.read(bys))!=-1)
{
fos = newFileOutputStream("c:\\"+(count++)+".part");
fos.write(bys,0,len);
fos.close();
}
fis.close();
}
}
对象序列化:
被序列化的类必须实现Serializable接口,来获得ID.
也可以自己设置ID,例如:static final long serialVersionUID = 42L
static静态成员是不能被序列化的.
transient修饰的成员也是不能被序列化的
import java.io.*;
class ObjectStreamDemo
{
public static void main(String[] args) throws Exception
{
//writeObj();
readObj();
}
public static void readObj() throws Exception
{
ObjectInputStream ois =
new ObjectInputStream(newFileInputStream("obj.txt"));
Person p = (Person)ois.readObject();
System.out.println(p);
ois.close();
}
public static void writeObj() throws IOException
{
ObjectOutputStream oos =
new ObjectOutputStream(newFileOutputStream("obj.txt"));
oos.writeObject(new Person("lisi",97));
oos.close();
}
}
class Person implements Serializable
{
//给类设置ID,
public static final long serialVersionUID = 42L;
String name;
int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public String toString()
{
return name+":"+age;
}
}
管道流:
管道流:输入输出可以直接连接,结合线程使用.
|--管道输入流:PipedInputStream
|--管道输出流:PipedOutpuStream
import java.io.*;
class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStream in)
{
this.in=in;
}
public void run()
{
try
{
byte[] bys = newbyte[1024];
System.out.println("读取前..没有数据..进入阻塞状态");
int len = in.read(bys);
System.out.println("读取到数据..阻塞状态结束");
String s = newString(bys,0,len);
System.out.println(s);
in.close();
}
catch (IOException e)
{
throw newRuntimeException("管道读取流失败");
}
}
}
class Write implements Runnable
{
private PipedOutputStream out;
Write(PipedOutputStream out)
{
this.out = out;
}
public void run()
{
try
{
System.out.println("开始写入数据,等待6秒");
Thread.sleep(6000);
out.write("PipedOutputStream is coming".getBytes());
out.close();
}
catch (Exception e)
{
throw newRuntimeException("管道输出流失败");
}
}
}
class PipedStreamDemo
{
public static void main(String[] args) throws IOException
{
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);
new Thread(new Read(in)).start();
new Thread(new Write(out)).start();
}
}
随机读写RandomAccessFile
该类不算是IO体系中的子类.
而是直接继承自Object.
但是它是IO包的成员,因为它具备读和写功能.
内部封装了一个byte数组,而且通过指针对数组的元素进行操作.
可以通过getFilePointer获取指针位置.
同时可以通过seek改变指针的位置
其实完成读写的原理就是内部封装了字节输入流和输出流.
通过构造函数可以看出,该类只能操作文件.
而且操作的文件还需要指定权限.
如果模式为只读 r,则不会创建文件,回去读取一个已存在的文件,如果该文件不存在,会出现异常
如果模式为 rw,操作的文件不存在,会自动创建,如果存在则不会覆盖
class RandomAccessFileDemo
{
public static void main(String[] args) throws IOException
{
//writeFile();
//readFile();
writeFile_2();
}
public static void readFile() throws IOException
{
RandomAccessFile raf = newRandomAccessFile("ran.txt","r");
//用seek()方法把指针调到8位置上
//raf.seek(8);
//跳过指定的字节数,skipBytes()只能向前,不能后退
raf.skipBytes(8);
byte[] bys = new byte[4];
raf.read(bys);
String name = new String(bys);
//方法readInt()取一个32位的整数
int age = raf.readInt();
System.out.println("name="+name);
System.out.println("age="+age);
}
public static void writeFile_2()throws IOException
{
RandomAccessFile raf = newRandomAccessFile("ran.txt","rw");
raf.seek(16);//利用seek方法,可以实现指定位置数据的添加和修改
raf.write("周七".getBytes());
raf.writeInt(103);
}
public static void writeFile() throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.write("李四".getBytes());
raf.writeInt(97);
raf.write("王五".getBytes());
raf.writeInt(99);
raf.close();
}
}