File--java.io
File表示一个抽象路径,简单的理解为可以访问文件系统中的一个文件或者目录.使用File我们可以:
* (1)访问其表示的文件或者目录的属性信息(名字,大小,修改时间等)
* (2)可以操作文件或者目录(创建,删除)
* (3)可以访问一个目录的所有子项,但是不能访问一个文件的数据
绝对路径与相对路径
在使用路径时,通常我们都使用相对路径,因为绝对路径的指向太明确,导致的问题是不可变动的,那么在跨平台时就会出现很多问题.相对目录比较灵活,但是要清楚相对路径时哪里,而相对的路径要基于程序的运行环境而定,都与我们现在使用的eclipse中,运行程序而言,那么其表示的当前目录就时程序所在的项目目录.
* 绝对路径:F:\tts9\workspace\JSD1806_SE\test.txt
* 相对路径:./test.txt
* '.'--->当前目录(eclipse规定程序所在项目的目录-->JSD1806_SE)
常用方法 gerName(),length(),canRead(),canWrite(),isHidden(),getCanonicalFile(),getAbsoluteFile()
File file = new File("./test.txt");
System.out.println("文件名:" + file.getName());// text.txt
System.out.println("字节数(long):" + file.length() + "字节");// 文件的字节量9432个字节(返回值类型为long)
boolean canRead = file.canRead();// 可读
boolean canWrite = file.canWrite();// 可写
boolean hidden = file.isHidden();// 隐藏
System.out.println("可读:" + canRead);
System.out.println("可写:" + canWrite);
System.out.println("隐藏:" + hidden);
System.out.println(file.getCanonicalFile());//规范的文件名
System.out.println(file.getAbsoluteFile());//绝对文件名
创建新文件(File file, !file.exists(),file.creatNewFile())
/*
* 在当前目录下创建一个demo.txt文件
* 1:创建一个File表示该文件
* 2:判断该文件是否存在
* 3:若文件不存在,则创建文件
*/
File file = new File("./demo.txt");
if(!file.exists()){
file.createNewFile();
System.out.println("文件已经创建成功!");
}else {
System.out.println("文件已经存在!");
}
删除文件(File file ,file.exists(),file.delete())
/*
* 将当前目录中的demo.txt文件删除
*/
File file = new File("./demo.txt");
if(file.exists()){
file.delete();
System.out.println("文件已经删除!");
}else {
System.out.println("文件不存在!");
}
创建目录(File dir ,!dir.exists(),dir.mkdir()s)
/*
* 在当前目录中创建一个目录:demo
*/
File dir = new File("demo");//./可以忽略不写,默认当前目录
if(!dir.exists()){
dir.mkdir();
System.out.println("目录创建成功!");
}else{
System.out.println("目录已经存在!");
}
创建多级目录(File dir,!dir.exists() ,dir.mkdirs(),)
/*
* 在当前目录下创建目录:a/b/c/d/e/f
*/
File dir = new File("a/b/c/d/e/f");
if (!dir.exists()) {
dir.mkdirs();
System.out.println("目录创建成功!");
} else {
System.out.println("目录已经存在");
}
删除目录(File dir ,dir.exists(),dir.delete())---->删除目录的前提条件是该目录为空,否则删不了
/*
* 删除demo目录
*/
File dir = new File("demo");
if (dir.exists()) {
dir.delete();
System.out.println("目录已经删除!");
} else {
System.out.println("目录不存在!");
}
访问一个目录中的所有子项(File dir;dir.isDirectory(),dir.listFiles())
/*
* 获取当前目录中的所有子项
* boolean isFile() 判断当前File表示的是否是一个文件
* boolean isDirectory() 判断当前File表示的是否是一个目录
*/
File dir = new File(".");
if (dir.isDirectory()) {
File[] subs = dir.listFiles();
for(int i = 0 ;i < subs.length ;i++){
File sub = subs[i];
System.out.println(sub.getName());
}
}
删除任意给定的文件或目录及其子项====>递归调用,开发中能不用就不用,内存消耗大
/**
* 递归调用
* 所谓递归的现象就是在当前方法内部再次调用当前方法的现象.
* 递归也用来重复执行某个动作,但是鱼for,while不同,他是将整个方法重头再来.
* 递归性能差,并且消耗资源打,如果可以尽量避免使用,递归调用一定时在一个分支
* 结构中被控制的,若方法内部一定再次调用该方法,那么一定是个死循环.
* @param file
*/
private static void delete(File file){//文件或者目录
if(file.isDirectory()){
File[] sub = file.listFiles();
for (int i = 0; i < sub.length; i++) {
File subs = sub[i];
delete(subs);
}
}
file.delete();
}
重载的listFiles(FileFilter filter)传入一个文件过滤器,然后只将该目录中蛮子过滤器要求的子项返回
方法一:自定义类继承FileFilter接口
public class ListFilesDemo2 {
public static void main(String[] args) {
/*
* 获取当前目录中所有名字是.开头的子项
*/
File dir = new File(".");
MyFliter filter = new MyFliter();
File[] files = dir.listFiles(filter);
for (int i = 0; i < files.length; i++) {
System.out.println(files[i].getName());
}
}
}
class MyFliter implements FileFilter {
@Override
public boolean accept(File file) {
String name = file.getName();
return name.startsWith(".");
}
}
方法二:匿名内部类:文件过滤器只使用一次,单独建类造成浪费
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
String name = file.getName();
return name.startsWith(".");
}
});
RandomAccessFile====>读写文件数据====>文件不存在时将自动创建文件
java.io.RandomAccessFile * 专门用来读写文件数据的类,其读写是基于指针进行的,即:RAF总是在指针指向位置读取或者写出字节二进制低八位
RAF有两种模式:
r:只读模式,只能读取文件数据,不可以做写操作
rw:读写模式,即可读也可写
RandomAccessFile(File file, String mode)
RandomAccessFile(String name, String mode)
写操作(write(int i))
/*
* 对项目目录下的test.dat文件进行读写操作
* 写二进制
*/
RandomAccessFile raf = new RandomAccessFile("./test.dat","rw");
/*
* void write(int i)
* 该方法可以向文件中写入一个字节,写入的是
* 给定的int值所对应的二进制的低八位
*/
raf.write(1);//0000 0001
raf.writeUTF("women");
System.out.println("写出完毕!");
//必须关闭源
raf.close();
读写说明
* 写 写 读
* 00000000 00000000 00000000 11111111 //255----255
* 00000000 00000000 00000001 00000000 //256----0
* 11111111 11111111 11111111 11111111 //-1 ----255
读操作(int read())
RandomAccessFile raf = new RandomAccessFile("./test.dat","r");
/*
* int read()
* 从文件中读取1个字节,并以int形式返回,若返回值为-1,则说明文件读到头
*/
int b = raf.read();
System.out.println(b);
raf.close();
文件复制(按字节复制)===>效率,低木桶效应
/*
* 1:创建一个RAF用于读取源文件
* 2:创建一个RAF用于写入复制文件
* 3:循环从源文件中读每一个字节写到目标文件中去
*/
RandomAccessFile src = new RandomAccessFile("img.jpg", "r");
RandomAccessFile dest = new RandomAccessFile("copyImg.jpg", "rw");
int b = -1;
while ((b = src.read()) != -1) {
dest.write(b);
}
src.close();
dest.close();//将在内存中的数据清除,才能够写出
块读写
int read(byte[] data);write(byte[] data ,int index .int len=data.length)--实际读多少写多少----若想提高读写效率,可以通过提高每次读写的数据量,以减少实际读写次数来达到.1024byte = 1kb 1byte = 8 bit (一般情况下8k--10k)
单字节读写称之为随机读写方式
一次读写一组字节称之为块读写方式
RandomAccessFile src = new RandomAccessFile("movie.mp4", "r");
RandomAccessFile dest = new RandomAccessFile("movie_cp.mp4", "rw");
/*
* RAF提供的块读写方法:
* int read(byte[] data)
* 一次性从文件中读取给定的数组长度的字节量,并存入到该数组中,返回值为实际读取到的字节量,
* 若返回值为-1,表示本次没有读取到任何数据(实际已经是文件的末尾了)
*
* void write(byte[] data)
* 一次性将给的那个的字节数组中所有字节写出
*
* void write(byte[] data ,int index, int len)
* 一次性将给定的字节数组这种index处开始的连续len个字节写出
*/
byte[] data = new byte[1024*10];//10kb大小的数组
int len = -1;
long start = System.currentTimeMillis();
while((len = src.read(data))!=-1){
dest.write(data , 0 ,len);//思考?为什要用重载方法,意义在哪
}
long end = System.currentTimeMillis();
System.out.println("movie复制完成,耗时:"+(end - start ) + "ms");
src.close();
dest.close();
向文件中写出字符串操作
RandomAccessFile raf = new RandomAccessFile("./demo/raf.txt", "rw");
String line = "凉风有幸秋月无边~~~海苔海苔";
/*
* 将字符串首先根据给定的字符集转换为一组字节
* 常见的支持中文的字符集有:
* GBK,UTF-8
* getBytes();//默认为系统字符集,需要指定字符集--->getBytes("UTF-8");
*/
byte[] data = line.getBytes("UTF-8");
raf.write(data);
raf.write("随风飘摇摇摇摇*****".getBytes("UTF-8"));
System.out.println("写出完毕!");
raf.close();
从文件中读取字符串
/*
* 将./demo/raf.txt中的所有字符取出来
*/
RandomAccessFile raf = new RandomAccessFile("./demo/raf.txt", "r");
/*
* 若想读取一个字符,应当读取几个字节?
* 不同的字符集,对应的文字占用的字节量时不同的,英文时相同的,
* 无论哪个字符集中英文都时一个字节,都用的asc编码的部分,到那时对于中文而言则不然,
* 在gbk编码中,每个中文字符占用2字节,在utf-8中,每个中文占用3个字节.
* 占用的这些字节对应的2进制不全是表达字符本身的数据,还含有算法(通过这个,得知应当
* 读取几个字节表示一个文字).
*/
byte[] data = new byte[(int) raf.length()];//由于此处长度小,所以可以进行强转
raf.read(data);//数据放在字节数组中
String string = new String(data, "UTF-8");//传入一个字节数组,并指定字符集
System.out.println(string);
raf.close();
RAF基于指针的读写操作以RAF读写基本类型数据的操作(writeInt(int b))==>RandomAccessFile提供了所有基本数据类型的写入方法
当调用readInt()方法时,不再以-1表示到达文件末尾,而是直接抛出异常EOFException(end of file)
/*
* 向文件中写入一个int最大值
* maxValue: vvvvvvvv
* 01111111 11111111 11111111 11111111
* maxValue>>>24
* 00000000 00000000 00000000 01111111
*/
int maxValue = Integer.MAX_VALUE;
raf.write(maxValue>>>24);
raf.write(maxValue>>>16);
raf.write(maxValue>>>8);
raf.write(maxValue>>>0);
raf.writeInt(maxValue);//等价于前四步
System.out.println("写出完毕");
raf.close();//写出后记事本打不开
long getFilePoint()===>返回当前指针的位置,返回值是long
void seek(long pos)===>将指针移动到指定位置
写注册文件
/**
* 完成注册用户操作
* <p>程序启动后.要求用户输入:用户名,密码,昵称,年龄
* <p>然后将该记录写入user.dat文件中
* <p>规划每条记录占用100个字节:
* <p>其中:用户名,密码,昵称为字符串,各占32个字节
* <p>年龄为int值,占4字节
* <p>字符串通常在设计时,都会故意留白,长度相对固定.
* <p>这样做的好处:1:格式统一,便于操作指针操作每条记录,2:留有一定余量可以修改数据
*/
RandomAccessFile raf = new RandomAccessFile("./demo/user.dat", "rw");
raf.seek(raf.length());//此处每次在写入文件操作前将指针移动到文件末尾
byte[] data = userName.getBytes("UTF-8");
data = Arrays.copyOf(data, 32);//扩容,使每个字段都保持在32个字节
raf.write(data);
data = passWord.getBytes("UTF-8");
data = Arrays.copyOf(data, 32);
raf.write(data);
data = nickName.getBytes("UTF-8");
data = Arrays.copyOf(data, 32);
raf.write(data);
raf.writeInt(age);
System.out.println("注册完成!");
raf.close();
读取注册文件
for(int i = 0 ; i < raf.length() / 100 ;i++){
byte[] data = new byte[32];
raf.read(data);
String userName = new String(data,"UTF-8").trim();
raf.read(data);
String passWord = new String(data,"UTF-8").trim();
raf.read(data);
String nickName = new String(data,"UTF-8").trim();
int age = raf.readInt();
System.out.println(userName + "," + passWord + "," + nickName + "," + age);
}
raf.close();
修改
boolean have = false;
RandomAccessFile raf = new RandomAccessFile("./demo/user.dat", "rw");
for(int i = 0 ;i < raf.length() /100 ;i++) {
//修改指针位置
raf.seek(100 * i);
byte[] data = new byte[32];
raf.read(data);
String name = new String(data, "UTF-8").trim();
//判断是否有
if(name.equals(username)){
raf.seek(100*i+64);//将指针移动到此记录的昵称处
data = Arrays.copyOf(nickname.getBytes("UTF-8"), 32);//将昵称以32位字节写入
raf.write(data);
have = true;
break;
}
}