IO的主要类:File,RandomAccessFile,FileInputStream,FileOutputStream,FileReader,FileWriter,PrintStream,SequenceInputStream。
1.File类是Object类的直接子类,在java.io包中。File类的对象可以序列化和排序。
构造方法:
· public File(String pathname) · public File(String parent,String child) 注意: 此构造和第一个构造方法相同,只是应用场合不同。 此构造方法的两个参数parent+child = path(第一个构造方法的那个参数)。 · public File(File parent,String child) 注意: 使用此构造方法时,传递的File对象必须指向一个文件夹,不能指向一个文件。 若指向一个文件,可以使用file.getParent()方法来获取其父目录。 |
常用方法:
范例1: 创建文件。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws IOException{ File file = new File("D:"+File.separator+"a.txt"); file.createNewFile(); //创建一个文件。 } } |
语句解释:
· createNewFile() 创建当前文件对象指向的文件,若文件存在,则不执行任何操作。 · 此方法,不论文件对象指向的文件,是否有后缀,创建的一定是文件。 |
范例2:删除文件。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws IOException{ File file = new File("D:"+File.separator+"a.txt"); file.delete(); //删除文件 } } |
语句解释:
· 若删除的对象不存在 则不执行任何操作。删除成功则返回true。 · 若使用此方法删除一个文件夹,则文件夹必须为空,否则无法删除。 |
范例3:判断文件是否存在。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws IOException{ File file = new File("D:"+File.separator+"a.txt"); if(file.exists()) file.delete(); else file.createNewFile(); } } |
语句解释:
· 判断当前文件对象所指向的文件或文件夹是否物理存在。 · 所谓的物理存在 :文件是否在硬盘上实际存在。 |
范例4:判断是文件还是文件夹。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws IOException{ File file = new File("D:"+File.separator+"a.txt"); if(file.isFile()) System.out.println("是文件."); if(file.isDirectory()) System.out.println("是目录."); } } |
语句解释:
· canExecute() :是否可执行。 · canRead() :是否能读。 · canWrite() :是否能写。 · delete() :是否能删除。 · isDirectory() :是否是文件夹。 · isFile() :是否是文件。 · isHidden() :是否是隐藏文件。 |- 这七个方法,当且仅当当前文件对象指向的文件存在且满足特定条件时,才返回true否则返回false。 |
范例5: 列出文件夹中所有的文件。
方案1:list 。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws IOException{ File file = new File("D:"+File.separator); String[] array = file.list(); for(String str : array) System.out.println(str); } } |
语句解释:
· String[] list() 以字符串数组的形式返回当前文件夹内所有内容。但只是列出了文件或者文件夹的名字。 |
方案2:listFiles。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws IOException{ File file = new File("D:"+File.separator); File[] array = file.listFiles(); for(File str : array) System.out.println(str); } } |
语句解释:
· File[] listFiles() 以文件数组的形式返回当前文件夹内所有内容。列出File对象。 |
方案3:筛选文件。
package org.hwh.io; public class FileDemo { public static void main(String[] args) throws IOException{ File file = new File("D:"+File.separator); File[] array = file.listFiles(new FileFilter(){ public boolean accept(File f){ if(f.getName().endsWith(".txt")) return true; return false; } }); for(File str : array) System.out.println(str); } } |
语句解释:
· 选择当前文件夹内,指定后缀的文件。 · 使用的匿名内部类 实现了FileFilter接口 并重写了accept方法。 · JVM负责为file下的所有文件调用一次accept方法。如果accept方法返回true则选中此文件。否则则放弃此文件。 · 只能对文件夹调用list等方法。如果文件对象指向一个文件或者指向了一个不可访问的位置(如系统文件夹 一般都会拒接访问)调用list方法则会返回null。 · .String getName() 返回文件的名称。说白了,你在构造方法里写什么, getName()就返回你写的内容中最内层的那段字符串。 · 注: listFiles()方法也可以对文件进行筛选。 |
范例6:创建目录。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws IOException{ File file = new File("D:"+File.separator+"a.txt"); file.mkdir(); } } |
语句解释:
·boolean mkdir() 创建当前文件对象指向的最内层文件夹,其父文件夹必须存在。 |- 若 File f=new File(“a.txt”); f.mkdir(); |- 此时创建一个名称为“a.txt”的文件夹而非文件。 ·mkdir()不论文件对象指向的文件是否有后缀,调用此方法,创建的一定是文件夹。 ·和createNewFile()方法相对应:不论文件是否有后缀 创建的一定是文件。 |
范例7:指定位置创建文件。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws IOException{ File file = new File("D:/fsdf/sdf/s/d/fs/df/sd/a.txt"); File parent = file.getParentFile(); parent.mkdirs() ; file.createNewFile(); } } |
语句解释:
· boolean mkdirs() 创建当前文件对象指向的文件夹、及其所有父文件夹,若已存在,则不另建。 |
注意:所有的文件操作不会立刻执行。因为Java通过JVM与底层OS进行交互的,所以所有的操作需要经过JVM来完成,因此会产生“延迟”。 |
其他方法:
· public String getPath() |- 获得相对路径。 |- 返回File对象构造器里指定的路径,若指定的是绝对路径,则返回绝对路径。 |- 说白了,咱们在构造方法里写什么,getPath()就返回什么。 · public String getAbsolutePath() |- 获得文件的绝对路径。 |- 返回值: |- 当前代码所在文件的路径+File构造器里指定的路径。 |- 如果构造器中写了绝对路径,则直接返回你写的路径,
注意: getPath()、 getAbsolutePath()、 getName() 三个方法不会去检查文件是否存在。 |
构造方法:
· public RandomAccessFile(File file,String mode) |- 打开文件的模式: |- “r” 以只读方式打开。此时调用结果对象的任何 write 方法都将导致抛出IOException。 |- “rw” 以读写的方式打开。如果该文件尚不存在,则尝试创建该文件。 · 以只读的方式打开文件时 此构造器可能抛出:FileNotFoundException。 |
常用方法:
RandomAccessFile类的读写方式:
|- 按数据类型读写
|- WriteXxx() 可以写八种基本类型 .
|- readXxx() 可以读八种基本类型 .
|- 随机读写
|- 综合读写(综合两种方式读写)
· 写字符串有三种方式。
|- 使用writeBytes()
|- 按字节序列将该字符串写入该文件。
|- 该字符串中的每个字符均按顺序写出,并丢弃其高八位。
|- 即写的字符串不能包含汉字,一般只写英文.即,只能写(0-255的字符)。
|- 如果写了汉字,则读取时,一定不能原样读会。
|- 使用writeChars()
|- 按字符的形式将该字符串写入该文件。不会丢其字符的高八位。
|- 它写的所有的字符(包括英文字母)都占2个字节。
|- 跳字节时,要注意,跳的是字符数*2。
|- 所以使用此方式写字符串,最好不要写英文,浪费空间。
|- 使用writerUTF()
|- 按UTF-8编码方式写字符串。要和readUTF()方法配合使用。
|- 注意:
|- 如果readUTF()读入的字节不表示 Unicode 字符串的有效 UTF-8 修改版编码则会抛异常:UTFDataFormatException (即 读到了UTF-8未定义的字符)。
|- 总之,别用readUTF()读不是writeUTF()写的东西。
· 使用RandomAccessFile类要坚持怎么写入,就怎么读取的方式。
比如:
使用writeBytes()写一个字符串,应该循环使用readByte();
使用writeChars()写一个字符串,应该循环使用readChar();
使用writeUTF() 写一个字符串,应该使用readUTF()读入这个字符串。
· RandomAccessFile类写数据时,会在每次写的数据后加一个标记,从而不会出现“多读”。
范例1:进行随机读写数据。
|- 第一部分代码 先向文件中写数据。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+File.separator+"a.txt"); RandomAccessFile r = new RandomAccessFile(file,"rw"); r.writeChars("张三"); r.writeInt(30); r.writeFloat(8000); r.writeChars("李四"); r.writeInt(33); r.writeFloat(5200); r.writeChars("王五"); r.writeInt(43); r.writeFloat(6200); |
语句解释:
· 使用“rw”方式打开文件。如果文件不存在则 创建文件。 |
|- 第二部分代码 从文件中读取数据。
r.seek(0); //回到文件开头 System.out.println("姓名: " + readString(r, 2) + "; 年龄:" + r.readInt()+ "; 工资:" + r.readFloat()); r.skipBytes(12); //跳过李四的信息。 System.out.println("姓名: " + readString(r, 2) + "; 年龄:" + r.readInt()+ "; 工资:" + r.readFloat()); r.close(); //用完后要关闭流 } public static String readString(RandomAccessFile r, int count) throws IOException { char[] array = new char[count]; for (int i = 0; i < count; i++) array[i] = r.readChar(); return new String(array); } }
|
语句解释:
· 使用“rw”方式打开文件。如果文件不存在则 创建文件。 |
扩展:
· seek()方法访问底层的运行时系统因此往往是消耗巨大的。 · RandomAccessFile类可以通过seek(file.length()) 跳到文件的最后,达到追加效果。 · 使用其他字节流指向某个文件,即使没有写任何东西,也会清空文件的内容。 · 使用RandomAccessFile类并不是将原内容清空,而是覆盖,写多少就覆盖多少,未覆盖的则保持不变。因此可以使用seek(file.length()) 进行追加。 |
3.FileOutputStream和FileInputStream是和文件关联的字节流
构造方法:
· public FileOutputStream(File file) throws FileNotFoundException · public FileOutputStream(File file,boolean append) throws FileNotFoundException public FileInputStream(File file) throws FileNotFoundException |- file 设置要操作的文件。 |- append 设置是否以追加的方式操作文件。 |
常用方法:
范例1: 向文件中写数据。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+File.separator+"a.txt"); FileOutputStream out = new FileOutputStream(file); out.write("张三".getBytes()); out.write(30); out.close(); } } |
语句解释:
· public void write(int b) throws IOException |- 将指定的字节写入此输出流。向输出流写入一个字节。 |- 要写入的字节是参数 b 的低八位。b 的高24位将被忽略。 Int型占4个字节32位。 · public void write(byte[] b) throws IOException |- 写一个字符串时,可以使用此方法。 · public void close() throws IOException |- 其实呢 字节流在一些时候是可以不关闭的,不会有什么影响。但是为养成一个好习惯 所以 还是关闭它吧。而且如果使用了缓冲区 则即使是字节流也同样需要关闭流。 · 字符串的getBytes()方法 可以将字符串转成一个字节数组。 |
注意:
· 如果不是以追加的方式写文件: |- 若文件不存在,则建立这个文件. |- 若文件存在,则删除其内的内容,后,再写上新内容。 |
范例2:从文件中读取数据。
package org.hwh.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+File.separator+"a.txt"); FileInputStream in = new FileInputStream(file); byte[] array = new byte[4]; for(int i=0;i<array.length;i++) array[i]=(byte)in.read(); //读取一个字节 System.out.println(new String(array)); System.out.println(in.read()); in.close(); } }
|
语句解释:
· public int read() throws IOException |- 从输入流读取下一个数据字节。如果到达流末尾,则返回值 -1。 |- 如果需要读入一个字符,则需要将返回值进行强制类型转换(char) |- 返回 0 到 255 范围内的 int 字节值(即只读1个字节,但是呢 不是截位读)。 · public int read(byte[] b) throws IOException |- 可以使用此方法,读入一个字符串。 |- 但byte[]大小不好估计: |- 估计大了容易浪费空间 |- 若估计小了,则读满数组,就停止,不会,继续读。 |- 这也是不直接使用节点流的原因,因为他的功能确实太简单了。 |- 但是也可以精确的指定数据的大小,在File类有一个方法, long length(), 若文件不存在,则返回0L。我们可以根据文件的大小来开辟数组。 · public void close() throws IOException |- 关闭流。 |
注意:
· 如果OutputStream指向的文件不存在,则会帮助我们自动创建一个文件。 · 如果InputStream指向的文件不存在,则会抛FileNotFoundException异常 · windows中使用\r\n换行,java中使用\n换行。因此向记事本中写数据的时候,如果想在记事本中换行,则需要写一个“\r\n”字符串。 · 创建节点流对象时,会立刻去查看其参数(文件对象)是否存在。如果不存在,输出流会在第一时间尝试创建这个文件,输入流会在第一时间,抛异常。 · 对一个文件正在读(或者写)的时候,不要同时进行写(或者读)操作。 |- 即,在对象out未调用close()方法之前,咱们不应该再使用对象in读,也许能读取成功,但是不要这么做。 |
4.FileReader和FileWriter是与文件关联的字符流
构造方法:
· public FileReader(File file) throws FileNotFoundException |- 设置要操作的文件对象。 · public FileWriter(File file) throws IOException |- 设置要操作的文件对象。 · public FileWriter(File file, boolean append) throws IOException |- append 设置是否以追加的方式操作文件。 |
范例1: 读写文件。
package cxy.zy.io; import java.io.*; public class FileDemo { public static void main(String[] args) throws Exception { FileWriter out = new FileWriter(new File("D:"+File.separator+"a.txt")); FileReader in = new FileReader(new File("D:"+File.separator+"a.txt")); out.write("世界,你好。\r\nHello World"); out.write(97); //虽然写的是97,但在记事本中,输入的是字符’a’ out.close(); int temp; while((temp = in.read())!=-1) System.out.print((char)temp); in.close(); } } |
语句解释:
· public void write(int c) throws IOException |- 1个int数据占32位 只能写入的 低16 位中,高16 位被忽略。 · public void write(String str) throws IOException |- 写一个字符串。 · 使用字符流读写字符串比使用字节流方便(这是必然的)。 · 使用FileWriter写时 可以写的单个字符或者一个字符串,此时,写字符串比字节流方便。其实也方便不了哪去。用字节流的write(“世界你好”.getBytes())一样方便。但是不论是字符流还是字节流 如果想直接使用节点流读入一个字符串 则就会有些费事了。 · 使用FileReader读时 只能读单个字符或者一个字符数组。 |
5. PrintStream类它是一个字节流 也是一个节点流。一般来说,不直接实例化此类对象.
范例1:PrintStream 。
import java.io.*; public class PrintStreamDemo { public static void main(String[] args) throws IOException{ PrintStream p=new PrintStream(new File("D:"+File.separator+"a.txt")); p.print('C'); p.print(123); p.println("\r\nHello world"); p.printf("\r\n%c,%d,%s", 'A',97,"Hello A!"); p.printf("\r\n%s,%s,%s", 'A',97,"Hello A!"); p.close(); } } |
6.SequenceInputStream类为合并流 将2个数据源中的内容合并在一起。如将2个记事本的内容合成1个记事本文件。构造方法:
SequenceInputStream(InputStream s1, InputStream s2) 接受两个InputStream对象。
范例1:
import java.io.*; public class SequenceDemo { public static void main(String[] args) throws Exception { BufferedInputStream buf = new BufferedInputStream( new SequenceInputStream(new FileInputStream(new File("D:/周杰伦 - 你怎么连话都说不清楚 - 演唱会 the one.mp3")),new FileInputStream(new File("D:/周杰伦-回到过去.mp3")))); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File("D:"+File.separator+"total1.mp3"))); int temp; long start = System.currentTimeMillis(); while( (temp = buf.read())!=-1) out.write(temp); System.out.println("耗时: "+(System.currentTimeMillis()-start)); buf.close(); out.close(); } } 注意:使用合并流时,要使用上面的read()读,而不要使用read(byte[])。 注意:上面2首歌共12MB 如果不使用缓冲区 则花费了65秒。 使用缓冲区后1328毫秒 |
---------------------- android培训、java培训、期待与您交流! ---------------------- 详细请查看:http://edu.csdn.net/heima