管理文件的内容

RandomAccessFile:管理文件的内容

1、 创建对象

2、 字节数据读写操作

3、 文件指针操作

扩展:

1、文件是什么:是一个以byte为单位的数据序列。这个数据序列每个数据单元有序号对应,从0~file.length()-1,读写文件需要按照序号位置读写:这个序号位置称为文件指针(File Pointer)。如果文件指针到达了file.length(),到达EOF(End Of File)文件的末尾。

  如:mp3文件:是5M个byte

     2014*1024*5个byte数据

2、文件是干什么用的?

       持久化存储数据的手段,用于软件内部或软件之间交换数据。

       持久化是什么呢?内存中的数据断电不能保存,所以需要将执行的程序(只保存对象)保存为一个文件在磁盘上,下次打开这个程序可以继续执行。

3、文件都是以byte为单位读写。

4、文件是一个长长的byte序列。

创建对象:

1、 RandomAccessFile在对文件进行随机访问操作时有两个模式分别是只读模式(只读取文件)和读写模式(对文件数据进行读写)。提供了按byte为单位读写文件。

        1、只读模式

            在创建RandomAccessFile时,其提供的构造方法要求我们传入访问模式:

            1、--RandomAccessFile(File file,Stringmode)

            2、--RandomAccessFile(String filename,String mode)

            --其中构造方法的第一个参数是需要访问的文件,而第二个参数是访问模式。

            --“r”:表示对该文件的访问是只读模式,如果文件不存在,则出错

            --“rw”:表示对文件的访问是读写模式,如果文件不存在,则创建文件

        2、读写模式:

            只需要在第二个参数中传入“rw”。表示对该文件的访问就是又可以读又可以写。

字节数据读写操作:

1、write(int d)方法:

RandomAccessFile提供了一个可以向文件中写出字节的方法:

---void write(int d):将d数据的低八位写出到打开的文进中。

---该方法会根据当前指针(从0开始)所在位置处写入一个字节,是将参数int的“低8位“写出,就是写出一个byte,int的前24位会被丢掉。

public void testWriteFile() throws Exception {
		//打开一个文件
		//检查文件指针的位置
		//写出数据:在当前指针位置写出一个int的低8位
		//每次写指针都会向后移动一个位置,方便下次写
		//检查文件指针的位置
		//写出数据
		RandomAccessFile raf=new RandomAccessFile("write.txt","rw");
		long index=raf.getFilePointer();//获取指针
		System.out.println(index);//0
		raf.write(50);//使用十六进制表示就是0011 0010
		index=raf.getFilePointer();
		System.out.println(index);//1
		raf.write(0xca);//1100 1010
		raf.write(0x100);//256  (1)0000 0000 低八位都是0
		index=raf.getFilePointer();
		System.out.println(index);//3
		raf.close();
	}

2、read()方法:

RandomAccessFile提供了一个可以从文件中读取字节的方法:

---int read()
该方法会从文件当前指针位置读取一个byte(8位)填充到int的低八位,高24位为0,返回值范围整数:0~255,如果返回-1表示读取到了文件末尾!每次读取后自动移动文件指针,准备下次读取。

        public void testRead() throws Exception {
		//读 取
		RandomAccessFile raf=new RandomAccessFile("write.txt","r");
		
		long index=raf.getFilePointer();
		System.out.println(index);//0
		
		int b=raf.read();
		System.out.println(Integer.toBinaryString(b));//这是上面第一次写入的50的十六进制的二进制表示,11 0010
		index=raf.getFilePointer();
		System.out.println(index);//1
		
		b=raf.read();
		System.out.println(Integer.toBinaryString(b));//这是上面第二次写入的0xca,1100 1010 
		index=raf.getFilePointer();
		System.out.println(index);//2
		
		b=raf.read();//这是上面第三次写入的0x100表示256,输出的只输出低八位,所以应该是0
		System.out.println(Integer.toBinaryString(b));//0
		index=raf.getFilePointer();
		System.out.println(index);//3
		
		b=raf.read();
		System.out.println(b);//读到了文件的末尾,现在返回值是-1
		System.out.println(Integer.toBinaryString(b));//11111111111111111111111111111111,-1表示为补码
		
		raf.close();
	}

	public void testRead2() throws Exception {
		//循环读取
		RandomAccessFile raf=new RandomAccessFile("write.txt","r");
		int b;
		while((b=raf.read())!=-1) {
			System.out.println(Integer.toBinaryString(b));// 110010  11001010  0
		}
		raf.close();
	}

