文件操作开发指南
1 修改历史
版本
|
修改历史
|
作者
|
描述
|
开发时间(h)
|
0.1
|
2007-8-13
|
LevinSoft
|
创建文档得基本结构、基本流程
|
2
|
2 介绍
本文是对文件相关操作的开发指南,介绍了文件的基本概念、操作步骤、api的使用等,采用了具体代码作为实例。其中大部分基础概念都是直接引用的是JDK的文档,对相关api使用方式上进行了整理和分类。
对跨系统操作文件提出一些方法和技巧,最后也介绍一些开源文件api项目和参考资源。
3 基本概念
文件和目录路径名的抽象表示形式。
用户界面和操作系统使用与系统相关的路径名字符串 来命名文件和目录。此类呈现分层路径名的一个抽象的、与系统无关的视图。抽象路径名 有两个组件:
- 一个可选的与系统有关的前缀 字符串,比如盘符,"/" 表示 UNIX 中的根目录,"////" 表示 Microsoft Windows UNC 路径名,以及
- 零个或更多字符串名称 的序列。
除了最后一个,抽象路径名中的每个名称代表一个目录;最后一个名称既可以代表目录,也可以代表文件。空的 抽象路径名没有前缀和名称序列。
路径名字符串与抽象路径名之间的转换与系统有关。将抽象路径名转换为路径名字符串时,每个名称与下一个名称之间由单个默认分隔符字符 隔开。默认名称分隔符由系统属性 file.separator定义,也可以从此类的公共静态字段 separator和 separatorChar中得到。将路径名字符串转换为抽象路径名时,可以使用默认名称分隔符或者受基础系统支持的其他任何名称分隔符来分隔其中的名称。
无论是抽象路径名还是字符串路径名,都可以是绝对 路径名或相对 路径名。绝对路径名是完整的路径名,不需要任何其他信息就可以定位自身表示的文件。相反,相对路径名必须使用来自其他路径名的信息进行解释。默认情况下,java.io包中的类总是根据当前用户目录来分析相对路径名。此目录由系统属性 user.dir指定,通常是 Java 虚拟机的调用目录。
前缀的概念用于处理 UNIX 平台的根目录,以及 Microsoft Windows 平台上的盘符、根目录和 UNC 路径名,如下所示:
- 对于 UNIX 平台,绝对路径名的前缀始终是 "/"。相对路径名没有前缀。表示根目录的绝对路径名的前缀为 "/"并且没有名称序列。
- 对于 Microsoft Windows 平台,包含盘符的路径名的前缀由驱动器名和一个 ":"组成:如果路径名是绝对路径名,后面可能跟着 "//"。UNC 路径名的前缀是 "////";主机名和共享名是名称序列中的前两个名称。没有指定驱动器的相对路径名无前缀。
File类的实例是不可变的;也就是说,一旦创建,File对象表示的抽象路径名将永不改变。
4 文件基本操作
4.1 常用类
4.1.1 RandomAccessFile
此类的实例支持对随机存取文件的读取和写入。随机存取文件的行为类似存储在文件系统中的一个大型字节数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机存取文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过
randomAccessFilePointer
方法读取,并通过 seek
方法设置。 通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出
EOFException
(是一种 IOException
)。如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出 IOException
,而不是 EOFException
。需要特别指出的是,如果流已被关闭,则可能抛出 IOException
。 RandomAccessFile file = new RandomAccessFile(file, "rw");
file.seek(0);
4.1.2 BufferedReader
从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取
通常,Reader 所作的每个读取请求都会导致对基础字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。例如,
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
将缓冲指定文件的输入。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。
4.1.3 BufferedWriter
与BufferedReader相反。
BufferedWriter out = new BufferedWriter(new FileWriter("foo.out"));
4.1.4 PrintWriter
向文本输出流打印对象的格式化表示形式。此类实现在
PrintStream
中的所有 print 方法。它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。 与
PrintStream
类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出新行字符时才完成。这些方法使用平台自有的行分隔符概念,而不是新行字符。 此类中的方法不会抛出 I/O 异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用
checkError()
是否出现错误。PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
4.1.5 获得系统属性
SystemUtils是个实用的类,它是apache commons一个api。通过此类,可以获得系统属性,例如:java_home,java版本、一些常量参数等。
4.1.6 文件上传
4.1.6.1 Fileupload类,
它是apache commons一个api,提供了上传一些方法。
4.1.6.2 SmartUpload类
提供了文件上传和下载的功能,来自jspSmartUpload.jar.
SmartUpload smartUpload = new SmartUpload();
smartUpload.initialize(this.servlet.getServletConfig(), request,response);
smartUpload.setContentDisposition(null);
smartUpload.downloadFile(localFile);
4.1.7 WebUtils
是spring中一个工具类。
Miscellaneousutilitiesforwebapplications.Usedbyvariousframeworkclasses.
例如:File tmpDir = WebUtils.getTempDir(servlet.getServletContext());
4.2 装载文件方法
1.通过Class获得文件URL
File source = new File ( filter.getClass().getResource( "Songs.xml" ).randomAccessFile() );
2.通过Class获得java.io.InputStream
ConfigUtils.class.getResourceAsStream(“Song.xml”);
4.3 操作文件实例
4.3.1 导出文件到本地目录
private void exportMessage(StringBuffer stringBuffer,String localDir)
{
File errFile=new File(localDir+SystemUtils.FILE_SEPARATOR+batchId+".txt");
try
{
if(errFile.exists())
{
errFile.delete();
}
errFile.createNewFile();
PrintWriter outPrint = new PrintWriter(new BufferedWriter(new FileWriter(errFile)));
outPrint.println(stringBuffer);
outPrint.flush();
}
catch(IOException e)
{
logger.debug("导出错误文件失败:"+e);
throw new DaoException("导出错误文件失败:" + e.getMessage());
}
}
4.3.2 删除文件和文件夹的方法
private void deleteTempFile(String fileName) {
// 得到临时文件所在的文件夹
File folder = new File(fileName).getParentFile();
if (folder.exists()) {
// 删除文件夹下的所有文件
for (int i = 0; i < folder.listFiles().length; i++) {
File file = folder.listFiles()[i];
if (!file.delete()) {
logger.debug("文件" + file.getName() + "删除失败");
}
}
// 删除文件夹
folder.delete();
}
}
5 操作Ftp上的文件
5.1 常用类包
apache commons 网络包:apache commons-net-1.3.0提供了ftp操作api,其中常用的类有:
1.FtpClient提供了访问ftp server常用的方法,比如:连接、上传、下载等。实例:FtpClient ftpClient =getConnect(path, host, username, password);
5.2 下载文件实例
5.2.1 下载流程
public static void downloadFile(String localeFile, String remoteFile, String path, String host,
String username, String password) throws ServiceException
{
try
{
FtpClient client = getConnect(path, host, username, password);
File file = new File(localeFile);
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
randomAccessFile.seek(0);
TelnetInputStream fget = client.get(remoteFile);
DataInputStream puts = new DataInputStream(fget);
while((int ch = puts.read()) >= 0)
{
randomAccessFile.write(ch);
}
}
catch(FileNotFoundException ex)
{
ex.printStackTrace();
throw new ServiceException("请确认文件是否存在!");
}
catch(IOException ex)
{
ex.printStackTrace();
throw new ServiceException("文件读取异常", ex);
}
finally{
try {
if(fget!=null)
fget.close();
if(randomAccessFile!=null)
randomAccessFile.close();
if(client!=null)
client.closeServer();
} catch (IOException e) {
throw new ServiceException("流关闭异常", e);
}
}
}
5.2.2 推荐使用的API
操作文件,推荐采用 PrintWriter、BufferedWriter、FileWriter包装,简化操作。例如:PrintWriterout =newPrintWriter(newBufferedWriter(newFileWriter("foo.out")));
如果没有缓冲,则每次调用 print() 方法会导致将字符转换为字节,然后立即写入到文件,而这是极其低效的。
6 总结和展望
a) 简单的总结前面知识
b) 今后的提高部分
7 参考资料
1.Apache commons相关的jar包和参考文档。
8 术语和附录