33.JAVA编程思想——JAVA IO File类
33.JAVA编程思想——JAVA IO File类
RandomAccessFile用于包括了已知长度记录的文件。以便我们能用 seek()从一条记录移至还有一条;然后读取或改动那些记录。
各记录的长度并不一定同样;仅仅要知道它们有多大以及置于文件何处就可以。
首先。我们有点难以相信RandomAccessFile 不属于InputStream 或者OutputStream 分层结构的一部分。除了恰巧实现了DataInput 以及DataOutput(这两者亦由 DataInputStream和DataOutputStream实现)接口之外,它们与那些分层结构并无什么关系。它甚至没实用到现有InputStream 或OutputStream 类的功能——採用的是一个全然不相干的类。
该类属于全新的设计,含有自己的全部(大多数为固有)方法。
之所以要这样做,是由于RandomAccessFile
拥有与其它 IO类型全然不同的行为。由于我们可在一个文件中向前或向后移动。无论在哪种情况下。它都是独立运作的,作为Object 的一个“直接继承人”使用。
从根本上说,RandomAccessFile 相似DataInputStream和 DataOutputStream的联合使用。
当中,getFilePointer()用于了解当前在文件的什么地方。seek()用于移至文件内的一个新地点。而 length()用于推断文件的最大长度。
此外,构建器要求使用还有一个自变量(与C 的fopen()全然一样)。指出自己仅仅是随机读("r")。还是读写兼施("rw")。这里没有提供对“仅仅写文件”的支持。也就是说,假如是从DataInputStream继承的,那么
RandomAccessFile也有可能能非常好地工作。
还有更难对付的。非常easy想象我们有时要在其它类型的数据流中搜索,比方一个ByteArrayInputStream。但搜索方法仅仅有RandomAccessFile 才会提供。而后者仅仅能针对文件才干操作,不能针对数据流操作。此时。BufferedInputStream 确实同意我们标记一个位置(使用mark(),它的值容纳于单个内部变量中)。并用reset()重设那个位置。但这些做法都存在限制。并非特别实用。
1. File类
File 类有一个欺骗性的名字——一般会觉得它对付的是一个文件。但实情并非如此。它既代表一个特定文件的名字,也代表文件夹内一系列文件的名字。若代表一个文件集。便可用list()方法查询这个集,返回的是一个字串数组。之所以要返回一个数组,而非某个灵活的集合类。是由于元素的数量是固定的。并且若想得到
一个不同的文件夹列表。仅仅需创建一个不同的File 对象就可以。其实,“FilePath”(文件路径)似乎是一个更好的名字。
1.1 文件夹列表器
如果想观看一个文件夹列表。可用两种方式列出File 对象。若在不含自变量(參数)的情况下调用list(),会获得 File 对象包括的一个完整列表。
然而。若想对这个列表进行某些限制,就须要使用一个“文件夹过滤器”,该类的作用是指出应怎样选择File 对象来完毕显示。
样例的代码:
l 代码例如以下
import java.io.*;
public
classDirList {
public
static void main(String[]
args) {
try {
Filepath=
newFile(".");
String[]list;
if (args.length == 0)
list = path.list();
else
list = path.list(new DirFilter(args[0]));
for (int
i = 0; i <
list.length;
i++)
System.out.println(list[i]);
}catch(Exception
e) {
e.printStackTrace();
}
}
}
class DirFilter
implements FilenameFilter {
Stringafn;
DirFilter(Stringafn){
this.afn =
afn;
}
public
boolean accept(File
dir, String name) {
// Strip path information:
Stringf =
new File(name).getName();
return
f.indexOf(afn) != -1;
}
} /// :~
l 运行
.classpath
.project
.settings
bin
src
DirFilter 类“实现”了interface FilenameFilter。
以下让我们看看FilenameFilter接口有多么简单:
public interface FilenameFilter {
boolean accept(文件文件夹, 字串名);
}
它指出这样的类型的全部对象都提供了一个名为 accept()的方法。之所以要创建这样的一个类,背后的全部原因就是把accept()方法提供给 list()方法。使list()可以“回调”accept(),从而推断应将哪些文件名称包括到列表中。因此,通常将这样的技术称为“回调”,有时也称为“算子”(也就是说,DirFilter 是一个算子,由于它唯一的作用就是容纳一个方法)。
由于 list()採用一个 FilenameFilter 对象作为自己的自变量使用。所以我们能传递实现了FilenameFilter
的不论什么类的一个对象,用它决定(甚至在运行期)list()方法的行为方式。
回调的目的是在代码的行为上提供更大的灵活性。
通过DirFilter。我们看出虽然一个“接口”仅仅包括了一系列方法。但并不局限于仅仅能写那些方法(可是。至少必须提供一个接口内全部方法的定义。
在这样的情况下,DirFilter 构建器也会创建)。accept()方法必须接纳一个 File 对象,用它指示用于寻找一个特定文件的文件夹;并接纳一个String,当中包括了要寻找之文件的名字。可决定使用或忽略这两个參数之中的一个。但有时至少要使用文件名称。
记住list()方法准备为文件夹对象中的每一个文件名称调用accept(),核实哪个应包括在内——详细由
accept()返回的“布尔”结果决定。
为确定我们操作的仅仅是文件名称,当中没有包括路径信息,必须採用String对象,并在它的外部创建一个File 对象。
然后调用 getName()。它的作用是去除全部路径信息(採用与平台无关的方式)。随后,accept()用String 类的indexOf()方法检查文件名称内部是否存在搜索字串"afn"。
若在字串内找到 afn,那么返回值就是afn 的起点索引;但假如没有找到,返回值就是-1。
注意这仅仅是一个简单的字串搜索样例。未使用常见的表达式“通配符”方案,比方"fo?.b?r*";这样的方案更难实现。
list()方法返回的是一个数组。
可查询这个数组的长度,然后在当中遍历,选定数组元素。
与 C 和C++的相似行为相比,这样的于方法内外方便游历数组的行为无疑是一个显著的进步。
1.2 匿名内部类
l 代码例如以下
用一个匿名内部类来重写显得非常理想。首先创建了一个filter()方法,它返回指向FilenameFilter 的一个句柄:
import java.io.*;
public
classDirList2 {
public
static FilenameFilter filter(final String
afn) {
// Creation of anonymous inner class:
return
new FilenameFilter() {
Stringfn =
afn;
public
boolean accept(File
dir, String n) {
// Strip path information:
Stringf =
new File(n).getName();
return
f.indexOf(fn) != -1;
}
};// End of anonymous inner class
}
public
static void main(String[]
args) {
try {
Filepath=
newFile(".");
String[]list;
if (args.length == 0)
list = path.list();
else
list = path.list(filter(args[0]));
for (int
i = 0; i <
list.length;
i++)
System.out.println(list[i]);
}catch(Exception
e) {
e.printStackTrace();
}
}
} /// :~
l 运行
.classpath
.project
.settings
bin
src
注意filter()的自变量必须是final。
这一点是匿名内部类要求的,使其能使用来自本身作用域以外的一个对象。
之所以觉得这样做更好,是由于FilenameFilter 类如今同DirList2 紧密地结合在一起。然而,我们可採取进一步的操作,将匿名内部类定义成list()的一个參数,使其显得更加精简。
l 代码2
import java.io.*;
public
classDirList3 {
public
static void main(final String[]
args) {
try {
Filepath=
newFile(".");
String[]list;
if (args.length == 0)
list = path.list();
else
list = path.list(new FilenameFilter() {
public
boolean accept(File
dir, String n) {
Stringf =
new File(n).getName();
return
f.indexOf(args[0]) != -1;
}
});
for (int
i = 0; i <
list.length;
i++)
System.out.println(list[i]);
}catch(Exception
e) {
e.printStackTrace();
}
}
} /// :~
l 运行
.classpath
.project
.settings
bin
src
main()如今的自变量是 final。由于匿名内部类直接使用args[0]。
这展示了怎样利用匿名内部类高速创建精简的类。以便解决一些复杂的问题。由于Java 中的全部东西都与类有关,所以它无疑是一种相当实用的编码技术。它的一个优点是将特定的问题隔离在一个地方统一解决。但在还有一方面,这样生成的代码不是十分easy阅读,所以使用时必须谨慎。
1.3 顺序文件夹列表
常常都须要文件名称以排好序的方式提供。由于 Java 1.0 和Java 1.1 都没有提供对排序的支持(从 Java 1.2開始提供),用创建的 SortVector将这一能力直接添加自己的程序。
l 代码
import java.io.*;
public
classSortedDirList {
private File
path;
private String[]
list;
public SortedDirList(final String
afn) {
path = new File(".");
if (afn ==
null)
list = path.list();
else
list = path.list(new FilenameFilter() {
public
boolean accept(File
dir, String n) {
Stringf =
new File(n).getName();
return
f.indexOf(afn) != -1;
}
});
sort();
}
void print() {
for (int
i = 0; i <
list.length;
i++)
System.out.println(list[i]);
}
private
void sort() {
StrSortVectorsv =
new StrSortVector();
for (int
i = 0; i <
list.length;
i++)
sv.addElement(list[i]);
// The first time an element is pulled from
// the StrSortVector the list is sorted:
for (int
i = 0; i <
list.length;
i++)
list[i] = sv.elementAt(i);
}
// Test it:
public
static void main(String[]
args) {
SortedDirListsd;
if (args.length == 0)
sd = new SortedDirList(null);
else
sd = new SortedDirList(args[0]);
sd.print();
}
} /// :~
l 运行
.classpath
.project
.settings
bin
src
这里进行了另外少许改进。不再是将path(路径)和 list(列表)创建为main()的本地变量,它们变成了类的成员。使它们的值能在对象“生存”期间方便地訪问。其实。main()如今仅仅是对类进行測试的一种方式。
一旦列表创建完毕,类的构建器就会自己主动開始对列表进行排序。
这样的排序不要求区分大写和小写,所以终于不会得到一组全部单词都以大写字母开头的列表。跟着是全部以小写字母开头的列表。
然而,我们注意到在以同样字母开头的一组文件名称中。大写字母是排在前面的——这对标准的排序来说仍是一种不合格的行为。
Java 1.2 已成功攻克了这个问题。
1.4 检查与创建文件夹
File 类并不仅仅是对现有文件夹路径、文件或者文件组的一个表示。亦可用一个 File 对象新建一个文件夹,甚至创建一个完整的文件夹路径——假如它尚不存在的话。
亦可用它了解文件的属性(长度、上一次改动日期、读/写属性等),检查一个File 对象究竟代表一个文件还是一个文件夹。以及删除一个文件等等。下列程序完整展示了怎样运用File 类剩下的这些方法:
l 代码
import java.io.*;
public
classMakeDirectories {
private
final static String
usage =
"Usage:MakeDirectories path1 ...\n" + "Creates each path\n"
+"Usage:MakeDirectories -d path1...\n" +
"Deleteseach path\n" +
"Usage:MakeDirectories -r path1 path2\n"
+"Renames from path1 to path2\n";
private
static void usage() {
System.err.println(usage);
System.exit(1);
}
private
static void fileData(File
f) {
System.out.println("Absolute path: "+
f.getAbsolutePath()+
"\n Can read: " + f.canRead() +
"\n Can write: "
+f.canWrite() +
"\n getName: "+ f.getName() +
"\n getParent: "+
f.getParent() + "\n getPath: "
+f.getPath() +
"\n length: "+ f.length() +
"\n lastModified: "+
f.lastModified());
if (f.isFile())
System.out.println("it's a file");
else
if (f.isDirectory())
System.out.println("it's a directory");
}
public
static void main(String[]
args) {
if (args.length < 1)
usage();
if (args[0].equals("-r")) {
if (args.length != 3)
usage();
Fileold=
newFile(args[1]),rname=
newFile(args[2]);
old.renameTo(rname);
fileData(old);
fileData(rname);
return;
// Exit main
}
int
count = 0;
boolean
del = false;
if (args[0].equals("-d")) {
count++;
del = true;
}
for (;
count < args.length;
count++) {
Filef =
new File(args[count]);
if (f.exists()) {
System.out.println(f +
" exists");
if (del) {
System.out.println("deleting..."+
f);
f.delete();
}
}else{
// Doesn't exist
if (!del) {
f.mkdirs();
System.out.println("created "+
f);
}
}
fileData(f);
}
}
} /// :~
l 运行
Usage:MakeDirectories path1 ...
Creates each path
Usage:MakeDirectories -d path1 ...
Deletes each path
Usage:MakeDirectories -r path1 path2
Renames from path1 to path2
加上运行參数:-rtest1.txt test2.txt
然后在文件夹中添加test1.txt文件,运行后
Absolute path: F:\java_test\test1.txt
Can read: false
Can write: false
getName: test1.txt
getParent: null
getPath: test1.txt
length: 0
lastModified: 0
Absolute path: F:\java_test\test2.txt
Can read: true
Can write: true
getName: test2.txt
getParent: null
getPath: test2.txt
length: 0
lastModified: 1460890496589
it's a file
在fileData()中。可看到应用了各种文件调查方法来显示与文件或文件夹路径有关的信息。
main()应用的第一个方法是 renameTo(),利用它可以重命名(或移动)一个文件至一个全新的路径(该路径由參数决定),它属于还有一个File 对象。这也适用于不论什么长度的文件夹。
若试验上述程序。就可发现自己能制作随意复杂程度的一个文件夹路径,由于mkdirs()会帮我们完毕全部工作。在Java 1.0 中,-d标志报告文件夹虽然已被删除,但它依旧存在。但在 Java 1.1 中,文件夹会被实际删除。
2. 附SortVector.java
import java.util.*;
public
classSortVector extends
Vector {
private Compare
compare; // To hold the callback
public SortVector(Compare
comp) {
compare = comp;
}
public
void sort() {
quickSort(0,size() - 1);
}
private
void quickSort(int
left, int
right) {
if (right >
left) {
Objecto1 = elementAt(right);
int
i = left - 1;
int
j = right;
while (true) {
while (compare.lessThan(elementAt(++i),
o1))
;
while (j > 0)
if (compare.lessThanOrEqual(elementAt(--j),
o1))
break;
// out of while
if (i >=
j)
break;
swap(i,
j);
}
swap(i,
right);
quickSort(left,
i - 1);
quickSort(i + 1,
right);
}
}
private
void swap(int
loc1, int
loc2) {
Objecttmp= elementAt(loc1);
setElementAt(elementAt(loc2),
loc1);
setElementAt(tmp,
loc2);
}
} /// :~
3. 附StrSortVector.java
import java.util.*;
interface Compare {
boolean lessThan(Object
lhs, Object rhs);
boolean lessThanOrEqual(Object
lhs, Object rhs);
} /// :~
public
classStrSortVector{
private SortVector
v = new SortVector(
// Anonymous inner class:
new Compare() {
public
boolean lessThan(Object
l, Object r) {
return ((String)
l).toLowerCase().compareTo(((String)r).toLowerCase())< 0;
}
public
boolean lessThanOrEqual(Object
l, Object r) {
return ((String)
l).toLowerCase().compareTo(((String)r).toLowerCase())<= 0;
}
});
private
boolean sorted =
false;
public
void addElement(String
s) {
v.addElement(s);
sorted = false;
}
public String elementAt(int
index) {
if (!sorted) {
v.sort();
sorted = true;
}
return (String)
v.elementAt(index);
}
public
Enumerationelements() {
if (!sorted) {
v.sort();
sorted = true;
}
return
v.elements();
}
// Test it:
public
static void main(String[]
args) {
StrSortVector sv = new
StrSortVector();
sv.addElement("d");
sv.addElement("A");
sv.addElement("C");
sv.addElement("c");
sv.addElement("b");
sv.addElement("B");
sv.addElement("D");
sv.addElement("a");
Enumeratione =
sv.elements();
while (e.hasMoreElements())
System.out.println(e.nextElement());
}
} /// :~
33.JAVA编程思想——JAVA IO File类的更多相关文章
- java编程思想-java IO系统
一.输入和输出 编程语言的I/O类库中常使用流这个抽象概念,它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象."流"屏蔽了实际的I/O设备中处理数据的细节. J ...
- 《Java编程思想》读书笔记-类与对象
欢迎各位读者关注我的微信公众号,共同探讨Java相关技术.生命不止,学习不休! 也许你慢慢地对程序有了这样的认识:程序只是一些列带有方法的对象的组合,这些方法以其它对象为参数,可在任何地方返回,并发送 ...
- java编程思想-java中的并发(二)
二.共享受限资源 有了并发就可以同时做多件事情了.但是,两个或多个线程彼此互相干涉的问题也就出现了.如果不防范这种冲突,就可能发生两个线程同时试图访问同一个银行账户,或向同一个打印机打印,改变同一个值 ...
- java编程思想-java中的并发(一)
一.基本的线程机制 并发编程使我们可以将程序划分为多个分离的.独立运行的任务.通过使用多线程机制,这些独立任务中的每一个都将由执行线程来驱动. 线程模型为编程带来了便利,它简化了在单一程序中同时jia ...
- java编程思想-java中的并发(四)
五. 新类库中的构件 Java SE5的java.util.concurrent引入了大量设计用来解决并发问题的新类.学习使用它们将有助于编写出更加简单而强壮的并发程序. 1. CountDownLa ...
- java编程思想——java IO系统
一.什么是IO io在本质上是单个字节的移动.而流能够说是字节移动的载体和方式,它不停的向目标处移动数据.我们要做的就是依据流的方向从流中读取数据或者向流中写入数据. 二.java中支持IO操作的库类 ...
- Java编程思想学习(五) 复用类
1.继承与组合 复用类的方法有两种:继承与组合.继承就不多说了,组合就是直接在类中new一个对象. 数组也是对象,使用数组也是组合的一种. 2.初始化基类 当创建一个导出类的对象时,该对象包含一个基类 ...
- Java编程思想学习笔记——复用类
前言 复用代码是Java众多引人注目的功能之一. 达到复用代码的方法有: 组合:新的类由现有类的对象所组成.(复用现有代码的功能,而非它的形式) 继承:按照现有类的类型组建新类.(不改变现有类的形式, ...
- 《 Java 编程思想》CH07 复用类
复用代码是 Java 众多引人注目的功能之一. Java 可以通过创建类来复用代码,要在使用类的时候不破坏现有代码,有两种方式: 组合:在新的类中使用现有类的对象. 继承:按照现有类的类型来创建新类, ...
随机推荐
- a标签中javascript和void
<body> <a href="javascript:;">点了无反应</a> <a href="javascript:void ...
- python--线程的其他方法
一 . current_thread的用法 import threading import time from threading import Thread, current_thread def ...
- 安装tesserocr的步骤和报错RuntimeError: Failed to init API, possibly an invalid tessdata path解决办法
1,首先下载合适的tesseract-ocr的版本 2,然后安装到这一步注意要勾选这一项来安装OCR识别支持的语言包,这样OCR就可以识别多国语言,然后就可以一直点击下一步完成安装. 3,安装tess ...
- PyCharm学习笔记(一) 界面配置
通过Ctrl+鼠标滚轮调整字体大小 设置代码区默认字体及大小 设置调试区的字体大小 设置代码风格:如Tab缩进 定义Python模板文件 # @Time : ${DATE} ${TIME} # @ ...
- include/autoconfig.mk
把autoconfig.mk和/include/configs/ $(obj)include/autoconf.mk.dep: $(obj)include/config.h include/commo ...
- PAT Basic 1039
1039 到底买不买 小红想买些珠子做一串自己喜欢的珠串.卖珠子的摊主有很多串五颜六色的珠串,但是不肯把任何一串拆散了卖.于是小红要你帮忙判断一下,某串珠子里是否包含了全部自己想要的珠子?如果是,那么 ...
- angularJs模块ui-router之多视图
可以给ui-view指定名称,这样一个模板中就可以有多个ui-view.假设您有一个应用,需要动态填充graph.table data和filters,像下面这样: 当您需要使用多视图时,需要用到状态 ...
- Spoj-BGSHOOT
The problem is about Mr.BG who is a great hunter. Today he has gone to a dense forest for hunting an ...
- 洛谷 [P3205] 合唱队
区间DP 手动模拟一下,我们发现本题就是一个左右加数的区间DP #include <iostream> #include <cstdio> #include <cstri ...
- 【HDOJ5952】Counting Cliques(团,dfs)
题意:给定一张n点m边的图,求大小为S的团的个数 N ≤ 100,M ≤ 1000,2 ≤ S ≤ 10,保证点的度不超过20 思路:dfs 因为每个点可能不止属于一个极大团,所以不能求出极大团然后计 ...