概括:1、File类的主要作用是完成文件的操作,与文件本身有关,File是指文件的路径
2、字节流:InputStream、OutputStream、字符流:Reader、Writer
以上四个类都是抽象类,抽象类的特点就是根据不同的需要实例化不同的子类。如果是文件的操作则是FileXxx.字符流操作时先到缓存,字节流是直接操作底层的IO。
JavaIO
在Java IO实际上很好的体现了面向对象的设计思想。一个接口或抽象类的具体行为由子类决定,那么根据实例化子类的不同完成的功能叶不同。Java IO的所有的操作都放在了java.io开发包中,主要的类和接口是:File、InputStream、OutputStream、Reader、Writer、Serialzable接口。
1、 File (包括了文件和文件夹的路径的抽象)
实现File的创建、删去、等操作。
构造方法:public File(String pathname);
File.separator表示文件分隔符“\”
1.1创建文件:public booleancreateNewFile() throws IOException
1.2删去文件:public booleandelete();
public class FileDeleteDemo { public static void main(String[] args) File file = new File("d:"+File.separator+"demo.txt");/*new了一个文件对象,但是在磁盘中还不存在此文件*/ file.createNewFile();//创建文件 Thread.sleep(2000); file.delete();//删去文件 } } |
1.3 判断文件是否存在:public booleanexits();
public class FileDeleteDemo { public static void main(String[] args) File file = new File("d:"+File.separator+"demo.txt");/*new了一个文件对象*/ if(file.exists()){//判断文件是否存在 System.out.println("文件存在!!"); }else{ System.out.println("文件不存在!!"); } } } |
1.4判断文件是否为文件夹:public booleanisDirectory();
判断文件是否为文件:public boolean isFile();
public static void main(String[] args) File file1 = new File("d:"+File.separator+"demo.txt");/*new了一个文件对象*/ File file2 = new File("d:"+File.separator+"demo"); file1.createNewFile(); file2.createNewFile(); System.out.println(file1.isFile()); System.out.println(file2.isDirectory()); } } /*true false*/ |
1.5列出文件目录:
public String[] list()//返回文件或文件夹的数组
public File[] listFiles()//返回一个抽象路径名数组
package com.jtlyuan; import java.io.File; import java.io.IOException; public class FileListDemo { public static void main(String[] args) throws Exception { File file = new File("d:"+File.separator+"jtl");/*new了一个文件路径对象*/ String str[] = file.list(); System.out.println("*********使用file.list()的效果*********"); for(int i=0;i<str.length;i++){ System.out.println(str[i]); } System.out.println(); System.out.println(); System.out.println("*********使用file.listFile()的效果*********"); File[] f = file.listFiles(); for(int i=0;i<f.length;i++){ System.out.println(f[i]); } } } } /* * *********使用file.list()的效果********* 12345 12345.rar 12345市长热线 2011-7-21会议记录.doc 2011年7月研发团队通讯录.xls 8月4日_会议内容.docx ADDB ADDB.rar
*********使用file.listFile()的效果********* d:\jtl\12345 d:\jtl\12345.rar d:\jtl\12345市长热线 d:\jtl\2011-7-21会议记录.doc d:\jtl\2011年7月研发团队通讯录.xls d:\jtl\8月4日_会议内容.docx d:\jtl\ADDB d:\jtl\ADDB.rar */ */ |
显然list()只是是显示文件或文件夹的名称,而listFile()则会列出文件或文件夹的完整路径
1.6创建文件夹
public boolean mkdir()//创建此抽象路径名指定的目录
public boolean mkdirs()//创建此抽象路径名指定的目录,包括所有必需但不存在的父目录
public class FileMikeeDemo { public static void main(String[] args) File file = new File("d:"+File.separator+"demo"+File.separator+"inner"); /*new了一个文件对象*/ file.mkdirs(); } } /*创建了D:\demo\inner文件夹*/ |
思考题:给定一个文件目录:列出里面所有的文件,包括子文件夹里的文件
public class AllFileListDemo { public static void main(String[] args) { File file = new File("d:"+File.separator); lists(file); } static void lists(File file){ if(file.isDirectory()){ File[] f =file.listFiles(); for(int i=0;i<f.length;i++){ lists(f[i]); } }else{ System.out.println(file); } } } |
2、 字节流和字符流(最重点)
整个IO包中,流的操作包包括了两种
·字节流:字节输出流:OutputStream、字节输入流InputStream
·字符流:(一个字符==2个字节)字符输出流Writer、字符输入流是Reader
2.1字节输入流:OutputStream
在java.io的开发包中,OutputStream是字节输出流的最大父类。是个抽象类,不能实例化,只能通过子类实例化(一般用FileOutputStream)
public abstract class OutputStream extends Objectimplements Closeable, Flushable |
OutputStream是方法有:
·写入一个一个数据:publicabstract void write(int b);(比较常用的方法)
·写入全部的字节数组:publicvoid write(byte[] b);
·写入部分字节数组:publicvoid write(byte[] b,int off,int length)
package com.jtlyuan.outstream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class OutputStreamTest{ public static void main(String[] args) /*定义了一个文件路径,注意原来是没有文件的,但是自动帮你建立一个文件了*/ File file = new File("d:"+File.separator+"demo.doc"); OutputStream out = null;//定义一个字节输出流,是抽象类 out = new FileOutputStream(file);//用子类FileOutputstream实例化 String str = "Hello jtlyuan"; byte[] b = str.getBytes(); for(int i=0;i<b.length;i++){ out.write(b );//利用这种方式写入文件的比较多 } out.close(); } } /在d:下建立生成了一个“demo.doc”的文件,里面写着Hello jtlyuan 呵呵,神奇吧*/ |
如果把Str改为“Hello World”的话,再次运行,文件中的原来的内容被覆盖了,那么可不可以在原来的内容中加追加内容,而不是覆盖呢?答案当然是可以的啦,好啦,把out = new FileOutputStream(file)改变为 out =new FileOutputStream(file,true)文件就解决了
public class OutputStreamTest{ public static void main(String[] args) /*定义了一个文件路径,注意原来是没有文件的,但是自动帮你建立一个文件了*/ File file = new File("d:"+File.separator+"demo.doc"); OutputStream out = null;//定义一个字节输出流,是抽象类 out = new FileOutputStream(file,true);//用子类FileOutputstream实例化 String str = "\r\nHello jtlyuan";//注意\r\n表示换行 byte[] b = str.getBytes(); for(int i=0;i<b.length;i++){ out.write(b[i] );//利用这种方式写入文件的比较多 } out.close(); } } |
2.2字节输入类:
同理InputStream是一个字节输入流的父类,是个抽象类,一个要用FileInputStream来实例化
利用InputStream中的public int read(byte[] b)throws IOException
将文件内容读入到byte数组中,然后返回文件的长度大小。
public class InputStreamTest { public static void main(String[] args)throws Exception { File file = new File("d:"+File.separator+"demo.doc"); InputStream in = null; in = new FileInputStream(file);//创建字节输入流的实例 byte[] b = new byte[(int)file.length()];//字节数组的大小根据文件的大小指定 in.read(b);//把file文件写到字节数组中 System.out.println(new String(b)); in.close(); } } |
2.3字符输出流:Writer
Writer类是在io包中操作字符最大的父类,和OutputStream一样的抽象类,需要FileWriter(File)来实例化,或者用FileWriter(File file,ture)(这是可以向文件追加内容的实例化方式)用public void write(String str) throws IOException写入字符串
public class WriterTest { public static void main(String[] args)throws Exception { File file = new File("d:"+File.separator+"demo1.doc"); Writer writer = null; writer = new FileWriter(file); String str = "梁任元"; writer.write(str); writer.close(); } } |
2.4字符输入流:Reader
字符类也是与字节流一样,但是使用的是char数组。
public class ReaderTest { public static void main(String[] args)throws Exception { File file = new File("d:"+File.separator+"demo1.doc"); Reader reader = null; reader = new FileReader(file); char[] c = new char[(int)file.length()]; reader.read(c); System.out.println(c); reader.close(); } } |
总结:字节流与字符流的区别:
为了看清楚,看下面的例子
范例:使用字节流
public static void main(String[] args) /*定义了一个文件路径,注意原来是没有文件的,但是自动帮你建立一个文件了*/ File file = new File("d:"+File.separator+"demo.doc"); OutputStream out = null;//定义一个字节输出流,是抽象类 out = new FileOutputStream(file);//用子类FileOutputstream实例化 String str = "Hello jtlyuan"; byte[] b = str.getBytes(); for(int i=0;i<b.length;i++){ out.write(b );//利用这种方式写入文件的比较多 } } }
|
注意到:文件没有关闭,但是可以看到文件已经有输出了,再看字符流
范例:
public class WriterTest { public static void main(String[] args)throws Exception { File file = new File("d:"+File.separator+"demo1.doc"); Writer writer = null; writer = new FileWriter(file); String str = "梁任元"; writer.write(str); //writer.flush() } } |
注意到:文件没有关闭,但是没有内容向文件输出,但是加了writer.flush()进行刷新的话,可以看到内容输出了,为什么呢?因为字符类操作的时候要刷新缓冲区,才完成操作,而直接关闭的话,也就自动强制进行了刷新。
得出这样的一个结论:
·字节流操作的时候是直接与文件本身关联,而不是缓冲区。
字节----à文件
·字符类才操作的时候是通过缓冲区与文件操作的
字符---à 缓冲区 ---à文件
终上所述:传输内容或者在硬盘上保持内容的时候都是以字节的形式存在的,所有使用字节流比较方面。而在操作中文(一个中文==2个字节)的时候使用字符类比较好。
作业:
实现文件的复制功能:
public class Copy { public static void main(String[] args) throws Exception {// 所有异常抛出 if (args.length != 2) { // 参数不是两个 System.out.println("操作的语法不正确,应该输入要拷贝的文件路径。"); System.out.println("例:java Copy 源文件路径 目标文件路径"); System.exit(1); // 系统退出 } if (args[0].equals(args[1])) { System.out.println("无法复制自身文件。"); System.exit(1); // 系统退出 } File file1 = new File(args[0]); // 找到第一个文件的File对象 if (file1.exists()) { File file2 = new File(args[1]); // 找到目标文件路径 InputStream input = new FileInputStream(file1); // 输入流 OutputStream output = new FileOutputStream(file2);// 输出流 int temp = 0; // 定义一个整数表示接收的内容 while ((temp = input.read()) != -1) { // 表示还有内容可以继续读 output.write(temp);// 写入数据 } System.out.println("文件复制成功。"); input.close(); // 关闭 output.close();// 关闭 } else { System.out.println("源文件不存在。"); } } } |