zoukankan      html  css  js  c++  java
  • io学习三

    RandomAccessFile##

    RandomAccessFile类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为 文件指针 ;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。

    *该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。
    RandomAccessFile实现了数据输入输出流的接口;可以随机存储硬盘的文件,但是来自网络的文件就不行

    RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream结合起来,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )、skipBytes()跳过多少字节数。此外,它的构造函数还要一个表示以只读方式("r"),还是以读写方式("rw")打开文件

    package randomfile;
    
    import java.io.RandomAccessFile;
    
    public class Example {
    	public static void main(String[] args) throws Exception {
    		RandomAccessFile afile = new RandomAccessFile("randomfile", "rw");
    		String[] type = new String[4];
    		type[0] = "php";
    		type[1] = "java";
    		type[2] = "c++";
    		type[3] = "测试中文adc";
    		afile.writeUTF(type[0]);
    		afile.writeUTF(type[1]);
    		afile.writeUTF(type[2]);
    		afile.writeUTF(type[3]);
    		afile.seek(afile.length());
    		afile.writeUTF("c");
    		afile.seek(0);
    		while(afile.getFilePointer()<afile.length()){
    			System.out.println(afile.readUTF());
    		}
    	}
    }
    
    

    以上 代码实现的是文件后面追加
    这里有个问题:使用writeUTF 会导致文字乱码(我已经指定编码是UTF-8) 在我电脑中显示的是:

    解决方法是 尽量用 write(byte[]) 这个方法写 原理参考:
    1、String.getBytes()将会按照当前系统默认的encoding方式获得字符串的 Bytes,RandomAccessFile.write(byte[])将这个byte数组正确写入。由于写入的实际就是Windows平台的 nativecode编码,所以文件还能够被正确的阅读。
    2、RandomAccessFile.writeBytes(String)将字符串的各个字符(当然是用unicode编码的)的高8位去掉,写入文件。
    3、RandomAccessFile.writeChars(String)将字符串的各个字符按照unicode的编码,以Big-endian的方式写入文件。Windows平台上默认文件的编码方式为Little-endian,所以用写字板打开看到的是乱码,但是如果我们用浏览器打开这个文件(testWriteChars.dat)并指定编码方式为Unicode Big-endian,就能看到正常的“中”字了。
    4、RandomAccessFile.writeUTF(String)首先写入00 03表示其后将写入3个实际的字节,然后写入“中”的UTF-8编码:E4 B8 AD
    通过上面的分析,我建议如果使用RandomAccessFile来写入中文的话,最好用 RandomAccessFile.write(String.getBytes())的方式,如果为了保险起见,还可以进一步指定运行平台的默认 nativecode编码方式,例如使用:RandomAccessFile.write(String.getBytes("gb2312"))
    参考 http://www.osedu.net/article/linux/2011-06-30/250.html

    RandomAccessFile 随意写测试:

    package randomfile;
    
    import java.io.RandomAccessFile;
    
    public class Example {
    	public static void main(String[] args) throws Exception {
    		RandomAccessFile afile = new RandomAccessFile("randomfile", "rw");
    		String[] type = new String[4];
    		type[0] = "php";
    		type[1] = "java";
    		type[2] = "c++";
    		type[3] = "测试中文adc";
    
    		afile.write(type[0].getBytes());
    		afile.write(type[1].getBytes());
    		afile.write(type[2].getBytes());
    		afile.write(type[3].getBytes());
    
    		afile.seek(0);
    
    		afile.write("c".getBytes());
    
    		afile.seek(0);
    
    		byte[] buffer = new byte[1024];
    		int readCount = 0;
    
    		while ((readCount=afile.read(buffer))!=-1) {
    			System.out.print(new String(buffer,0,readCount));
    		}
    	}
    }
    

    这里可以看出RandomAccessFile 写的时候会覆盖以前的内容

    RandomAccessFile 实现插入

    package randomfile;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.RandomAccessFile;
    
    public class Example2 {
    	public static void main(String[] args) throws Exception {
    		File temp = File.createTempFile("test", "temp");
    		temp.deleteOnExit();
    		FileInputStream fin = new FileInputStream(temp);
    		FileOutputStream fout = new FileOutputStream(temp);
    		RandomAccessFile rFile = new RandomAccessFile("randomfile", "rw");
    		rFile.seek(0);
    		byte[] buffer=new byte[1024];
    		int readCount=0;
    		while((readCount=rFile.read(buffer))!=-1){
    			fout.write(buffer, 0, readCount);
    		}
    		rFile.seek(0);
    		rFile.write("test插入".getBytes());
    		
    		while((readCount=fin.read(buffer))!=-1){
    			rFile.write(buffer, 0, readCount);
    		}
    		
    	}
    }
    
    

    这里使用了File的临时文件:
    File 的 createTempFile() 方法
    该方法有两种调用方式:
    createTempFile(String prefix, String suffix);
    在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。
    createTempFile(String prefix, String suffix, File directory);
    在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。
    File file2 = new File("D: emp");// D;/temp 为一个目录
    File tempFile1= file2.createTempFile("msg", ".tmp",file2);
    File tempFile2 = file2.createTempFile("msg", ".tmp");
    System.out.println(tempFile2.getAbsolutePath());
    可以这么认为,createTempFile() 方法,在指定的目录下创建一个temp文件,directory 类型为File ,如果路径不存在,则创建失败。createTempFile(String prefix, String suffix);方法默认的保存路径为:C:Documents and SettingsAdministratorLocal SettingsTemp 。

    可以看出其实插入操作 只要数据上了一定大小,是很耗费时间的和内存的(临时的文件的内存)
    可以尝试使用RandomAccessFile实现多线程的续点下载
    **RandomAccessFile的绝大多数功能,但不是全部,已经被JDK 1.4的nio的"内存映射文件(memory-mapped files)"给取代了,你该考虑一下是不是用"内存映射文件"来代替RandomAccessFile了。 **

  • 相关阅读:
    异常
    动态链接库与静态链接库的区别
    OpenBLAS 安装与使用
    Eigen 优化技巧
    C++读取保存为二进制的 numpy 数组
    Sublime Text Windows版使用Conda环境
    Repeater 时间格式化
    C#与js的各种交互
    js 实现精确加减乘除
    常用正则表达式
  • 原文地址:https://www.cnblogs.com/joeCqupt/p/6882648.html
Copyright © 2011-2022 走看看