Directory类系
综述:Directory类系可以被理解成是一个文件夹,它提供些对文件夹内容及本身的一些操作。比如:
1.建立/读取/删除/重命名文件;
2.复制文件夹;
3.查寻是否存在某文件;
4.设置/获取某文件最后访问时间;
5.查寻文件夹大小;
6.查看文件列表
1.Directory类系层次图

2. 部分代码说明
Directory类
Directory是所有文件夹类的父类。它规定了所有子类必须提供的操作,但它本身只实现了部分,其中比较重要的就是文件夹间的拷贝操作copy()方法。
1
public static void copy(Directory src, Directory dest, boolean closeDirSrc)
2
throws IOException
{ // 文件夹之间的的复制
3
final String[] files = src.list(); // 获取源文件夹文件列表
4
5
if (files == null)
6
throw new IOException("cannot read directory " + src
7
+ ": list() returned null");
8
9
byte[] buf = new byte[BufferedIndexOutput.BUFFER_SIZE]; // 建立缓冲buf
10
for (int i = 0; i < files.length; i++)
{ // 对每个文件进行复制操作
11
IndexOutput os = null; // 写通道
12
IndexInput is = null; // 读通道
13
try
{
14
// create file in dest directory
15
os = dest.createOutput(files[i]); // 创建对file[i]的写通道
16
// read current file
17
is = src.openInput(files[i]); // 读通道
18
// and copy to dest directory
19
long len = is.length(); // 文件总长度
20
long readCount = 0; // 已读取长度
21
while (readCount < len)
{ // 循环读取文件数据
22
int toRead = readCount + BufferedIndexOutput.BUFFER_SIZE > len ? (int) (len - readCount)
23
: BufferedIndexOutput.BUFFER_SIZE; // 实际一次读取长度
24
is.readBytes(buf, 0, toRead); // 读取
25
os.writeBytes(buf, toRead); // 写入
26
readCount += toRead; // 记录已写入数量
27
}
28
} finally
{ // 关闭操作
29
// graceful cleanup
30
try
{
31
if (os != null)
32
os.close();
33
} finally
{
34
if (is != null)
35
is.close();
36
}
37
}
38
}
39
if (closeDirSrc)
40
src.close();
41
}
FSDirectory类
FSDirectory是基于硬盘的Directory。
FSDirectory中最重要的实例生成方法就是getFSDirectory(File, LockFactory)了。
1
public static FSDirectory getDirectory(File file, LockFactory lockFactory)
2
throws IOException
{
3
file = new File(file.getCanonicalPath()); // 获得file
4
5
if (file.exists() && !file.isDirectory()) // file存在但不是文件夹
6
throw new IOException(file + " not a directory");
7
8
if (!file.exists()) // file不存在
9
if (!file.mkdirs()) // 试图创建file文件夹,失败则抛出异常
10
throw new IOException("Cannot create directory: " + file);
11
12
FSDirectory dir;
13
synchronized (DIRECTORIES)
{ // 同步访问DIRECTORIES
14
dir = (FSDirectory) DIRECTORIES.get(file); // 试图从DIRECTORIES中获取
15
if (dir == null)
{ // 获取失败
16
try
{
17
dir = (FSDirectory) IMPL.newInstance(); // 创建一个新实例
18
} catch (Exception e)
{
19
throw new RuntimeException(
20
"cannot load FSDirectory class: " + e.toString(), e);
21
}
22
dir.init(file, lockFactory); // 初始化dir
23
DIRECTORIES.put(file, dir); // 把dir放入DIRECTORIES
24
} else
{
25
// Catch the case where a Directory is pulled from the cache,
26
// but has a
27
// different LockFactory instance.
28
if (lockFactory != null && lockFactory != dir.getLockFactory())
{
29
throw new IOException(
30
"Directory was previously created with a different LockFactory instance; please pass null as the lockFactory instance and use setLockFactory to change it");
31
}
32
}
33
}
34
synchronized (dir)
{
35
dir.refCount++; // refCount++
36
}
37
return dir;
38
}
init(File, LockFactory)为初始化FSDirectory实例的方法,只能内部调用。
1
private void init(File path, LockFactory lockFactory) throws IOException
{
2
3
// Set up lockFactory with cascaded defaults: if an instance was passed
4
// in,
5
// use that; else if locks are disabled, use NoLockFactory; else if the
6
// system property org.apache.lucene.store.FSDirectoryLockFactoryClass
7
// is set,
8
// instantiate that; else, use SimpleFSLockFactory:
9
10
directory = path;
11
12
boolean doClearLockID = false;
13
14
if (lockFactory == null)
{
15
16
if (disableLocks)
{
17
// Locks are disabled:
18
lockFactory = NoLockFactory.getNoLockFactory();
19
} else
{
20
String lockClassName = System
21
.getProperty("org.apache.lucene.store.FSDirectoryLockFactoryClass");
22
23
if (lockClassName != null && !lockClassName.equals(""))
{ // 系统设置了默认lockFactory
24
Class c;
25
26
try
{
27
c = Class.forName(lockClassName);
28
} catch (ClassNotFoundException e)
{
29
throw new IOException("unable to find LockClass "
30
+ lockClassName);
31
}
32
33
try
{
34
lockFactory = (LockFactory) c.newInstance(); // 实例化系统默认的lockFactory
35
} catch (IllegalAccessException e)
{
36
throw new IOException(
37
"IllegalAccessException when instantiating LockClass "
38
+ lockClassName);
39
} catch (InstantiationException e)
{
40
throw new IOException(
41
"InstantiationException when instantiating LockClass "
42
+ lockClassName);
43
} catch (ClassCastException e)
{
44
throw new IOException("unable to cast LockClass "
45
+ lockClassName + " instance to a LockFactory");
46
}
47
48
if (lockFactory instanceof NativeFSLockFactory)
{ // 根据lockFactory的类型各自调用setLockDir()
49
((NativeFSLockFactory) lockFactory).setLockDir(path);
50
} else if (lockFactory instanceof SimpleFSLockFactory)
{
51
((SimpleFSLockFactory) lockFactory).setLockDir(path);
52
}
53
} else
{ // 使用lucene默认的lockFactory: SimpleFSLockFactory
54
// Our default lock is SimpleFSLockFactory;
55
// default lockDir is our index directory:
56
lockFactory = new SimpleFSLockFactory(path);
57
doClearLockID = true; // 设置为true, 不懂!!!!!!
58
}
59
}
60
}
61
62
setLockFactory(lockFactory); // 设置lockFactory
63
64
if (doClearLockID)
{
65
// Clear the prefix because write.lock will be
66
// stored in our directory:
67
lockFactory.setLockPrefix(null);
68
}
69
}
MMapDirectory类
MMapDirectory是FSDirectory的子类,它重写了FSDirectory的openInput()方法。他们的区别是,在读取文件时,FSDirectory在底层用BufferedIndexInput(把文件部分读入内存),而MMapDirectory则用MMapDirectory/MultiMMapDirectory(把文件一次性全部读入内存)。
openInput(String)功能为打开某文件的读取通道。
1
public IndexInput openInput(String name) throws IOException
{
2
File f = new File(getFile(), name);
3
RandomAccessFile raf = new RandomAccessFile(f, "r");
4
try
{ // 根据文件的大小选择适当的IndexInput
5
return (raf.length() <= MAX_BBUF) ? (IndexInput) new MMapIndexInput(
6
raf)
7
: (IndexInput) new MultiMMapIndexInput(raf, MAX_BBUF);
8
} finally
{
9
raf.close();
10
}
11
}
RAMDirectory类
RAMDirectory与FSDirectory不同,它是基于内存的。它在内存中划出一个区域,用来存放文件,在性能上肯定要比FSDirectory快的多。当然它也有它的局限性,比如,文件过大,内存小放不下,呵呵。
RAMDirectory里定义了变量:HashMap fileMap = new HashMap()用来存放文件名及与之对应得文件在内存中的指针。还有一个变量long sizeInBytes:文件夹总字节数。
当通过Directory来创建RAMDirectory时,RAMDirectory需要把Directory中的数据拷贝到RAMDirectory中来。
1
private RAMDirectory(Directory dir, boolean closeDir) throws IOException
{
2
this();
3
Directory.copy(dir, this, closeDir); // 拷贝数据
4
}
list()用来列出RAMDirectory中的所有文件,也就是fileMap中的所有文件名。
1
public synchronized final String[] list()
{ // 列出fileMap中的文件清单
2
ensureOpen(); // 确保fileMap不为空
3
Set fileNames = fileMap.keySet(); // 返回文件名set
4
String[] result = new String[fileNames.size()];
5
int i = 0;
6
Iterator it = fileNames.iterator();
7
while (it.hasNext())
8
// 遍历文件名
9
result[i++] = (String) it.next();
10
return result; // 返回文件名数组
11
}
在查询某文件是否存在时,只需要到fileMap中看下对应的文件名是否存在。
1
public final boolean fileExists(String name)
{ // 查询是否存在名为name的文件
2
ensureOpen();
3
RAMFile file;
4
synchronized (this)
{
5
file = (RAMFile) fileMap.get(name); // 从fileMap中取name文件
6
}
7
// file != null 说明文件存在;反之,不存在
8
return file != null;
9
}
touchFile(String)功能是修改给定文件名的文件的最近修改时间。方法本身并不是同步方法,因此在方法体内部需要考虑同步的问题。
1
public void touchFile(String name) throws IOException
{
2
// 修设置最近修改时间为当前时间
3
ensureOpen();
4
RAMFile file;
5
synchronized (this)
{
6
file = (RAMFile) fileMap.get(name);
7
}
8
if (file == null)
9
throw new FileNotFoundException(name);
10
11
long ts2, ts1 = System.currentTimeMillis();
12
do
{ // 这个循环的用意是什么?????有人告诉我不????
13
try
{
14
Thread.sleep(0, 1); // 睡 1ns
15
} catch (InterruptedException e)
{
16
}
17
ts2 = System.currentTimeMillis(); // 获取当前时间
18
} while (ts1 == ts2);
19
20
file.setLastModified(ts2); // 同步修改最近修改时间
21
}
deleteFile(String)功能为删除给定文件名的文件,不存在则抛出异常。
1
public synchronized void deleteFile(String name) throws IOException
{ // 删除name文件
2
ensureOpen();
3
RAMFile file = (RAMFile) fileMap.get(name);
4
if (file != null)
{
5
fileMap.remove(name); // 从fileMap中删除此文件,也就是删掉该文件的相关记录:名字和buffer地址
6
file.directory = null; // 设置file的所属文件夹为null,即它不再属于任何文件夹
7
sizeInBytes -= file.sizeInBytes; // updates to RAMFile.sizeInBytes synchronized on directory
8
} else
9
throw new FileNotFoundException(name);
10
}
createOutput()创建一个新文件并返回其写通道。若同名文件已存在,则删除之。

public IndexOutput createOutput(String name) throws IOException
{ // 新建给定名字的文件并返回它的写通道
ensureOpen(); // 确保fileMap不为null
RAMFile file = new RAMFile(this); // 创建一个内存文件,参数为当前文件夹

synchronized (this)
{ // 获取同步锁
RAMFile existing = (RAMFile) fileMap.get(name);

if (existing != null)
{ // 存在同名文件,则删除之
sizeInBytes -= existing.sizeInBytes; // 更改文件夹大小
existing.directory = null; // 设置其directory为null
}
fileMap.put(name, file);
}
return new RAMOutputStream(file); // 返回该文件的写通道
}