JAVASE--03


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;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值