------- android培训、java培训、期待与您交流! ----------
File概述
用来将文件或文件夹封装成对象。
方便文件与文件夹的属性信息进行操作。
File对象可以作为参数传递给流的构造函数(流只能操作数据)。
File类的常见方法:
1、 创建。
booleancreateNewFile(); 在指定位置创建文件,如果该文件已经存在,则不创建,返回false,和输出流不一样,输出流对象一建立文件,而且文件已经存在,则会覆盖。
public staticvoid method_1() throws IOException
{
Filef=new File(“file.txt”);
f.deleteOnExit();//文件退出时删除
sop(“create:”+f.createNewFile());
sop(“delete”+f.delete());//删除
//创建文件夹
Filedir=new File(“abc”);
sop(“mkdir”+dir.mkdir());//只能创建一级目录
}
boolean mkdir():创建文件夹
booleanmkdirs():创建多级文件夹
2、 删除
booleandelete();删除失败返回false
voiddeleteOnExit();在程序退出时删除指定文件
3、 判断
File f=new File(“file.txt”);
sop(“execute:”+f.canExecute());测试应用程序是否可以执行此抽象路径名表示的文件
Boolean exists:文件是否存在
f .exists();判断文件对象是否是文件或者目录时,必须要先判断该文件对象封装的内容是存在的,通过exists判断
isFile();
isDirectory();
isHidden();判断是否隐藏
sop(f.isAbsolute());绝对路径是true
4、 获取信息
getName();获取名称
getPaht()获取路径
getParent();获取父目录,该方法返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是返回结果
getAbsolutePath();获取绝对路径
longlastModified();最后一次修改的时间
long length();文件大小
File f1=newFile(“c:\\Test.java”);
File f2=newFile(“d:\\hahah.java”);
f1.renameTo(f2);重命名,且换目录相当于剪切
import java.io.*;
class FileDemo
{
publicstatic void main(String[] args)
{
}
//创建File对象
public staticvoid main(Stirng[] args)
{
//将a.txt封装成file对象,可以将已有的和未出现的文件或者文件夹封装成对象
File f1=new File(“c:\\abc\\a.txt”);
File f2=new File(“c:\\abc”,”b.txt”);//左边是父目录,右边是文件名
File d=new File(“c:\\abc”);
File f3=new File(d,”c.txt”);
sop(f1);
sop(f2);
sop(f3);//打印结果一样
File f4=new File(“c:”+File.separator+”abc”+File.separato+”a.txt”);//separator是跨平台分割符
}
public staticvoid sop(Object obj)
{
System.out.println(obj);
}
}
//列出机器中的有效盘符
public static void listRootsDemo()
{
File[]files=File.listRoots();
for(Filef:files)
{
System.out.println(f);
}
}
//list方法
public static void listDemo()
{
Filef=new File(“c:\\”);
String[]names=f.list();//打印c盘下的所有文件和文件夹的名称,包含隐藏文件。调用list方法的file对象必须是封装了一个目录,而且该目录必须存在
for(Stringname:names)
{
System.out.println(name);
}
}
//list(接口类型)传一个匿名内部类
public static void main(String[] args)
{
Filedir=new File(“d:\\java1223\\day18”);
String[]arr=dir.list(new FilenameFilter()
{
public boolean accept(File dir,Stringname)
{
returnname.endsWith(“.bmp”);//过滤bmp文件
}
});
System.out.println(“len”:+arr.length);
for(Stringname:arr)
{
System.out.println(name);
}
}
需求:列出指定目录下的文件或者文件夹,包含子目录中的内容,也就是列出指定目录下的所有内容。
因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。在列出过程中出现的还是目录的话,还可以再次调用本功能。也就是函数自身调用自身。
这种表现形式,或者编程手法,称为递归。
递归要注意:
1、 限定条件;
2、 注意递归的次数,尽量避免内存溢出。
import java.io.*;
class FileDemo3
{
publicstatic void main(String[] args)
{
File dir=new File(“d:\\testdir”);
showDir(dir,0);
}
public staticString getLevel(int level)
{
StringBuilder sb=new StringBuilder();
sb.append(“|--”);
for(int x=0;x
需求:删除一个带内容的目录
删除原理:
在window中,删除目录是从里面往外删除的。需要用到递归。
import java.io.*;
classs RemoveDir
{
publicstatic void main(Strring[] args)
{
File dir=new File(“d:\\testdir”);
removeDir(dir);
}
public staticvoid removeDir(File dir)
{
File[] files=dir.listFiles();
for(int x=0;x
Properties是hashtable的子类。
也就是它具备map集合的特点。而且它里面存储的键值对都是字符串。是集合中和IO技术相结合的集合容器。
该对象的特点:可以用于键值对形式的配置文件。
那么在加载数据时,需要数据有固定格式:键=值。
import java.io.*;
import java.util.*;
class PropertiesDemo
{
public staticvoid main(String[] args)
{
setAndGet();
loadDemo();
}
//演示,如何将流中的数据存储到集合中。
//想要将info.txt中键值数据存到集合中进行操作
public staticvoid loadDemo()
{
Properties prop=new Properties();
FileInputStream fils=new FileInputStream(“info.txt”);
//将流中的数据加载进集合
prop.load(fis);
prop.setProperty(“wangwu”,”39”);//改变内存的结果
FileOutputStream fos=new FileOutputStream(“info.txt”);
prop.store(fos,”haha”);//haha是注释信息
//System.out.println(prop);
prop.list(System.out);
fos.close();
fis.close();
}
/*
1、用一个流和info.txt文件关联
2、读取一行数据,将改行数据用“=”进行切割
3、等号左边作为键,右边作为值。存入到Properties集合中即可
*/
public staticvoid method_1()
{
BufferedReader bufr=new BufferedReader(new FileReader(“info.txt”));
String line=null;
Properties prop=new Properties();
while((line=bufr.readLine())!=null)
{
String[] arr=line.split(“=”);
System.out.println(arr[0]+”...”+arr[1]);
prop.setProperty(arr[0],arr[1]);
}
bufr.close();
}
//设置和获取元素
public staticvoid setAndGet()
{
Properties prop=new Properties();
prop.setProperty(“zhangsan”,”30”);
prot.setProperty(“lisi”,”39”);
String value=prop.getProperty(“lisi”);
System.out.println(value);
//修改lisi的值
prop.setProperty(“lisi”,89+” ”);
//遍历集合中的所有数据
Set names=prop.stringPropertyNames();
for(String s : names)
{
System.out.println(s+”:”+prop.getProperty(s));
}
}
}
打印流
该流提供了打印方法,可以将各种数据类型的数据和都原样打印
1)字节打印流:
printStream
构造函数可以接收的参数类型:
1、file对象。File
2、字符串路径。String
3、字节输出流。OutputStream
2)字符打印流:
PrintWriter
构造函数可以接收的参数类型:
1、file对象。File
2、字符串路径。String
3、字节输出流。OutputStream
4、字符输出流,Writer
import java.io.*;
calss PrintStreamDemo
{
public staticvoid main(String[] args)
{
BufferedReader bufr=new BufferedReader(newInputStreamReader(System.in));
PrintWriter out=new PrintWriter(new FileWriter(“a.txt”));//将文件封装到流里面不用自动刷新
String line=null;
while((line=bufr.readLine())!null)
{
if(“over”.equal(line))
break;
out.println(line.toUpperCase());
//out.flush();
}
out.close();
out.close();
}
}
合并流
import java.io.*;
import java.util.*;
class SequenceDemo
{
public staticvoid main(Strring[] args)
{
Vector v=new Vector();
v.add(new FileInputStream(“c:\\1.txt”));
v.add(new FileInputStream(“c:\\2.txt”));
v.add(new FileInputStream(“c:\\3.txt”));
Enumeration en=v.elements();
SequenceInputStream sis=new SequenceInputStream(en);//将多个读取流合并成一个读取流
FileOutputStream fos=new FileOutputStream(“c:\\4.txt”);
type[] buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}
切割文件
一个读取流三个输出流
import java.util.*;
class SplitFile
{
public staticvoid main(String[] args) throw IOException
{
splitFile();
merge();
}
//合并
public staticvoid merge() throws IOException
{
ArrayList al=newArrayList();
for(int x=0;x<=3;x++)
{
al.add(new FileInputStream(“c:\\splitfiles\\”+x+”.part”));
}.
final Interator it=al.iterator();
Enumeration en=newEnumeration()
{
public boolean hasMoreElemnets()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
SequenceInputStream sis=new SequenceInputStream(en);//源有了
FileOutStream fos=new FileOutputStream(“c:\\splitfiles\\0.bmp”);
byte[] buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
//切割
public staticvoid splitFile() throw IOException
{
FillInputStream fis=new FileInputStream(“c:\\1.bmp”);
FileOutputStream fos=null;
byte[] buf=new byte[1024*1024];
int len=0;
while((len=fis.read(buf))!=-1)
{
fos=new FileOutputStream(“c:\\splitfiles\\”+(count++)+”.part”);
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
}
对象的序列化
ObjectOutputStream ObjectInputStream 成对出现
import java.io.*;
class ObjectStreamDemo
{
public staticvoid main(String [] ages) throws Exception
{
//writeObj();//对象就不在堆内存中的,对象存到obj.txt文件里面了
readObj();
}
public staticvoid readObj() throws Exception
{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(“obj.txt”));
Person p=(Person)ois.readObject();
System.out.println(p);
ois.close();
}
public staticvoid writeObj() throws IOException
{
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(“obj.txt”);//传字节流,将对像写入到文件里面去,传操纵文件的流比较合适,在定义目的。把数据写到文件里面去,数据不是纯文本数据,是字节的。能直接操纵对象的类是Object。。
//一般文件名不存成txt。存成.object
oos.writeObject(new Persong(“lisi”,39,”kr”));//这个对象存在硬盘上了
oos.close();
}
}
类通过实现java.io.Serializable接口以启用其序列化功能
import java.io.*;
//没有方法的接口就是标记接口
class Person implements Serializable
{
public staticfinal long serialVersionUID=42l;//自定义UID。不定义就是根据成员自动生成
String name;
transient intage;//非静态的也不想被序列化就加transient
static Stringcountry=”cn”;//静态不能被序列化。静态在方法区,只能将堆里面的序列化
Persong(Stringname,int age,String country)
{
this.name=name;
this.age=age;
this.country=country;
}
public StringtoString()
{
return name+”:”+age+”:”+name;
}
}
管道流
PipedInputStream 和PipedOutputStream输入输出可以直接进行连接,通过结合线程使用。
import java.io.*;
class Read implements Runnable
{
privatePipedInputStream in;
Read(PipedInputStream in)
{
this.in=in;
}
public voidrun()
{
//覆盖了方法,只能try,不能抛出
try
{
byte[] buf=new byte[1024];
int len=in.read(buf);//读取前没有数据就阻塞,读到数据,阻塞结束
String s=new String(buf,0,len);
System.out.println(s);
in.close();
}
catch(IOException e)
{
throw new RuntimeException(“管道读取流失败”);
}
}
}
class Write implements Runnable
{
privatePipedOutputStream out;
Write(PipedOutputStreamout)
{
this.out=out;
}
public voidrun()
{
try
{
out.write(“piped lai le”.getBytes());
out.close();
}
catch(IOException e)
{
throw new RuntimeException(“管道输出流失败”);
}
}
}
class PipedStreamDemo
{
public staticvoid main(String[] args) throws IOException
{
PipedInputStream in=new PipedInputStream();
PipedOutputStream out=new PipedIOutputStream();
in.connect(out);
Read r=new Read();
Write w=new Write();
new Thread(r).start();
new Thread(w).start();
}
}
RandomAccessFile
随机访问文件,自身具备读写的方法。
通过skipBytes(int x),seek(int x)来达到随机访问
该类不算是IO体系中的子类。而是直接继承自Object。但是它是IO包中成员,因为它具备读和写功能。
内部封装了一个数组,而且通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置。
同时可以通过seek改变指针的位置
其实完成读写的原理就是内部封装了字节输入流和输出流。
通过构造函数可以看出该类只能操作文件。而且操作文件还有模式:只读r,读写rw等。
如果模式为只读r,不会创建文件,会去读取一个已存在的文件,如果该文件不存在则会报异常;如果模式为rw,该对象的构造函数要操作的文件不存在,会自动创建。如果存在则不会覆盖,直接在文件中写数据
import java.io.*;
class RandomAccessFileDemo
{
public staticvoid main(String[] args) throws IOException
{
writeFile();
writeFile_2();
}
public staticvoid readFile() throws IOException
{
RandomAccessFile raf=new RandomAccessFile(“ran.txt”,”r”);//只读
//raf.write(“haha”.getBytes());只读权限,屏蔽了写操作
//调整对象的指针
//raf.seek(8*1);//取王五的值
//跳过指定的字节数
raf.skipBytes(8);//但是跳过不能往回跳
byte[] buf=new byte[4];
raf.read(buf);
String name=new String(buf);
int age=raf.readInt();//一次读一个32位整数,四个字节,读完自动转换
System.out.println(“name”+name+”age”+age);
raf.close();
}
public staticvoid writeFile_2() throws IOException//随机可以往里读写,还能对数据进行修改
{
RandomAccessFile raf=new RandomAccessFile(“ran.txt”,”rw”);
raf.seek(8*3);
raf.write(“周期”.getBytes());
raf.writeInt(93);
raf.close();
}
public staticvoid writeFile() throws IOException
{
RandomAccessFile raf=new RandomAccessFile(“ran.txt”,”rw”);
raf.write(“李四”.getBytes());
//raf.write(97);//取最低八位,容易丢数据
raf.writeInt(97);// 取四个字节
raf.write(“王五”.getBytes());
raf.writeInt(93);// 取四个字节
raf.close();
}
}
DateInputStream与DataOutputStream
可以用于操作基本数据类型的数据的流对象
import java.io.*;
class DataStreamDemo
{
public staticvoid main(String[] args) throws IOException
{
//writeData();
//readDate();
writeUTFDemo();//gbk 4字节,下面utf 6字节,这个utf8字节
OutputStreamWriter osw=new OutputStreamWriter(new FileOutStream(“utf.txt”,”utf-8”));
osw.write(“你好”);
osw,close();
readUTFDemo();
}
public staticvoid readUTFDemo() throws IOException
{
DataInputStream dis=new DataInputStream(new FileInputStream(“utfdate.txt”));
String s=dis.readUTF();
System.out.println(s);//读出你好
dis.close();
}
public staticvoid writeUTFDemo() throws IOException
{
DataOutputStream dos=new DataOutputStream(new FileOutputStream(“utfdate.txt”));
dos.writeUTF(“你好”);//用这个写的只能用readUTF()读
dos.close();
}
public staticvoid readData() throws IOException
{
DataInputStream dis=new DataInputStream(new FileInputStream(“data.txt”));
int num=dis.readInt();
boolean b=dis.readBoolean();
double d=dis.readDouble();
System.out.println(“num=”+num);
System.out.println(“b=”+b);
System.out.println(“d=”+d);
dis.close();
}
public staticvoid writeData() throws IOException
{
DataOutputStream dos=new DataOutputStream(new FileOutputStream(“data.txt”));
dos.writeInt(234);
dos.writeBoolean(true);
dos.writeDouble(9887.543);
dos.close();
}
}
操作字节数组
ByteArrayInputStream(负责源)与ByteArrayOutputStream
ByteArrayInputStream:在构造的时候需要接收数据源,而且在数据源是一个字节数组。
ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字符数组,这就是数据目的地。
因为这两个流对象都操作的数组,并没有使用系统资源,所以不用close关闭。
源设备:键盘System.in,硬盘FileStream,内存ArrayStream
目的设备:控制台System.out,硬盘FileStream,内存ArrayStream
用流的读写思想来操作数组
import java.io.*;
class ByteArrayStream
{
public staticvoid main(String[] args)
{
//数据源
ByteArrayInputStream bis =new ByteArrayInputStream(“ABCDED”.getBytes());
//数据目的
ByteArrayOutputStream bos=new ByteArrayOutputStream();
System.out.println(bos.size());//0
int by=0;
while((by=bis.read())!=-1)
{
bos.write(by);
}
System.out.println(bos.size());//7
System.out.println(bos.toString());//ABCDED
}
}
操作字符数组
CharArrayReader与CharArrayWrite
操作字符串
StringReader与StringWriter
字符编码
字符流的出现为了方便操作字符。
更重要的是加入了编码转换。
通过子类转换流来完成:
InputStreamReader OutputStreamWriter
在两个对象进行构造的时候可以加入字符集。
编码表的由来:
计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。就将各个国家的文字用数字来表示,并一一对应,形成一张表。这就是编码表。
ASCII:美国标准信息交换码。用一个字节的7位可以表示
ISO8859-1:拉丁码表。欧洲码表。用一个字节的8位表示
GB2312:中国的中文编码表。从中国开始用两个字节了
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
Unicode:国际标准码,融合了多种文字。所有文字都用两个字节表示,java语言用的就是unicode
UTF-8:最多用三个字节来表示一个字符