java io的一些总结

ByteZenith
• 阅读 4194

RandomAccessFile类的使用

该类默认的写操作是覆盖操作。例如原来的文件内容是“abcde”,我们将文件指针移向2位置(seek(2),即覆盖的位置在b字符之后),我们写入3个字符:raf.write("xxx".getBytes());文件就变成了"abxxe"。如果我们要将xxx插入到b和c字符之间,默认的RandomAccessFile是无法实现的

/**
 * 向文本文件的特定位置插入字符串
 */
public static void insertStringToTxtFile(File f,String content,int pos) throws IOException{
    
    RandomAccessFile raf = new RandomAccessFile(f, "rw");
    raf.seek(pos);
    
    // 暂存插入点后的字符串
    byte[] buf = new byte[1024];
    int len = 0;
    StringBuilder sb = new StringBuilder();
    while ((len = raf.read(buf)) != -1) {
        sb.append(new String(buf, 0, len));
    }
    
    // 此时FP已经移动到了EOF,需要重新回到插入点写入字符串
    raf.seek(pos);
    raf.write(content.getBytes());
    raf.write(sb.toString().getBytes());
    raf.close();
    
}

以上的代码中最关键的代码是将文件指针之后的内容暂存起来,使用到了StringBuilder容器,读取的时候采用的是读取到字节数组(因为一次读取一行可能会产生换行的问题)。

该类用于随机读取文件,利用该类我们可以实现多线程写文件的操作。具体思路是将目标文件分块,每个线程负责写入一个数据块。例如:

public class WriteFile implements Runnable{

    private int block;                                // 数据块标号
    private File descFile;                            // 目标文件
    private static final int SIZE_PER_BLOCK = 20;    // 每个数据块大小
    
    public WriteFile(int block, File descFile) {
        super();
        this.block = block;
        this.descFile = descFile;
    }

    @Override
    public void run() {
        try {
            RandomAccessFile raf = new RandomAccessFile(descFile, "rw");
            raf.seek((block - 1) * SIZE_PER_BLOCK);
            raf.writeBytes("This is block " + block + "\n");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
public class MultipleThreadWrite {
    
    static File file = new File("data.txt");
    
    public static void main(String[] args) {
        
        for (int i = 1; i < 6; i++) {
            new Thread(new WriteFile(i, file)).start();
        }
    }

}

以上开启了5个线程向data.txt文件中写入数据,每个线程负责写入一个数据块的数据,我们要写入的字符串的长度是16个字节,没有完全占用1个数据块,但是第二个线程写入数据的时候将文件指针移动到了20,从20开始写入,前面的4个字节是没有数据的。因此,全部线程执行完毕之后,文件的大小是 4 * 20 + 16 = 96bytes。

java io的一些总结

apache commons IO库

maven依赖如下:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

常用方法如下:

@Test
public void testFileUtils() throws Exception{
    
    File file = new File("test.txt");

    // 将文本文件读取为字符串
    String str = FileUtils.readFileToString(file, "utf-8");
    System.out.println("文本文件内容:" + str);
    
    // 文件大小
    System.out.println(FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(new File("F:/BaiduYunDownload/OS X Mavericks 10.9 (GM).iso"))));
    
    // 向文件中写入字符串
    FileUtils.writeStringToFile(new File("data.txt"), "你好hellodfd#$", "utf-8");
    
    // 遍历目录及其子目录下的所有文件
    Iterator<File> iterator = FileUtils.iterateFilesAndDirs(new File("E:/tmp"), FileFileFilter.FILE, DirectoryFileFilter.DIRECTORY);
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
        
    }
    
    // 文件拷贝
    File destFile = new File("test_copy.txt");
    FileUtils.copyFile(file, destFile);
    
    // 从URL(必须是file协议,即本地计算机)中得到文件资源
    file = FileUtils.toFile(new URL("file:///E:/tmp/%E7%84%A6%E7%82%B9%E5%9B%BE.html"));
    System.out.println("本地文件:" + file);
    
    // 将文件拷贝到指定目录(目录不存在,创建之)
    FileUtils.copyFileToDirectory(file, new File("E:/tmp/demo"));
    
    // 拷贝一个目录(及其文件和子目录)到另一个目录
    FileUtils.copyDirectoryToDirectory(new File("E:/tmp"), new File("E:/demo"));
    
    // 下载远程资源到本地
    FileUtils.copyURLToFile(new URL("http://www.knowsky.com/384261.html"), new File("tmp.html"), 3000, 3000);
    
    // 删除目录中的内容
    FileUtils.deleteDirectory(new File("E:/demo"));
    
    // 移动文件(rename)
    FileUtils.moveFile(new File("test.txt"), new File("ok.txt"));
    
}

commons io参考文档

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
半臻 半臻
4年前
Python基础8——文件操作
16文件操作16.1文件操作的基本概念文件操作的步骤1.打开文件2.读、写文件3.关闭文件open函数,创建一个file对象,默认是以只读的方式打开read方法:一次性读取文件的所有内容write方法:将指定内容写入文件close方法:关闭文件file对象的属性flie.name文件的名称file.mode文件的访问模式file.closed
Karen110 Karen110
4年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Peter20 Peter20
4年前
mysql中like用法
like的通配符有两种%(百分号):代表零个、一个或者多个字符。\(下划线):代表一个数字或者字符。1\.name以"李"开头wherenamelike'李%'2\.name中包含"云",“云”可以在任何位置wherenamelike'%云%'3\.第二个和第三个字符是0的值wheresalarylike'\00%'4\
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Easter79 Easter79
4年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
4年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
小万哥 小万哥
1年前
Java 文件处理完全指南:创建、读取、写入和删除文件详细解析
Java文件操作文件处理简介文件处理是任何应用程序的重要部分。Java提供了许多用于创建、读取、更新和删除文件的方法。Java文件处理Java中的文件处理主要通过java.io包中的File类完成。该类允许我们处理文件,包括创建、读取、写入和删除文件。创建
ByteZenith
ByteZenith
Lv1
人有悲欢离合,月有阴晴圆缺,此事古难全。但愿人长久,千里共婵娟。
文章
7
粉丝
0
获赞
0