黑马程序员 IO之File等类

来源:互联网 发布:淘宝卖家等级怎么看分 编辑:程序博客网 时间:2024/06/05 03:32

-----------android培训java培训、java学习型技术博客、期待与您交流! -----------


File类:

用来对文件或者文件夹封装对象,对其属性进行操作。
File对象可以作为参数传递给流的构造函数。
File f = new File("a.txt")可以将已有或者没有的文件或者文件夹封装成对象。
File f = new File("c:\\abc","b.txt")括号内,左边是文件目录,右边是文件。

对于目录分隔符,可以同File.separator()方法获取一个跨平台的目录分隔符。

File类常见方法:
1.创建
创建文件:
boolean createNewFile() 当文件不存在,创建成功返回true,文件存在,创建不成功,返回false。
static File createTempFile(String prefix, String suffix) 在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。 
创建文件夹:
boolean mkdir() 创建此抽象路径名指定的目录。只能创建一级目录
boolean mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。 创建多级目录。
2,删除
boolean delete(),删除某个文件。
void deleteOnExit() 在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。 
3,判断
boolean canExecute() 测试应用程序是否可以执行此抽象路径名表示的文件。 
boolean canRead() 测试应用程序是否可以读取此抽象路径名表示的文件。 
boolean canWrite() 测试应用程序是否可以修改此抽象路径名表示的文件。 
boolean exists() 测试此抽象路径名表示的文件或目录是否存在。 
boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录。 
boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件。 
在判断一个文件是目录还是文件时,必须先判断该文件对象封装的内容是否存在。
boolean isHidden() 测试此抽象路径名指定的文件是否是一个隐藏文件。 
boolean isAbsolute() 测试此抽象路径名是否为绝对路径名。 
4,获取信息
getName():获取文件名
getPath():获取文件相对路径。
getParent():该方法返回的是绝对路径中的父目录。相对路径的话返回的是null.如果相对路径中有上一层目录,该目录就是返回结果。
getAbsolutePath():返回文件的绝对路径
long lastModified():返回此路径名表述的文件最后一次被修改的时间。
long length():返回文件的大小
boolean renameTo(File dest) 重新命名此抽象路径名表示的文件。类似于剪切功能。 

static File[] listRoots()列出可用的文件系统根。
String[] list() 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。包含隐藏文件。 
String[] list(FilenameFilter filter) 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录 
FilenameFilter一个接口,里面只有一个public boolean accept()方法。可以用来对指定文件过滤
File[] listFiles()获取的是文件对象,这个可以对返回的文件进行操作,实际用的比较多。

列出指定目录下所有的内容:递归
import java.io.File;class FileDemo {public static void main(String[] args) {File dir = new File("C:\\Documents and Settings\\Administrator\\桌面\\zhuomian");showDir(dir);}public static void showDir(File dir){File[] f = dir.listFiles();for (int x=0;x<f.length ;x++ ){if (f[x].isDirectory()){System.out.println(f[x].getName());showDir(f[x]);}elseSystem.out.println(f[x]);}}}

因为目录中还有目录,只要使用同一个列出目录功能的函数完成就可以了。就需要函数调用自身。这个形式称为:递归。
递归需要注意:1,要有限定条件。2,递归次数不要过多,防止内存溢出。
***********************************************************************************************************
Properties对象:hashtable的子类。

该对象具备map集合的特点。里面存储的键值对都是字符串。该对象是集合中和IO技术相结合的集合容器。可以用于键值对形式的配置文件。

方法: 没有静态方法,需要建立对象调用。

Set<String> stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。 
String getProperty(String key)  用指定的键在此属性列表中搜索属性。 
Object setProperty(String key, String value)  调用 Hashtable 的方法 put。 

 void load(InputStream inStream) 
          从输入流中读取属性列表(键和元素对)。 
 void load(Reader reader) 
          按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 
 void list(PrintStream out) 
          将属性列表输出到指定的输出流。 
 void list(PrintWriter out) 
          将属性列表输出到指定的输出流。 
 void store(OutputStream out, String comments) 
          以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。 

 void store(Writer writer, String comments)  以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。 

eg:

