zoukankan      html  css  js  c++  java
  • 18 IO流(十五)——RandomAccessFile随机访问文件及使用它进行大文件切割的方法

    本文部分内容转自:https://blog.csdn.net/nightcurtis/article/details/51384126

    1.RandomAccessFile特点

    RandomAccessFile是java Io体系中功能最丰富的文件内容访问类。即可以读取文件内容,也可以向文件中写入内容。但是和其他输入/输入流不同的是,程序可以直接跳到文件的任意位置来读写数据。
    因为RandomAccessFile可以自由访问文件的任意位置,所以如果我们希望只访问文件的部分内容,那就可以使用RandomAccessFile类。
    与OutputStearm,Writer等输出流不同的是,RandomAccessFile类允许自由定位文件记录指针,所以RandomAccessFile可以不从文件开始的地方进行输出,所以RandomAccessFile可以向已存在的文件后追加内容。则应该使用RandomAccessFile。

    2.RandomAccessFile的整体介绍

       RandomAccessFile类包含了一个记录指针,用以标识当前读写处的位置,当程序新创建一个RandomAccessFile对象时,该对象的文件记录指针位于文件头(也就是0处),当读/写了n个字节后,文件记录指针将会向后移动n个字节。除此之外,RandomAccessFile可以自由的移动记录指针,即可以向前移动,也可以向后移动。RandomAccessFile包含了以下两个方法来操作文件的记录指针.

    • long getFilePointer(); 返回文件记录指针的当前位置
    • void seek(long pos); 将文件记录指针定位到pos位置

    RandomAccessFile即可以读文件,也可以写,所以它即包含了完全类似于InputStream的3个read()方法,其用法和InputStream的3个read()方法完全一样;也包含了完全类似于OutputStream的3个write()方法,其用法和OutputStream的3个Writer()方法完全一样。除此之外,RandomAccessFile还包含了一系类的readXXX()和writeXXX()方法来完成输入和输出。

    RandomAccessFile有两个构造器,其实这两个构造器基本相同,只是指定文件的形式不同而已,一个使用String参数来指定文件名,一个使用File参数来指定文件本身。除此之外,创建RandomAccessFile对象还需要指定一个mode参数。该参数指定RandomAccessFile的访问模式,有以下4个值:

    • “r” 以只读方式来打开指定文件夹。如果试图对该RandomAccessFile执行写入方法,都将抛出IOException异常。
    • “rw” 以读,写方式打开指定文件。如果该文件尚不存在,则试图创建该文件。
    • “rws” 以读,写方式打开指定文件。相对于”rw” 模式,还要求对文件内容或元数据的每个更新都同步写入到底层设备。
    • “rwd” 以读,写方式打开指定文件。相对于”rw” 模式,还要求对文件内容每个更新都同步写入到底层设备。


    ————————————————
    版权声明:本文为CSDN博主「Simon_night」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/nightcurtis/article/details/51384126

    案例演示

    使用RandomAccessFile类将一个大文件分割为几个小文件。

    思路解析

    import java.io.*;
    public class Test03
    {
    	public static void main(String[] args) throws IOException{
    		//需要分割的文件	
    		//获取文件的大小	
    		//创建分割器 RandomAccessFile
    		//块长:你需要将文件分为的每个小文件最大为多大
    		//总块数=文件长度/块长 使用向上取整(Math.ceil())获得总块数
    		//定义起始分割位置
    		int beginPos = 0;
    		//实际每次分割到的大小 的初始值:=块长>文件长度?文件长度:块长。
    		//循环 计算并操作 每块分配到的数据
    		for(int i=0;i<总块数;i++){
    			//计算新的开始位置
    			if(i==blockAll-1){//最后一块
    				//将剩余量赋给实际分割大小变量
    			}else{
    				//实际分割大小为块长
    				//文件长度-=块场
    			}
    			//操作每块的数据 可以输出到文件、控制台等等
    			//fileSplit(beginPos,actualSize);//操作:调用分段输出内容方法
    		}
    		//关闭流
    		raf.close();
    	}	
    
    /**
    *操作每块的方法用例:输出到控制台
    *传入起始位置和实际长度
    */
    
    public static void fileSplit(int beginPos,int actualSize) throws IOException
    {
    		RandomAccessFile raf = new RandomAccessFile(new File("Test01.txt"),"r");
    
    		//随机读取
    		raf.seek(beginPos);
    		//读取
    		//操作 分段读取
    		byte[] flush = new byte[1024];//缓冲容器
    		int len = -1;//接收长度
    		while((len = raf.read(flush))!=-1){
    			if(len<actualSize){//如果本次读到的小于需要的
    				System.out.println(new String(flush,0,len));//本次读到的全都要
    				actualSize -= len;//需要的部分减少
    			}else{//如果本次读取的超过需要的,只拿需要的部分
    				System.out.println(new String(flush,0,actualSize));
    				break;
    			}
    		}
    
    		//关闭流
    		raf.close();
    	}
    }
    

      

    完整代码

    import java.io.*;
    public class Test05
    {
    	public static void main(String[] args) throws IOException{
    		//文件
    		File src = new File("test01.txt");
    		//文件大小
    		long len = src.length();
    		//流
    		RandomAccessFile raf = new RandomAccessFile(src,"r");
    		//单块长度
    		int blockSize = 1024;
    		//需要分成的总块数
    		int blockAll = (int)Math.ceil(len*1.0/blockSize);
    		//开始位置变量
    		int beginPos = 0;
    		//单词读取的实际长度及初始值
    		int actualSize = (int)(blockSize>len?len:blockSize);
    		//控制台输出文件及块信息
    		System.out.printf("文件大小:%d 分割块数:%d%n",len,blockAll);
    		//for循环操作每一块
    		for(int i = 0;i<blockAll;i++){
    			//计算开始位置
    			beginPos = i*blockSize;
    			if(i!=blockAll-1){//如果不是最后一块
    				actualSize = blockSize;//本次读取长度等于块长
    				len-=blockSize;//剩余文件长度
    			}else{//如果是最后一块
    				actualSize = (int)len;
    			}
    			//调用针对每个块的方法
    			fileSplit(i,beginPos,actualSize);//调用分割文件方法
    			System.out.println("第"+i+"块,本次读取数据:"+actualSize+" 剩余文件长度:"+len);
    		}
    	}
    
    	//操作方法:将文件分割并生成分割文件
    	public static void fileSplit(int i,int beginPos,int actualSize) throws IOException{
    		//文件
    		File src = new File("test01.txt");
    		//流
    		RandomAccessFile raf = new RandomAccessFile(src,"rw");
    		RandomAccessFile raf2 = new RandomAccessFile(new File("dest/"+i+"copy.txt"),"rw");//分割文件保存位置
    		String num = String.valueOf(i);
    		
    		byte[] flush = new byte[1024];
    		int len = -1;
    		raf.seek(beginPos);
    		while((len = raf.read(flush))!=-1){
    			if(actualSize>len){
    				raf2.write(flush,0,len);
    				actualSize -= len;
    			}else{
    				raf2.write(flush,0,actualSize);
    				break;
    			}
    		}
    		raf.close();
    		raf2.close();
    	}
    }
    

      

  • 相关阅读:
    hbase 简介
    Hadoop本地库介绍
    MapReduce:详解Shuffle过程
    eucalyptus,openstack
    openstack installing...
    今年2011
    wget代理设置(转载)
    openstack running
    python 升级到2.6(转载)
    高德地图Windowphone API学习地图定位与地图模式的切换
  • 原文地址:https://www.cnblogs.com/Scorpicat/p/11935100.html
Copyright © 2011-2022 走看看