文件操作是Java I/O中常用且重要的一类操作,数据在磁盘中的唯一最小描述就是文件,上层应用程序只能通过文件来操作磁盘上的数据。在Java中,文件通过File类来描述,表示一个真实存在的文件或者是一个包含多个文件的目录。Java.io.File类能够完成对文件的基本操作,如创建、删除等操作,也可以完成对目录的创建这些操作。
首先来看File中两个重要的变量:
private String path; private transient int prefixLength;
在File中有多个构造函数,但是不难发现这些构造函数会有一个共同点,那就是为如上的两个变量赋值,如:
public File(String pathname) {
if (pathname == null) {
throw new NullPointerException();
}
this.path = fs.normalize(pathname);
this.prefixLength = fs.prefixLength(this.path);
}normalize()方法主要的作用是规范路径的写法,所以String path="D:\\a.cmd.txt"、String path="/D:/a.cmd.txt"和String path="D:\\\\\\\a.cmd.txt"都是合法的。
prefixLength是由transient关键字修饰,为了安全问题,所以并不希望把类里面所有的东西都能存储(因为那样,别人可以通过序列化知道类里面的内容),即不会随类一起序列化到本地,所以当还原后,这个关键字定义的变量也就不再存在。当调用normalize()方法将路径规范化后,调用prefixLength()方法计算前缀长度,方便计算路径的父路径或者计算路径中包含的文件名等操作。如:
public String getParent() {
int index = path.lastIndexOf(separatorChar);
if (index < prefixLength) {
if ((prefixLength > 0) && (path.length() > prefixLength))
return path.substring(0, prefixLength);
return null;
}
return path.substring(0, index);
}
测试如下:
String path="D:\\\\a/cmd.txt";
File f=new File(path);
System.out.println("path="+f.getPath());// path=D:\a\cmd.txt
System.out.println(f.getName());// cmd.txt
System.out.println(f.getParent()); // D:\a 可以看到,路径被正确规范化,并且正确得到了文件名和父路径等信息。其实对于文件的操作非常多,有兴趣的可以自己根据如下的一些例子去查看源代码,下面来介绍一些常见的操作。
1、列出指定目录下的文件或目录
//只能列出一层目录
public class ListMyDir {
public static void main(String[] args) {
String fileName = "C:" + File.separator + "data";
File f = new File(fileName);
File[] fs = f.listFiles();
for (int i = 0; i < fs.length; i++) {
System.out.println(fs[i].getName());
}
}
} public void print(File f) {
if (f != null) {
if (f.isDirectory()) {
File[] fileArray = f.listFiles();
if (fileArray != null) {
for (int i = 0; i < fileArray.length; i++) {
print(fileArray[i]);// 递归调用
}
}
} else {
System.out.println(f);
}
}
}
public void readFile(String fileName) {
File srcFile = new File(fileName);
InputStream in = null;
try {
in = new FileInputStream(srcFile);
byte[] b = new byte[(int) srcFile.length()];
for (int i = 0; i < b.length; i++) {
b[i] = (byte) in.read();
}
System.out.println(new String(b));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
in = null;
}
} catch (Exception e) { }
}
}
public void writeWithByte() {
String fileName = "D:" + File.separator + "hello.txt";
OutputStream out = null;
File f = new File(fileName);
try {
out = new FileOutputStream(f, true);
String str = " [Publicity ministry of ShangHai Municipal committee of CPC]";
byte[] b = str.getBytes();
out.write(b);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
out = null;
}
} catch (Exception e) { }
}
}
public void writeWithByteArray() {
String fileName = "D:" + File.separator + "hello.txt";
OutputStream out = null;
File f = new File(fileName);
try {
out = new FileOutputStream(f, true);
String str = " [hello with byte yi ge ge xie]";
byte[] b = str.getBytes();
for (int i = 0; i < b.length; i++) {
out.write(b[i]);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
out = null;
}
} catch (Exception e) { }
}
} 5、实现文件的复制
public void copy(String src, String des) {
File srcFile = new File(src);
File desFile = new File(des);
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(srcFile);
out = new FileOutputStream(desFile);
byte[] b = new byte[(int) srcFile.length()];
for (int i = 0; i < b.length; i++) {
b[i] = (byte) in.read();
}
out.write(b);
System.out.println("copied [" + srcFile.getName() + "] with "
+ srcFile.length());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
out = null;
}
} catch (Exception e) { }
try {
if (in != null) {
in.close();
in = null;
}
} catch (Exception e) { }
}
}或者使用缓存实现文件的复制,如下:
public void copy(String src, String des) {
File srcFile = new File(src);
File desFile = new File(des);
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
try {
bin = new BufferedInputStream(new FileInputStream(srcFile));
bout = new BufferedOutputStream(new FileOutputStream(desFile));
byte[] b = new byte[1024];
while (bin.read(b) != -1) {
bout.write(b);
}
bout.flush();
System.out.println("copied [" + srcFile.getName() + "] with "
+ srcFile.length());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bout != null) {
bout.close();
bout = null;
}
} catch (Exception e) { }
try {
if (bin != null) {
bin.close();
bin = null;
}
} catch (Exception e) { }
}
}
可能在写入或读取文件的时候,通常还需要更加灵活的操作,如向一个文件中的开始处添加字符串,读取一个文件末尾的指定数量的字符等等,这时候就需要通过RandomAccessFile类中的方法进行操作了。这主要是通过一个类似于数组指针来实现的,可以将一个文件中存储的所有内容放到一个数组中,然后通过指定来读取到特定的部分,常见的这类方法如:
seek(long pos) // Sets the file-pointer offset, measured from the beginning of this file, at which the next read or write occurs.
getFilePointer() // Returns the current offset in this file.可以看到,能够灵活地操作file-pointer来读取或写入内容。
举个例子:
public class RandomAccess {
public void writeToFile() {
String fileName = "D:" + File.separator + "hello.txt";
RandomAccessFile randomIO = null;
try {
File f = new File(fileName);
randomIO = new RandomAccessFile(f, "rw");
randomIO.writeBytes("asdsad");
randomIO.writeInt(12);
randomIO.writeBoolean(true);
randomIO.writeChar(‘A‘);
randomIO.writeFloat(1.21f);
randomIO.writeDouble(12.123);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (randomIO != null) {
randomIO.close();
randomIO = null;
}
} catch (Exception e) { }
}
}
public static void main(String[] args) {
RandomAccess randomA = new RandomAccess();
randomA.writeToFile();
}
}
传统的文件操作只能实现一些简单的输入、输出、创建、删除等操作,如果要进行更加复杂的操作就无能为力了。例如,读取一个非常大的日志文件会造成I/O阻塞、对文件的属性支持力度不够、不支持目录树导航的类或方法等等,而这些操作往往对一个文件的操作来说非常重要,所以Java 7提供了亲的I/O API,即NIO.2。
由于新的NIO中文件或目录使用的对象为Path,所以为了兼容新的类,File中提供了toPath()方法,源代码如下:
public Path toPath() {// 在Java1.7中,主要对文件的操作就是Path对象,提供了一个兼容
Path result = filePath;
if (result == null) {
synchronized (this) {
result = filePath;
if (result == null) {
result = FileSystems.getDefault().getPath(path);
filePath = result;
}
}
}
return result;
}可以直接将已经存在的File对象转换为NIO中的Path对象进行操作。
seek(long pos)
Sets the file-pointer offset, measured from the beginning of this file, at which the next read or write occurs.
|
原文:http://blog.csdn.net/mazhimazh/article/details/18790847