详解Java中的File文件类以及FileDescriptor文件描述类
file
file 是“文件”和“目录路径名”的抽象表示形式。
file 直接继承于object,实现了serializable接口和comparable接口。实现serializable接口,意味着file对象支持序列化操作。而实现comparable接口,意味着file对象之间可以比较大小;file能直接被存储在有序集合(如treeset、treemap中)。
1. 新建目录的常用方法
方法1:根据相对路径新建目录。
示例代码如下(在当前路径下新建目录“dir”):
file dir = new file("dir"); dir.mkdir();
方法2:根据绝对路径新建目录。
示例代码如下(新建目录“/home/skywang/dir”):
file dir = new file("/home/skywang/dir"); dir.mkdirs();
说明:上面是在linux系统下新建目录“/home/skywang/dir”的源码。在windows下面,若要新建目录“d:/dir”,源码如下:
file dir = new file("d:/dir"); dir.mkdir();
方法3
uri uri = new uri("file:/home/skywang/dir"); file dir = new file(uri); sub.mkdir();
说明: 和“方法2”类似,只不过“方法2”中传入的是完整路径,而“方法3”中传入的是完整路径对应uri。
2. 新建子目录的几种常用方法
例如,我们想要在当前目录的子目录“dir”下,再新建一个子目录。有一下几种方法:
方法1
file sub1 = new file("dir", "sub1"); sub1.mkdir();
说明:上面的方法作用是,在当前目录下 "dir/sub1"。它能正常运行的前提是“sub1”的父目录“dir”已经存在!
方法2
file sub2 = new file(dir, "sub2"); sub2.mkdir();
说明:上面的方法作用是,在当前目录下 "dir/sub2"。它能正常运行的前提是“sub2”的父目录“dir”已经存在!
方法3
file sub3 = new file("dir/sub3"); sub3.mkdirs();
说明:上面的方法作用是,在当前目录下 "dir/sub3"。它不需要dir已经存在,也能正常运行;若“sub3”的父母路不存在,mkdirs()方法会自动创建父目录。
方法4
file sub4 = new file("/home/skywang/dir/sub4"); sub4.mkdirs();
说明:上面的方法作用是,新建目录"/home/skywang/dir/sub3"。它不需要dir已经存在,也能正常运行;若“sub4”的父母路不存在,mkdirs()方法会自动创建父目录。
方法5
uri uri = new uri("file:/home/skywang/dir/sub5"); file sub5 = new file(uri); sub5.mkdirs();
说明: 和“方法4”类似,只不过“方法4”中传入的是完整路径,而“方法5”中传入的是完整路径对应uri。
3. 新建文件的几种常用方法
例如,我们想要在当前目录的子目录“dir”下,新建一个文件。有一下几种方法
方法1
try { file dir = new file("dir"); // 获取目录“dir”对应的file对象 file file1 = new file(dir, "file1.txt"); file1.createnewfile(); } catch (ioexception e) { e.printstacktrace(); }
说明:上面代码作用是,在“dir”目录(相对路径)下新建文件“file1.txt”。
方法2
try { file file2 = new file("dir", "file2.txt"); file2.createnewfile(); } catch (ioexception e) { e.printstacktrace(); }
说明:上面代码作用是,在“dir”目录(相对路径)下新建文件“file2.txt”。
方法3
try { file file3 = new file("/home/skywang/dir/file3.txt"); file3.createnewfile(); } catch (ioexception e) { e.printstacktrace(); }
说明:上面代码作用是,下新建文件“/home/skywang/dir/file3.txt”(绝对路径)。这是在linux下根据绝对路径的方法,在windows下可以通过以下代码新建文件"d:/dir/file4.txt"。
try { file file3 = new file("d:/dir/file4.txt"); file3.createnewfile(); } catch (ioexception e) { e.printstacktrace(); }
方法4
try { uri uri = new uri("file:/home/skywang/dir/file4.txt"); file file4 = new file(uri); file4.createnewfile(); } catch (ioexception e) { e.printstacktrace(); }
说明:
和“方法3”类似,只不过“方法3”中传入的是完整路径,而“方法4”中传入的是完整路径对应uri。
4. file api使用示例
关于file中api的详细用法,参考示例代码(filetest.java):
import java.io.file; import java.io.ioexception; import java.net.uri; import java.util.calendar; import java.text.simpledateformat; public class filetest { public static void main(string[] args) { testfilestaticfields() ; testfiledirapis() ; } public static void testfilestaticfields() { // 打印 路径分隔符":" system.out.printf("file.pathseparator=\"%s\"\n", file.pathseparator); // 打印 路径分隔符':' system.out.printf("file.pathseparatorchar=\"%c\"\n", file.pathseparatorchar); // 打印 分隔符"/" system.out.printf("file.separator=\"%s\"\n", file.separator); // 打印 分隔符'/' system.out.printf("file.separatorchar=\"%c\"\n", file.separatorchar); } public static void testfiledirapis() { try { // 新建目录 "dir" file dir = new file("dir"); dir.mkdir(); // 方法1:新建目录 "dir/sub1"。父目录“dir”必须已经存在! file sub1 = new file("dir", "sub1"); sub1.mkdir(); // 方法2:新建目录 "dir/sub2"。父目录“dir”必须已经存在! file sub2 = new file(dir, "sub2"); sub2.mkdir(); // 方法3:新建目录 "dir/sub3"。mkdirs()会自动创建不存在的父目录。 file sub3 = new file("dir/sub3"); sub3.mkdirs(); // 方法4:新建目录 "dir/sub4"。根据“绝对路径”创建,前面3个方法都是根据“相对路径”创建。 string dirpath = dir.getabsolutepath(); // 获取“dir”的绝对路径 string sub4abspath = dirpath + file.separator + "sub4"; // file.separator是分隔符"/" file sub4 = new file(sub4abspath); sub4.mkdirs(); // 方法5:新建目录 "dir/sub5"。根据uri string uri_sub5_path = "file:"+ dirpath + file.separator + "sub5"; uri uri_sub5 = new uri(uri_sub5_path); file sub5 = new file(uri_sub5); sub5.mkdirs(); // 方法1:新建文件 "dir/l1_normal.txt" file l1_normal = new file(dir, "l1_normal.txt"); l1_normal.createnewfile(); // 方法2:新建文件 "dir/.l1_hide.txt"。 file l1_hide = new file("dir", ".l1_hide.txt"); // 在linux中, "."开头的文件是隐藏文件。 l1_hide.createnewfile(); // 方法3:新建文件 "dir/l1_abs.txt"。 string dirabspah = dir.getabsolutepath(); // 获取dir的绝对路径 string l1_abs_path = dirabspah+file.separator+"l1_abs.txt"; file l1_abs = new file(l1_abs_path); l1_abs.createnewfile(); //system.out.printf("l1_abs_path=%s\n", l1_abs_path); //system.out.printf("l1_abs path=%s\n", l1_abs.getabsolutepath()); // 方法4:新建文件 "dir/l1_uri.txt"。根据uri新建文件 string uri_path = "file:"+ dirabspah + file.separator + "l1_uri.txt"; uri uri_l1 = new uri(uri_path); //system.out.printf("uri_l1=%s\n", l1_abs.getabsolutepath()); file l1_uri = new file(uri_l1); l1_uri.createnewfile(); // 新建文件 "dir/sub/s1_normal" file s1_normal = new file(sub1, "s1_normal.txt"); s1_normal.createnewfile(); system.out.printf("%30s = %s\n", "s1_normal.exists()", s1_normal.exists()); system.out.printf("%30s = %s\n", "s1_normal.getname()", s1_normal.getname()); system.out.printf("%30s = %s\n", "s1_normal.getparent()", s1_normal.getparent()); system.out.printf("%30s = %s\n", "s1_normal.getpath()", s1_normal.getpath()); system.out.printf("%30s = %s\n", "s1_normal.getabsolutepath()", s1_normal.getabsolutepath()); system.out.printf("%30s = %s\n", "s1_normal.getcanonicalpath()", s1_normal.getcanonicalpath()); system.out.printf("%30s = %s is \"%s\"\n", "s1_normal.lastmodified()", s1_normal.lastmodified(), getmodifytime(s1_normal.lastmodified())); system.out.printf("%30s = %s\n", "s1_normal.touri()", s1_normal.touri()); // 列出“dir”目录下的“文件”和“文件夹”。 // 注意:dir.listfiles()只会遍历目录dir,而不会遍历dir的子目录! system.out.println("---- list files and folders ----"); file[] fs = dir.listfiles(); for (file f:fs) { string fname = f.getname(); string absstr = f.isabsolute() ? "[absolute]" : ""; string hidstr = f.ishidden() ? "[hidden]" : ""; string dirstr = f.isdirectory() ? "[directory]" : ""; string filestr = f.isfile() ? "[file]" : ""; system.out.printf("%-30s %s%s%s%s\n", fname, filestr, dirstr, absstr, hidstr); } } catch (exception e) { e.printstacktrace(); } } private static string getmodifytime(long millis) { // 获取calendar对象 calendar cal = calendar.getinstance(); // 设置时间为 millis cal.settimeinmillis(millis); // 获取格式化对象,它会按照"yyyy-mm-dd hh:mm:ss"格式化日期 simpledateformat sdf = new simpledateformat("yyyy-mm-dd hh:mm:ss"); //system.out.printf("time %s\n", str); return sdf.format(cal.gettime()); } }
运行结果(在ubuntu 12.04系统下的运行结果,而不是windows!):
file.pathseparator=":" file.pathseparatorchar=":" file.separator="/" file.separatorchar="/" s1_normal.exists() = true s1_normal.getname() = s1_normal.txt s1_normal.getparent() = dir/sub1 s1_normal.getpath() = dir/sub1/s1_normal.txt s1_normal.getabsolutepath() = /home/skywang/wind_talker/workout/java/skywang/io/io/src/file/dir/sub1/s1_normal.txt s1_normal.getcanonicalpath() = /home/skywang/wind_talker/workout/java/skywang/io/io/src/file/dir/sub1/s1_normal.txt s1_normal.lastmodified() = 1381730064000 is "2013-10-14 13:54:24" s1_normal.touri() = file:/home/skywang/wind_talker/workout/java/skywang/io/io/src/file/dir/sub1/s1_normal.txt ---- list files and folders ---- l1_uri.txt [file] sub1 [directory] l1_abs.txt [file] sub5 [directory] sub4 [directory] .l1_hide.txt [file][hidden] sub3 [directory] sub2 [directory] l1_normal.txt [file]
结果说明:运行程序,会在源文件所在的目录新建目录"dir"及其子目录和子文件。如下图:
filedescriptor
filedescriptor 是“文件描述符”。
filedescriptor 可以被用来表示开放文件、开放套接字等。
以filedescriptor表示文件来说:当filedescriptor表示某文件时,我们可以通俗的将filedescriptor看成是该文件。但是,我们不能直接通过filedescriptor对该文件进行操作;若需要通过filedescriptor对该文件进行操作,则需要新创建filedescriptor对应的fileoutputstream,再对文件进行操作。
in, out, err介绍
(1) in -- 标准输入(键盘)的描述符
(2) out -- 标准输出(屏幕)的描述符
(3) err -- 标准错误输出(屏幕)的描述符
它们3个的原理和用法都类似,下面我们通过out来进行深入研究。
1.1 out 的作用和原理
out是标准输出(屏幕)的描述符。但是它有什么作用呢?
我们可以通俗理解,out就代表了标准输出(屏幕)。若我们要输出信息到屏幕上,即可通过out来进行操作;但是,out又没有提供输出信息到屏幕的接口(因为out本质是filedescriptor对象,而filedescriptor没有输出接口)。怎么办呢?
很简单,我们创建out对应的“输出流对象”,然后通过“输出流”的write()等输出接口就可以将信息输出到屏幕上。如下代码:
try { fileoutputstream out = new fileoutputstream(filedescriptor.out); out.write('a'); out.close(); } catch (ioexception e) { }
执行上面的程序,会在屏幕上输出字母'a'。
为了方便我们操作,java早已为我们封装好了“能方便的在屏幕上输出信息的接口”:通过system.out,我们能方便的输出信息到屏幕上。
因此,我们可以等价的将上面的程序转换为如下代码:
system.out.print('a');
下面讲讲上面两段代码的原理
查看看out的定义。它的定义在filedescriptor.java中,相关源码如下:
public final class filedescriptor { private int fd; public static final filedescriptor out = new filedescriptor(1); private filedescriptor(int fd) { this.fd = fd; usecount = new atomicinteger(); } ... }
从中,可以看出
(1) out就是一个filedescriptor对象。它是通过构造函数filedescriptor(int fd)创建的。
(2) filedescriptor(int fd)的操作:就是给fd对象(int类型)赋值,并新建一个使用计数变量usecount。
fd对象是非常重要的一个变量,“fd=1”就代表了“标准输出”,“fd=0”就代表了“标准输入”,“fd=2”就代表了“标准错误输出”。
fileoutputstream out = new fileoutputstream(filedescriptor.out);
就是利用构造函数fileoutputstream(filedescriptor fdobj)来创建“filed.out对应的fileoutputstream对象”。
关于system.out是如何定义的。可以参考"深入了解system.out.println("hello world") "
通过上面的学习,我们知道,我们可以自定义标准的文件描述符[即,in(标准输入),out(标准输出),err(标准错误输出)]的流,从而完成输入/输出功能;但是,java已经为我们封装好了相应的接口,即我们可以更方便的system.in, system.out, system.err去使用它们。
另外,我们也可以自定义“文件”、“socket”等的文件描述符,进而对它们进行操作。参考下面示例代码中的testwrite(), testread()等接口。
2. 示例代码
源码如下(filedescriptortest.java):
import java.io.printstream; import java.io.filedescriptor; import java.io.fileinputstream; import java.io.fileoutputstream; import java.io.ioexception; public class filedescriptortest { private static final string filename = "file.txt"; private static final string outtext = "hi filedescriptor"; public static void main(string[] args) { testwrite(); testread(); teststandfd() ; //system.out.println(outtext); } /** * filedescriptor.out 的测试程序 * * 该程序的效果 等价于 system.out.println(outtext); */ private static void teststandfd() { // 创建filedescriptor.out 对应的printstream printstream out = new printstream( new fileoutputstream(filedescriptor.out)); // 在屏幕上输出“hi filedescriptor” out.println(outtext); out.close(); } /** * filedescriptor写入示例程序 * * (1) 为了说明,"通过文件名创建fileoutputstream"与“通过文件描述符创建fileoutputstream”对象是等效的 * (2) 该程序会在“该源文件”所在目录新建文件"file.txt",并且文件内容是"aa"。 */ private static void testwrite() { try { // 新建文件“file.txt”对应的fileoutputstream对象 fileoutputstream out1 = new fileoutputstream(filename); // 获取文件“file.txt”对应的“文件描述符” filedescriptor fdout = out1.getfd(); // 根据“文件描述符”创建“fileoutputstream”对象 fileoutputstream out2 = new fileoutputstream(fdout); out1.write('a'); // 通过out1向“file.txt”中写入'a' out2.write('a'); // 通过out2向“file.txt”中写入'a' if (fdout!=null) system.out.printf("fdout(%s) is %s\n",fdout, fdout.valid()); out1.close(); out2.close(); } catch(ioexception e) { e.printstacktrace(); } } /** * filedescriptor读取示例程序 * * 为了说明,"通过文件名创建fileinputstream"与“通过文件描述符创建fileinputstream”对象是等效的 */ private static void testread() { try { // 新建文件“file.txt”对应的fileinputstream对象 fileinputstream in1 = new fileinputstream(filename); // 获取文件“file.txt”对应的“文件描述符” filedescriptor fdin = in1.getfd(); // 根据“文件描述符”创建“fileinputstream”对象 fileinputstream in2 = new fileinputstream(fdin); system.out.println("in1.read():"+(char)in1.read()); system.out.println("in2.read():"+(char)in2.read()); if (fdin!=null) system.out.printf("fdin(%s) is %s\n", fdin, fdin.valid()); in1.close(); in2.close(); } catch(ioexception e) { e.printstacktrace(); } } }
运行结果:
fdout(java.io.filedescriptor@2b820dda) is true in1.read():a in2.read():a fdin(java.io.filedescriptor@675b7986) is true hi filedescriptor
上一篇: 浅谈java异常处理(父子异常的处理)
下一篇: Java 数组详解及示例代码
推荐阅读
-
详解Java中的File文件类以及FileDescriptor文件描述类
-
详解Java中的File文件类以及FileDescriptor文件描述类
-
java实现利用String类的简单方法读取xml文件中某个标签中的内容
-
java实现利用String类的简单方法读取xml文件中某个标签中的内容
-
java创建一个类实现读取一个文件中的每一行显示出来
-
java创建一个类实现读取一个文件中的每一行显示出来
-
解析Java的Hibernate框架中的持久化类和映射文件
-
Java中的日期和时间类以及Calendar类用法详解
-
Java中的日期和时间类以及Calendar类用法详解
-
Java文件(io)编程_基于File类的基本用法(必看篇)