----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
File概述
File类:用来将文件或者文件夹封装成对象。方便对文件与文件夹的属性信息进行操作。File对象可以作为参数传递给流的构造函数。
示例:
import java.io.*;
class FileDemo
{
public static void main(String[] args)
{
consMethod();
}
public static void consMethod()
{
//创建File对象,将a.txt封装成File对象。可以将已有的和不存在的文件或文件夹封装成File对象。
File f1=new File("a.txt");
File f2=new File("d:\\abc","b.txt");
File d=new File("d:\\abc");
File f3=new File(d,"c.txt");
File f4=new File("d:"+File.separator+"abc"+File.separator+"zzz"+File.separator+"z.txt");
sop("f1:"+f1);
sop("f2:"+f2);
sop("f3:"+f3);
sop("f4:"+f4);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
File类中常见方法:
1.创建:
boolean createNewFile():在指定位置创建文件。如果该文件已经存在,则不创建,返回false。
boolean mkdir():创建一级文件夹。
boolean mkdirs():创建多级文件夹。
2.删除:
boolean delete():删除失败返回false。如果文件正在被使用,则删除失败返回false。
void deleteOnExit():在程序退出时删除指定文件。
示例1:
import java.io.*;
class FileDemo1
{
public static void main(String[] args)throws IOException
{
File f=new File("file.txt");
sop("create:"+f.createNewFile());
//sop("delete:"+f.delete());
f.deleteOnExit();
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
3.判断:
boolean exists():文件是否存在。
isFile():是否是文件。
isDirectory():是否是文件夹。
isHidden():是否是隐藏文件。
isAbsolute():是否是绝对路径。
canExecute():是否是可执行文件。
示例2:
import java.io.*;
class FileDemo2
{
public static void main(String[] args)throws IOException
{
method_2();
method_3();
}
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void method_2()
{
File f=new File("file.txt");
//File f=new File("FileDemo.java");
sop("execute:"+f.canExecute());
sop("exists:"+f.exists());
//创建文件夹。
File dir=new File("wanglin");
sop("mkdir:"+dir.mkdir());
File dir1=new File("wanglin\\tangwei\\abc\\fdree\\java.txt");
sop("mkdirs:"+dir1.mkdirs());
}
public static void method_3()throws IOException
{
File f1=new File("file.txt");
//在判断文件对象是否是文件或者文件夹目录时,必须要先判断该文件对象封装的内容是否存在。通过exists方法判断。
f1.mkdir();
sop("dir:"+f1.isDirectory());
sop("file:"+f1.isFile());
sop(f1.isAbsolute());
File f2=new File("d:\\java01\\day20\\file.txt");
sop(f2.isAbsolute());
}
}
4.获取:
getName();
getPath():只获取文件对象封装的路径目录。
getParent():获取父目录。
getAbsolutePath():获取绝对路径。
long lastModified():获取文件最后一次修改时间。
long length():获取文件大小。
示例3:
import java.io.*;
class FileDemo3
{
public static void main(String[] args)throws IOException
{
method_4();
method_5();
}
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void method_4()
{
File f=new File("file.txt");
sop("path:"+f.getPath());
sop("absolute:"+f.getAbsolutePath());
//sop("parent:"+f.getParent());
File f3=new File("wanglin\\file.txt");
sop("parent:"+f3.getParent());
}
public static void method_5()
{
File f1=new File("f:\\java01\\day20\\FileDemo.java");
File f2=new File("d:\\wanglin.txt");
sop("rename:"+f1.renameTo(f2));
}
}
5.列出文件列表:
list():列出指定目录下所有文件和文件夹名称,包括隐藏文件和文件夹。
示例:
import java.io.*;
class FileDemo4
{
public static void main(String[] args)
{
listRootsDemo();
listDemo();
}
public static void listRootsDemo()
{
File[] files=File.listRoots();
for(File f:files)
{
System.out.println(f);
}
}
public static void listDemo()
{
File f1=new File("e:\\");
String[] names=f1.list();
for(String name:names)
{
System.out.println(name);
}
}
}
FilenameFilter接口:获取指定目录下的指定名称的文件名。
示例:
import java.io.*;
class FileDemo5
{
public static void main(String[] args)
{
File dir=new File("d:\\");
File[] files=dir.listFiles();
for(File f:files)
{
System.out.println(f.getName()+"::::"+f.length());
}
listDemo_2();
}
public static void listDemo_2()
{
File dir1=new File("f:\\java01\\day19");
String[] arr=dir1.list(new FilenameFilter()
{
public boolean accept(File dir,String name)
{
return name.endsWith(".txt");//获取指定目录下的.txt文件。
}
});
System.out.println("len:"+arr.length);
for(String name:arr)
{
System.out.println(name);
}
}
}
怎样列出指定目录下的所有内容,包括子内容?
因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。在列出过程中出现的还有目录的话,还可以再次调用本功能。也就是函数自身调用自身,这种表现形式或者编程手法,称为递归。
递归要注意:
1.限定条件。
2.要注意递归的次数。次数太多,内存会溢出。
递归示例:
import java.io.*;
class FileDemo6
{
public static void main(String[] args)
{
File dir=new File("f:\\java01");
showDir(dir);
toBin(74);
int n=getSum(142);
System.out.println("n="+n);
}
public static int getSum(int n)
{
if(n==1)
return 1;
return n+getSum(n-1);
}
public static void toBin(int num)
{
if(num>0)
{
toBin(num/2);
System.out.println(num%2);
}
}
public static void showDir(File dir)
{
System.out.println(dir);
File[] files=dir.listFiles();
for(File file:files)
{
if(file.isDirectory())
showDir(file);
else
System.out.println(file);
}
}
}
删除带内容的目录:
删除原理:先删除完里面的内容,再删外面的内容,最后删除指定的文件夹。这时就需要用到递归。
删除文件夹示例:
import java.io.*;
class FileDemo8
{
public static void main(String[] args)
{
File dir=new File("f:\\myclass");
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].toString()+":-file-:"+files[x].delete());
}
System.out.println(dir+"::dir::"+dir.delete());
}
}
Properties简述
Properties是Hashtable的子类。也就是说它具备Map集合的特点。而且它里面存储的键值对都是字符串。它是集合中和IO技术相结合的集合容器。
Properties对象的特点:可以用于键值对形式的配置文件。那么在加载数据时,需要数据有固定格式:键=值
Properties存取元素:
示例:
import java.io.*;
import java.util.*;
class PropertiesDemo
{
public static void main(String[] args)
{
setAndGet();
}
public static void setAndGet()
{
Properties prop=new Properties();
prop.setProperty("wanglin01","23");
prop.setProperty("wanglin02","25");
prop.setProperty("wanglin03","27");
System.out.println(prop);
String value=prop.getProperty("wanglin02");
System.out.println(value);
prop.setProperty("wanglin03",20+"");
Set<String> names=prop.stringPropertyNames();
for(String s:names)
{
System.out.println(s+"::"+prop.getProperty(s));
}
}
}
Properties存取配置文件:
示例:
import java.io.*;
import java.util.*;
class PropertiesDemo2
{
public static void main(String[] args)throws IOException
{
//method_1();
loadDemo();
}
public static void loadDemo()throws IOException
{
Properties prop=new Properties();
FileInputStream fis=new FileInputStream("info.txt");
prop.load(fis);
System.out.println(prop);
prop.setProperty("wanglin03",30+"");
FileOutputStream fos=new FileOutputStream("info.txt");
prop.store(fos,"tangwei");
prop.list(System.out);
fos.close();
fis.close();
}
public static void method_1()throws IOException
{
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();
System.out.println(prop);
}
}
IO包中的其他类:
1.打印流:PrintWriter与PrintStream 可以直接操作输入流和文件。该流提供了打印方法,可以将各种数据类型的数据都原样打印。
字节打印流:PrintStream
构造函数可以接收的参数类型:File对象 file;字符串路径 String;字节输出流 OutputStream
字符打印流:PrintWriter
构造函数可以接收的参数类型:File对象 file;字符串路径 String;字节输出流 OutputStream;字符输出流 Writer
打印流示例:
import java.io.*;
class PrintStreamDemo
{
public static void main(String[] args)throws IOException
{
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
//PrintWriter out=new PrintWriter(new FileWriter("a.txt"),true);
//PrintWriter out=new PrintWriter(System.out);
PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("a.txt")),true);
String line=null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toUpperCase());
out.flush();
}
out.close();
bufr.close();
}
}
2.序列流: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("d:\\1.txt"));
v.add(new FileInputStream("d:\\2.txt"));
v.add(new FileInputStream("d:\\3.txt"));
Enumeration<FileInputStream> en=v.elements();
SequenceInputStream sis=new SequenceInputStream(en);
FileOutputStream fos=new FileOutputStream("d:\\4.txt");
byte[] buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,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>();
for(int x=1;x<=4;x++)
{
al.add(new FileInputStream("f:\\splitfiles\\"+x+".part"));
}
final Iterator<FileInputStream> it=al.iterator();
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("f:\\splitfiles\\0.mp3");
byte[] buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
public static void splitFile()throws IOException
{
FileInputStream fis=new FileInputStream("f:\\1.mp3");
FileOutputStream fos=null;
byte[] buf=new byte[1024*1024];
int len=0;
int count=1;
while((len=fis.read(buf))!=-1)
{
fos=new FileOutputStream("f:\\splitfiles\\"+(count++)+".part");
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
}
3.操作对象:ObjectInputStream与ObjectOutputStream 被操作的对象需要实现Serializable接口(标记接口)。
对象的序列化:将堆内存中的对象数据保存到硬盘上的一个文件中,从而将对象永久保存,这就叫做对象序列化,也叫对象持久化。
对象序列化示例:
Person对象:
import java.io.*;
class Person implements Serializable
{
public static final long serialVersionUID=48L;
private String name;
transient int age;
static String country="cn";
Person(String name,int age,String country)
{
this.name=name;
this.age=age;
this.country=country;
}
public String toString()
{
return name+"::"+age+"::"+country;
}
}
将Person对象序列化:
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(new FileInputStream("obj.txt"));
Person p=(Person)ois.readObject();
System.out.println(p);
ois.close();
}
public static void writeObj()throws IOException
{
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("obj.txt"));
oos.writeObject(new Person("wanglin01",22,"jp"));
oos.close();
}
}
4.RandomAccessFile:随机访问文件,自身具备读写的方法。该类不算是IO体系中的子类,而是直接继承自Object类。但是它是IO包中成员,因为它具备读写功能。该类内部封装了一个字节数组,可以通过指针对数组的元素进行操作。可以通过getFilePointer获取指针的位置,再通过seek方法或skipBytes方法改变指针的位置。从而达到随机访问。其实该类完成读写的原理就是内部封装了字节输入流和输出流。通过构造函数可以看出,该类只能操作文件。而且操作的文件有两种模式:r(只读),rw(读写)。
示例:
import java.io.*;
class RandomAccessFileDemo
{
public static void main(String[] args)throws IOException
{
//writeFile();
writeFile_2();
readFile();
RandomAccessFile raf=new RandomAccessFile("ran1.txt","rw");
//RandomAccessFile raf=new RandomAccessFile("ran1.txt","r");
raf.write("tang".getBytes());
}
public static void readFile()throws IOException
{
RandomAccessFile raf=new RandomAccessFile("ran.txt","r");
raf.seek(8*1);//将指针调整到脚标8位置。
//raf.skipBytes(8);//跳过8个字节。
byte[] buf=new byte[4];
raf.read(buf);
String name=new String(buf);
int age=raf.readInt();
System.out.println("name="+name);
System.out.println("age="+age);
raf.close();
}
public static void writeFile_2()throws IOException
{
RandomAccessFile raf=new RandomAccessFile("ran.txt","rw");
raf.seek(8*0);
//raf.seek(8*3);
raf.write("丽丽".getBytes());
raf.writeInt(201);
raf.close();
}
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();
}
}
5.管道流:PipedInputStream和PipedOutputStream 输入输出可以直接进行连接,通过结合线程使用。涉及到多线程技术的IO流对象。
示例:
import java.io.*;
class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStream in)
{
this.in=in;
}
public void run()
{
try
{
byte[] buf=new byte[1024];
System.out.println("读取前。。。没有数据阻塞");
int len=in.read(buf);
System.out.println("读到数据。。。阻塞结束");
String s=new String(buf,0,len);
System.out.println(s);
in.close();
}
catch (IOException e)
{
throw new RuntimeException("管道读取流失败");
}
}
}
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("piped lai la".getBytes());
out.close();
}
catch (Exception e)
{
throw new RuntimeException("管道输出流失败");
}
}
}
class PipedStreamDemo
{
public static void main(String[] args)throws IOException
{
PipedInputStream in=new PipedInputStream();
PipedOutputStream out=new PipedOutputStream();
in.connect(out);
Read r=new Read(in);
Write w=new Write(out);
new Thread(r).start();
new Thread(w).start();
}
}
6.操作基本数据类型的数据的流对象:DataInputStream和DataOutputStream
示例:
import java.io.*;
class DataStreamDemo
{
public static void main(String[] args)throws IOException
{
writeData();
readData();
}
public static void writeData()throws IOException
{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(346);
dos.writeBoolean(false);
dos.writeDouble(45893.9823);
dos.close();
}
public static void readData()throws IOException
{
DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));
int num=dis.readInt();
boolean b=dis.readBoolean();
double d=dis.readDouble();
sop("num="+num);
sop("b="+b);
sop("d="+d);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
7.操作字节数组的流对象:
ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream:在构造的时候,不用定义数据目的。因为该对象中已经封装了可变长度的字节数组,这就是数据目的地。
示例:
import java.io.*;
class ByteArrayStream
{
public static void main(String[] args)
{
ByteArrayInputStream bis=new ByteArrayInputStream("wanglin01".getBytes());
ByteArrayOutputStream bos=new ByteArrayOutputStream();
int by=0;
while((by=bis.read())!=-1)
{
bos.write(by);
}
System.out.println(bos.size());
System.out.println(bos.toString());
}
}
转换流的字符编码:
字符流的出现为了方便操作字符。更重要的是加入了编码转换。通过子类转换流来完成:InputStreamReader和OutputStreamWriter。这两个流对象进行构造的时候可以加入字符集。
编码表的由来:
计算机只能识别二进制数据。为了方便应用计算机,让它可以识别各个国家的文字,就将各个国家的文字用数字来表示,并一一对应,形成一张表。这就是编码表。
常见的编码表:
ASCII:美国标准信息交换码。用一个字节的7位可以表示。
ISO8859-1:欧洲码表。用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:GB2312的升级版。融合了更多的中文文字符号。
Unicode:国际标准码,融合了多种文字。所有文字都用两个字节表示。Java语言使用的就是Unicode。
UTF-8:国际标准码改进版,最多用三个字节来表示一个字符。
转化流的编码应用:
1.可以将字符以指定编码格式存储。
2.可以对文本数据以指定编码格式来读取。
3.指定编码表的动作由构造函数完成。
应用示例:
import java.io.*;
class EncodeStream
{
public static void main(String[] args)throws IOException
{
//writeText();
readText();
}
public static void readText()throws IOException
{
//InputStreamReader isr=new InputStreamReader(new FileInputStream("gbk.txt"),"GBK");
InputStreamReader isr=new InputStreamReader(new FileInputStream("utf.txt"),"GBK");
char[] buf=new char[10];
int len=isr.read(buf);
String str=new String(buf,0,len);
System.out.println(str);
isr.close();
}
public static void writeText()throws IOException
{
//OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("gbk.txt"),"GBK");
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");
osw.write("你好");
osw.close();
}
}
字符编码:字符串变成字节数组。通过getBytes(指定的编码表);
字符解码:字节数组变成字符串。通过new String(byte[],指定的编码表);
编码与解码示例:
import java.util.*;
class EncodeDemo
{
public static void main(String[] args)throws Exception
{
String s="你好";
byte[] b1=s.getBytes("gbk");
//byte[] b1=s.getBytes("utf-8");
System.out.println(Arrays.toString(b1));
//String s1=new String(b1,"GBK");
//String s1=new String(b1,"UTF-8");
String s1=new String(b1,"iso8859-1");
System.out.println("s1="+s1);
byte[] b2=s1.getBytes("ISO8859-1");
System.out.println(Arrays.toString(b2));
String s2=new String(b2,"gbk");
//String s2=new String(b2,"utf-8");
System.out.println("s2="+s2);
}
}
字符编码中的特殊现象:在记事本程序中写入“联通”两个字,保存后再打开记事本,这两个字变成乱码。原因是:“联通”这两个字的GBK编码的二进制形式正好符合UTF-8的二进制编码规则,记事本程序自动用UTF-8编码表进行解码,所以变成乱码。
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------