import java.io.*;import java.util.*;class  PropertiesDemo{public static void main(String[] args){try{loadDemo();}catch (IOException e){throw new RuntimeException();}}//设置和获取元素public static void setAndGet(){Properties prop = new Properties();//设置元素prop.setProperty("zhangsan","30");prop.setProperty("lisi","20");//获取键位“lisi”的值String value = prop.getProperty("lisi");//重新设置"lisi"对应的值,返回的是旧值“20“的对象。prop.setProperty("lisi","89+");//将prop中元素的键返回到Set集合中Set<String> names = prop.stringPropertyNames();//遍历集合,打印prop中的键和值。 for(String s : names){System.out.println(s+":"+prop.getProperty(s));}}public static void loadDemo()throws IOException{Properties prop = new Properties();FileReader fis = new FileReader("info.txt");prop.load(fis);prop.setProperty("wangwu","39");FileWriter fw = new FileWriter("info.txt");prop.store(fw,"hah");//因为通过store方法写入,不会出现覆盖。//System.out.println(prop);prop.list(System.out);}//想要将info.txt中键值数据存到集合中进行操作。//用一个流和info.txt文件关联。public static void method_1() throws IOException{BufferedReader bur = new BufferedReader(new FileReader("info.txt"));String line = null;Properties prop = new Properties();while ((line=bur.readLine())!=null){String[] arr = line.split("=");//System.out.println(arr[0]+"........"+arr[1]);for (int x=0;x<arr.length ;x++ ){System.out.print(arr[x]+"   ");}prop.setProperty(arr[0],arr[1]);}bur.close();System.out.println(prop);}}


一个有趣的例子:
/*用于记录应用程序运行次数如果使用次数已到,那么给出注册提示。*/import java.io.*;import java.util.*;class  RunCount{public static void main(String[] args) throws IOException{Properties prop = new Properties();File file = new File("count.ini");if(!file.exists())file.createNewFile();FileInputStream fis = new FileInputStream(file);prop.load(fis);String value = prop.getProperty("time");int count = 0;if(value!=null){count = Integer.parseInt(value);if(count>=5){System.out.println("您好,次数已到。");return;}}count++;prop.setProperty("time",count+"");FileOutputStream fos = new FileOutputStream(file);prop.store(fos,"");fos.close();fis.close();}}

***********************************************************************************************************

打印流:PrintStream,PrintWriter

该流提供了打印方法,可以将各种数据类型的数据都原样打印。
凡是和文件相关的类都是比较重要的类。
PrintWriter构造函数可以接受的参数类型:
1,file对象,File
2,字符串路径:String
3,字节输出流:OutputStream
4,字符输出流:Writer
对输出流操作时,可以在构造函数里面确定是否需要自动刷新。

用println()方法,可以自动换行,还能配合构造函数自动刷新。

import java.io.*;class  PrintStreamDemo{public static void main(String[] args) throws IOException{BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//参数为true,表示可以用println方法自动刷新,PrintWriter out = new PrintWriter(System.out,true);String line = null;while ((line=bufr.readLine())!=null){if("over".equals(line))break;out.println(line.toUpperCase());//out.flush();}out.close();bufr.close();}}


***********************************************************************************************************
其它功能性流对象:

1,SequenceInputStream  合并流

顾名思义,将多个读取流合并,其中用到Enumeration.

import java.util.*;import java.io.*;class SequenceDemo {public static void main(String[] args) throws IOException{//枚举Enumeration在Vector集合中有Vector<FileInputStream> v = new Vector<FileInputStream>();v.add(new FileInputStream("c:\\1.txt"));v.add(new FileInputStream("c:\\2.txt"));v.add(new FileInputStream("c:\\3.txt"));//获取枚举Enumeration<FileInputStream> en = v.elements();//将枚举中的流对象用合并流合并。SequenceInputStream sis = new SequenceInputStream(en);FileOutputStream fos = new FileOutputStream("c:\\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();}}


操作对象的流:ObjectInputStream,ObjectOutputStream
该流可以操作基本数据类型,操作对象。这两个流需要成对使用
被操作的对象需要实现Serializable(标记接口)。该接口用作标记,没有方法。
被标记的对象拥有唯一性。
对象内的静态内容不在堆内存里面,所以无法序列化。
当想非静态成员不被序列化,可以在成员前加上关键字:transient
import java.io.*;class  ObjectStreamDemo{public static void main(String[] args) throws Exception{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 Exception{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Obj.txt"));oos.writeObject(new Person("zhangsan",30));oos.close();}}class Person implements Serializable{public static final long serialVersionUID = 43L;//手动设置该对象的UID,使对象被修改后能被读取写入。static String country//静态无法被序列化。private String name;transient int age;//被transient修饰,无法被序列化Person(String name,int age){this.name = name;this.age = age;}public String toString(){return name+"..."+age;}}

管道流:PipedInputStream和PipedOutputstream
输入输出可以直接进行连接,通过结合线程使用。
class Read implements Runable{private PipedInputStream in;Read(PipedInputStream in){this.in = in;}public void run(){try{byte[] buf = new byte[1024];int len = 0;while((len=in.read(buf))!=-1){String s = new String(buf,0,len);System.out.println(s);}in.close();}catch(IOException e){throw new RuntimeException("读取失败");}}}class Write implements Runable{private PipedOutputStream out;Write(PipedInputStream out){this.out = out;}public void run(){try{out.write("这是管道流".getBytes());out.close();}catch(IOException e){throw new RuntimeException("读取失败");}}}class PipedStreamDemo{public static void main(String[] args){PipedOutputStream out = new PipedOutputStream();PipedInputStream in = new PipedInputStream();in.connect(out);//输出流将数据写入到输入流。//PipedInputStream in = new PipedInputStream(out);Read r = new Read(in);Write w = mew Write(out);new Thread(r).start();new Thread(w).start();}}

RandomAccessFile:
随机访问文件,自身具备读写方法。该类不算是IO体系中的子类,直接继承自Object
,但是它是IO包中的成员,内部封装了一个大型byte数组,通过指针对数组的元素进行操作。可以通过getFilePointer获取指针位置。通过seek改变指针位置。对指定数据进行读取。
该类只能用指定模式操作文件。
RandomAccessFile(File file, String mode)       
RandomAccessFile(String name, String mode) 
mode的类型只有四种:r:只读,rw:读写,rws:读写操作,还要保证对文件的内容和元数据更改都被写入到设备。rwd:仅更新对内容的更改。
可以对基本数据类型进行读取写入。

如果模式为只读r,不会创建文件。会去读取一个已存在文件。如果该文件不存在。会报错。
如果模式为rw,该对象的构造函数要操作的文件不存在,会自动创建。如果存在不会覆盖。
class import java.io.*;class  RandomAccessFileDemo{public static void main(String[] args) throws IOException{writeFile();//readFile();}public static void readFile() throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","r");//调整对象中的指针。raf.seek(8);//跳过指定的字节数,只能往前跳,不能往回跳。raf.skipBytes(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()throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");raf.write("李四".getBytes());raf.writeInt(258);//write方法只写数据后八位。所以用特有的writeInt方法raf.write("王武".getBytes());raf.writeInt(25);raf.close();}public static void writeFile2()throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");//不覆盖文件raf.seek(8);raf.write("周期".getBytes());raf.writeInt(34);raf.close();}} 

用于操作基本数据类型的数据流对象:DataInputStream和DataOutputStream
在操作基本数据的时候,用这个类比较好。
特殊方法: void writeUTF(String str) 
          使用 modified UTF-8修改版编码以与机器无关的方式将一个字符串写入该文件。
 用这种方法写的话,只能用这种方法对应的读取方式读取。转换流都读不出来。
import java.io.*;class  DataStreamDemo{public static void main(String[] args) throws IOException{readData();}public  static void writeData()throws IOException{DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));dos.writeInt(234);dos.writeBoolean(true);dos.writeDouble(243434.343);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();System.out.println(num);System.out.println(b);System.out.println(d);dis.close();}}

对数组操作的流:
ByteArrayInputStream:
不涉及底层数据操作,不会抛出IO异常。不用进行close关闭
ByteArrayOutputStream:构造的时候不用定义数据目的。该对象中已经内部封装了可变长度的字节数组(源目的地)。
源和目的都是内存。目的还是一个长度可变数组。用流的思想操作数组。
 void writeTo(OutputStream out) 
将此 byte 数组输出流的全部内容写入到指定的输出流参数中,这与使用 out.write(buf, 0, count) 调用该输出流的 write 方法效果一样 
同理可得:StringArrayStream
 CharArrayStream
import java.io.*;class  ByteArrayStream{public static void main(String[] args) {ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFG".getBytes());ByteArrayOutputStream bos = new ByteArrayOutputStream();int by = 0;while ((by=bis.read())!=-1);{bos.write(by);}System.out.println(bos.size());}}
*********************************************************************************************************************

字符编码:

常见的标码表:
ASCII:美国标准信息交换表。用一个字节的7位可以表示
ISO8859-1:拉丁码表,欧洲码表。用一个字节的8为表示。
GB2312:中国的中文编码表(带字符7,8千个字)
GBK:中国的中文编码表升级,融合了更多的中文文字符号。中文码表两个字节的高位都是1。(扩容后有上万字符)
Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,java语言使用的就是unicode。
UTF-8:最多用三个字节来表示一个字符。

对于编码编错了,解码出来的就是乱码,没有编码时候的码表,基本上没办法。
对于编码编对了,解码解错了,可以用解错的码表重新编码回去,再用对的码表解码。
注意:
    如果用GBK编码。UTF-8解码,出现乱码。重新编回去以后,再解码还是会出现乱码。
    因为,两个码表都支持中文。当UTF-8码表对编码后的字节查表的时候,找不到符合规则的数据,
    于是就去对应码表以外的未知字符区域去查,返回字符。当重新编码的时候,编的码就不是原来的码了。

联通:当我们在记事本中写入“联通”两个字的时候,默认的GBK编码。编出的码表是11000001,10101010,11001101,10101000
该编码符合UTF-8编码,记事本解码时候用的UTF-8编码,所以出现错误。
标识头:
UTF-8,
用一个字节表示一个字符的时候,字节的头位是0
用两个字节表示一个字符的时候,第一个字节的头位是110,第二个字节是10
用三个字节表示一个字符的时候,第一个字节的头位是1110,第二个字节是10,第三个字节是10.


-----------android培训java培训、java学习型技术博客、期待与您交流! -----------


原创粉丝点击