3、write(byte[] d)方法:

RandomAccessFile提供了一个可以向文件中写出一组字节的方法:

---void write(byte[] d)

该方法会根据当前指针所在位置处连续写出给定数组中的所有字节。

重载的方法:

---void write(byte[] d,int offset,int len)

该方法会根据当前指针所在位置处连续写出给定数组中的部分字节,这个部分是从数组的offset处开始,连续len个字节。

public void testWrite1() throws Exception {
		RandomAccessFile raf=new RandomAccessFile("write2.txt","rw");
		
		//0xca  0xff大于127,超过了byte的范围,byte的范围是-128~127
		//经过强制类型转换之后,变为负数!
		byte[] buf= {0x32,(byte)0xca,0x00,(byte)0xff};
		// 十进制数据是          50     -54      0       -1
		raf.write(buf);
		//写完之后文件指针的位置是4
		raf.close();
	}

4、read(byte[] b)方法:

RandomAccessFile提供了一个可以从文件中批量读取字节的方法:

---int read(byte[] b)

该方法会从文件中尝试最多读取给定数组的总长度的字节量,并从给定的字节数组中第一个位置开始,将读取到的字节顺序存放至数组中,返回值为实际读取到的字节量。

        public void testReadByBuffer() throws Exception {
		RandomAccessFile raf=new RandomAccessFile("write2.txt","r");
		
		//返回长度不够
		byte[] buf=new byte[3];//buf的长度是3,而上面写入了4个字节,所以只返回前3个字节的内容
		int n=raf.read(buf);//返回字节量,也就是buf中字节的长度,3
		System.out.println(n);
		//显示byte数组中的数据
		for(byte b:buf) {
			//System.out.println(Integer.toHexString(b));
			//32  ffffffca  0
			//因为0xca超过byte的范围了,所以返回补码
			System.out.println(Integer.toHexString(b&0xff));
			//32 ca 0
		}
		
		//返回长度多余
//		byte[] buf1=new byte[5];//超过了文件中写入的个数
//		int m=raf.read(buf1);
//		System.out.println(m);//4
//		for(byte bt:buf1) {
//			System.out.println(Integer.toHexString(bt&0xff));//32 ca 0 ff 0
		//最后一个0是因为buf1初始化数组中的元素是0
//		}
		raf.close();
	}

	public void testReadByBuffer1() throws Exception {
		RandomAccessFile raf=new RandomAccessFile("write2.txt","r");
		
		//如果将文件的全部数据一次读取到byte数组中
		//提示:文件长度raf.length()
		byte[] buf=new byte[(int)raf.length()];//将文件的数据一次读取到内存中
		                                       //适合小文件,不能用于大文件
		int n=raf.read(buf);
		System.out.println(n);//4
		//达到文件末尾,再读取返回-1
		int m=raf.read(buf);
		System.out.println(m);//-1
		
	}
        public void testWriteByteArray() throws Exception {
		RandomAccessFile raf=new RandomAccessFile("write1.txt","rw");
		byte[] buf="helloworld".getBytes();
		//将字节数组中所有字节一次性写出
		raf.write(buf);
		raf.close();
	}
	
	public void testReadByteArray() throws Exception {
		RandomAccessFile raf=new RandomAccessFile("write1.txt","r");
		//创建10个字节的数组,因为上面helloworld有十个字节
		byte[] buf=new byte[10];
		int len=raf.read(buf);
		System.out.println("读取到了"+len+"个元素");//读取到了10个元素
		System.out.println(new String(buf));//helloworld
		raf.close();
	}

5、拆分方法:

raf.writeInt(i):将int拆分成4个byte写出

raf.writeLong(i):将long拆分成8个byte写出

raf.writeDouble(i):将double拆分成8个byte写出

public void testWriteInt() throws Exception {
		int row=4;
		int col=1;
		RandomAccessFile raf=new RandomAccessFile("write3.txt","rw");
		raf.writeInt(row);//注意不是write,这个地方增加了4个byte
		raf.writeInt(col);
		raf.close();
	}

6、拼接方法:

int i=raf.readInt():连续读取4个byte拼接为一个int返回

其余的都一个道理

        public void testReadInt() throws Exception {
		int row,col;
		RandomAccessFile raf=new RandomAccessFile("write3.txt","r");
		row=raf.readInt();//注意不是read
		col=raf.readInt();//注意读取顺序
		raf.close();
		System.out.println("row="+row+",col="+col);//row=4,col=1
	}

7、如何使用RandomAccessFile存储一个电话本

int       long     Stirng  String

序号   创建时间   姓名    电话   

1      创建时间    小米    118

2      创建时间     黑米   110

       文件的设计,每条信息为372个字节

0~3     4个    存储int编号

4~11    8个    存储long创建时间

12+50   62个   存储String姓名,从左边起写,后面的补0

62+30   92个   存储String电话

92~200     个   存储String地址

剩下的备用

 

如何写出:

第一条:

0      编号

4   时间

12   name

62    mobile

92     address

 

第二条:

372+0   编号

372+4   时间

372+12  name

372+62   mobile

372+92    address

 

第n条:

372*(n-1)+0 编号

372*(n-1)+4 时间

372*(n-1)+12 name

372*(n-1)+62 mobile

372*(n-1)+92 address


设计方法:

       //将信息写入到raf文件中,n表示第几条

       publicvoid writeContect(RandomAccessFile raf,int n,int id,Datetime,

                     Stringname,String mobile,String address) {}

        public void writeContect(RandomAccessFile raf,int n,int id,Date time,
			String name,String mobile,String address) throws Exception {
		//1、先为文件增加一个定长记录
		long start=372*(n-1);
		raf.setLength(start+372);//先为每条记录分配一个372的空间
		
		raf.seek(start);//是id的写出位置,然后从头开始分配
		raf.writeInt(id);
		
		raf.seek(start+4);//是时间的写出为止
		raf.writeLong(time.getTime());
		
		raf.seek(start+12);//是姓名的写出位置
		raf.write(name.getBytes());
		
		raf.seek(start+62);//是电话的写出位置
		raf.write(mobile.getBytes());
		
		raf.seek(start+92);//是地址的写出位置
		raf.write(address.getBytes());		
	}
	//@Test
	public void testWriteContect() throws Exception {
		//写入文件
		RandomAccessFile raf=new RandomAccessFile("contect.dat","rw");
		writeContect(raf,1,1,new Date(),"小米","118","北京大钟寺");
		writeContect(raf,2,2,new Date(),"黑米","110","北京");
		raf.close();
	}

读取地址信息:

public Map<String,Object>readContect(RandomAccessFile raf,int n){}

//读取地址信息
	public Map<String,Object> readContect(RandomAccessFile raf,int n) throws Exception{
		int start=372*(n-1);
		
		raf.seek(start+0);
		int id=raf.readInt();//读取编号
		
		raf.seek(start+4);
		long time=raf.readLong();//读取时间
		
		raf.seek(start+12);
		//读取人名12连续50个byte
		byte[] buf=new byte[50];//读取人名
		raf.read(buf);
		String name=new String(buf).trim();//trim()去掉字符串前后的空白
		
		//读取电话
		buf=new byte[30];
		raf.seek(start+62);
		raf.read(buf);
		String mobile=new String(buf).trim();
		
		//读取地址
		buf=new byte[200];
		raf.seek(start+92);
		raf.read(buf);
		String address=new String(buf).trim();
		
		Map<String,Object> map=new LinkedHashMap<String,Object>();
		map.put("id", id);
		map.put("time", new Date(time));
		map.put("name", name);
		map.put("mobile", mobile);
		map.put("address",address);				
		return map;
	}
	//@Test
	public void testReadContect() throws Exception {
		RandomAccessFile raf=new RandomAccessFile("contect.dat","r");
		//读取一条联系人信息
		Map<String,Object> contact=readContect(raf,2);//读第二条
		raf.close();
		//输出读取结果
		System.out.println(contact);		
	}

“id”:1

“time”:Date

“name”:“黑米”

“mobile”:110

“address”:“北京”

因为数据类型什么都有,所以使用Object类型。

8、seek方法:

raf.seek(pointer)

移动文件读取指针到指定位置

如果指针位置超出文件长度,文件自动增加

如:在新文件上执行

raf.seek(372)

文件会增长到372,文件的内容默认为0

9、skipBytes方法

RandomAccessFile提供了一个方法可以尝试跳过输入的n个字节以丢弃跳过的字节。

方法:

----int skipByte(int n

该方法可能跳过一些较少数量的字节,这可能由任意数量的条件引起,在跳过n个字节之前已经达到文件的末尾只是其中的一种可能。此方法不抛出EOFException。返回跳过的实际字节数。如果n是负数,则不跳过任何字节。这个是相对位置,在相对于当前位置跳过n个字节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值