zoukankan      html  css  js  c++  java
  • Java对文件的读、写随机访问,RandomAccessFile类的使用分析

    Java对文件的读、写随机访问,RandomAccessFile类的使用分析

    在网上看了一些关于java中的RandomAccessFile类的介绍,又经过查看Java API和自己编的测试程序,总算是对RandomAccessFile的使用有了一定的了解。自己做了以下比较详细的总结吧。

      1.RandomAccessFile类的简单介绍

      该类的实例支持对文件的随机读取和写入。随机存取文件的行为类似存储在文件系统中的一个大型字节数组。存在指向该隐含数组的光标或索引,称为文件指针。读取操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机存取文件以读取/写入模式创建,则写入操作也可用;写入操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。该文件指针可以通过 getFilePointer 方法读取,并通过seek 方法设置。

      通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出 EOFException如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出 IOException。需要特别指出的是,如果流已被关闭,则可能抛出 IOException

      2.一个文件读取错误例子引出的思考

    复制代码
    import java.io.RandomAccessFile;
    public class RandomAccessFile_test {
        public static void main(String args[]) throws Exception{
            RandomAccessFile access=new RandomAccessFile("c:\\a.txt","rw");    //文件a.txt中只有一个整数1234
            System.out.println("文件长度为:"+access.length());
            System.out.println("读出的数据位:"+access.readInt());
            access.close();
        }
    }
    复制代码

      执行输出: 文件长度为:4
            读出的数据位:825373492

      分析:这是因为RandomAccessFile类的实例都是根据要读取的数据类型来读取指定大小的数据块到变量。int类型占4个字节,因此readInt()函数会从文件开头读取四个字节,每个字节都当做ASCII码。读到的四个ASCII码字节是‘1’,‘2’,‘3’,‘4’,对应十六进制为31H,32H,33H,34H,即31323334H=825373492D。

      3.随机读写文件的存储图示

        3.1数据存放

        (1)用RandomAccessFile类写入的数据一般都是按照ASCII字符的形式保存在文件中的,即以字节的形式,字节是计算机存储设备编址的最小单元。

          (2)Java中各数据类型所占的字节数,如图表所示:  

         (3)如下图就是依次写入int,byte,double,int,byte,short,short数据时,在文件中的存放。文件指针会随着数据的写入按照写入后移。

        3.2数据读取

        (1)如用readInt()方法读取一个int数据。文件指针会从当前位置向后读取去四个字节的数据,将取到的数据在强制转换为int类型返回即可,同时文件指针也自动的向后移动了相应的四个位置。

          (2)如果先用readByte()方法读取一个byte数据,读取后文件指针移动了一个位置(还在int原本的四个字节中),这样再用readInt()方法读取一个int数据就会出现乱码。

        (3)也就是说用RandomAccessFile类来操作文件,应该知道数据事先是如何存放的,之后用相应的读取就能顺序的读出,而不会出现乱码。

       4.特殊的数据读取

        4.1字符串读readUTF()和字符串写writeUTF(String str)

        这2个方法都带有“UTF”,是因为写入数据时按照utf-8编码写入,读取时也是utf-8。

        每次写入的字符串的长度是不一定的。因为Java API给出了读取与写入字符串是成对的,因此需要标记每次写入的字符串的长度。每次写入字符串时,会分配2个字节来保存,要写入的字符串的大小,也就是一次写入字符串的大小应该不能大于65536个字节。每次读取的字符串时,先从文件指针的位置开始读取2个字节,分析得到要读取字符串的长度,之后在进行读取。如下图所示:

          

        程序举例:写入2次字符串。

    复制代码
    import java.io.RandomAccessFile;
    public class Char_Byte{
        public static void main(String args[]) throws Exception{
            RandomAccessFile access=new RandomAccessFile("C:\\a.txt","rw");    //“读写”方式建立类的实例
            access.writeUTF("你好");    //以utf-8格式写入数据
            access.writeUTF("朋友"); //以utf-8格式写入数据
            access.close();
        }
    }
    复制代码

        查看生成文件,可以看到在汉字的前面有一些字符,其实就是2个字节的标记字符串长度的ASCII编码。

        4.2读取一行readLine()

         (1)Java API中只有读取一行readLine()方法,然而没有写入一行writeLine()的方法。
         (2)在Windows下的行结束符号是“\r\n”。执行readLine()方法,从当前的文件指针开始读取,直到遇到“\r\n”或者文件结束为止。
         (3)此方法不支持完整的 Unicode 字符集。所以用writeUTF(String str)写入的中文需要相应的readUTF()读取,以免出现乱码。汉字的UTF-8编码占3个字节,而GBK占用2个字节,汉字的Unicode编码占2字节。
         (4)在写文件时,为了可以更换使用readLine(),需要自己写入行结束符号是“\r\n”。
        程序举例:写入2次字符串,以行结束符号隔开。

    复制代码
    import java.io.RandomAccessFile;
    public class Char_Byte{
        public static void main(String args[]) throws Exception{
            RandomAccessFile access=new RandomAccessFile("C:\\a.txt","rw");    //“读写”方式建立类的实例
            access.writeBytes("Hello world!!!");    //写入数据
            access.writeBytes("\r\n");//写入行结束符号
            access.writeUTF("he he"); //以utf-8格式写入数据
            access.close();
            
            access=new RandomAccessFile("C:\\a.txt","rw");
            String context=access.readLine();    //读取数据
            access.close();
            System.out.println(context);
        }
    }
    复制代码

        程序输出:Hello world!!!

      5.总结

      (1)RandomAccessFile类可以进行文件的随机读写,就好比对一个大型的数组的操作,对于大文件来说速度是比较慢的。

      (2)RandomAccessFile类的实例是根据给定的数据类型大小写入和读取数据,因此用writeXXX()写入的数据,最好用相应的readXXX()来读取。

      (3)RandomAccessFile类的实例写入也是按照字节顺序的写入,生成文件的。要读取这样的文件就必须知道是如何生成的,否则很可能出现读取出乱码。

    参考:

    1.Java API文档

    2.http://blog.csdn.net/akon_vm/article/details/7429245

    3.http://zhidao.baidu.com/question/139267246.html

     
     

    一:

    上一篇的链接:

    基于.net开发chrome核心浏览器【一】

    二:

    相关资源介绍:

    chrome Frame:

      让IE有一颗chrome的心,看起来不错,但我没有深入研究这个东西。

    http://www.google.com/chromeframe?hl=zh-CN&quickenable=true

    https://developers.google.com/chrome/chrome-frame/

    WebKit.Net

      已经有一段时间没人更新这个开源项目了,没有研究过

      http://sourceforge.net/projects/webkitdotnet/

    CEF

      研究过,很不错的类库,但是是C和C++写的

      https://code.google.com/p/chromiumembedded/

      http://www.cnblogs.com/think/archive/2011/10/06/CEF-Introduce.html(园友谭振林写的相关文章)

    Xilium.CefGlue

      基于CEF,用.net包装过,很不错,我就用的这个类库(Xilium.CefGlue/3)

      https://bitbucket.org/xilium/xilium.cefglue/wiki/Home

    O.N.E

      国内的人开发的,没研究过,貌似收费的。

    http://www.one-lab.net/

    node-webkit

      园子里的人开发的,非常不错的点子,node和chromium的结合,赞

      https://github.com/rogerwang/node-webkit/

      http://www.cnblogs.com/zhchbin/

    qt

      我在这方面花费了大量的时间和精力,结果是一个坑跟着一个坑,但到现在还是不忍放弃

      http://qt-project.org/downloads

    另外

    这里说到的很多资源都是园友在上一篇文章中提到的。

    谢谢你们。

    三:

    CEF有两个版本,CEF1和CEF3

    CEF1是单进程的,实现了更多的特性,内存使用更少,与客户端应用更能完美的结合,使用的是WebKit的API,但是FLASH无法在这个框架中正常播放,不支持html5的音频和视频,只支持NPAPI插件。关于NPAPI插件的相关知识,请参阅这里:http://developer.chrome.com/extensions/npapi.html(好像要FQ)

    CEF3是多进程的,使用异步消息的方式来完成主进程和其他进程的通信(其他进程有可能是Webkit,也有可能是V8的解析引擎进程),使用的是chromium官方的内容呈现API,支持NPAPI和PPAPI插件,有一个单独的进程用于调试,相对于CEF1来说,虽然可以播放FLASH等视频,但是还有很多问题没有处理掉,社区里的人认为CEF1更稳定一些,CEF3的issues列表,请参阅这里:https://code.google.com/p/chromiumembedded/issues/list

    我们选用的是CEF3和Xilium.CefGlue,Xilium.CefGlue是对CEF项目的.net的包装,它是用P/Invoke的方式来调用CEF类库的,请参见:https://bitbucket.org/xilium/xilium.cefglue/wiki/Home

    还有一个CEFSharp的项目,是用C++/CLI的方式来调用CEF类库的,请参见:https://github.com/chillitom/CefSharp

    四:

    下载最新版的CEF的动态链接库

    下载地址为:http://xilium.bitbucket.org/cefglue/

    一定要在这个页面来下载!因为只有这个页面给出的动态链接库才是Xilium.CefGlue所支持的

    目前看到的是3.1353.1236版本(我没有下载debug版本的)

    五:

    下载最新的Xilium.CefGlue代码

    下载地址:https://bitbucket.org/xilium/xilium.cefglue/overview

    右侧点“下载”就可以了

    六:

    把下载到的两个压缩包都解压缩

    把\cef_binary_3.1453.1236_windows_xilium\Release目录里的文件复制出来

    粘帖到:\xilium-xilium.cefglue-50e94efc4182\CefGlue.Demo.WinForms\bin\Debug目录下

    七:

    打开\xilium-xilium.cefglue-50e94efc4182\目录下的解决方案文件

    把CefGlue.Demo.WinForms设为启动项目

      注意事项:

      1.

    把程序集CefGlue.Demo.GtkSharp卸载掉,

    这个程序集是给mono平台用的,你也可以把WPF相关的程序集也卸载掉

      2.

      右键单击CefGlue.Demo.WinForms程序集,点属性,选择调试,

      取消选中“启用visual studio承载进程”,

      因为CEF3是基于多进程的,VS无能力承载,所以只有取消掉这个选项

      3.

      右键单击CefGlue.Demo.WinForms程序集,点属性,选择生成,把目标平台改成X86

      (这一项如果编译不通过再来修改也无碍)

    八:

    编译并执行,

    你就可以看到CefGlue为你写的DEMO了。

    你如果线这个DEMO里的代码比较复杂

    你也可以看看CefGlue.Client这个程序集

    这个程序集是个比较简单的DEMO,

    你也可以按照上面的步骤让这个DEMO跑起来

    九:

    上面的DEMO看起来是这个样子的:

    在这个DEMO的samples菜单中有几个简单的示例

    这给开发者提供方便的,开发者在写自己的程序时,经常会看这几个DEMO

    但几个DEMO实在是太少了。

    十:

    打开cef_binary_3.1453.1236_windows_xilium目录中的工程文件

    (这才是CEF项目,前面说的是基于CEF开发的CefGlue项目)

    编译并运行

    你会看到一个类似这样的界面:

    这个DEMO中,主菜单中的test是为开发人员准备的DEMO

    明显比CefGlue要多一些!

    如果你有一些C和C++功底(不用很高)也能看懂这里的例子

    十一:

    说实在的,这个项目还是有挺多的坑的,我已经碰到了好几个

    跌跌撞撞总算走过来了,我一步一步的把我的经验都分享给园友

    请持续关注我的后续文章

     
     
    分类: WIN FORM(c#)
    分类: java编程
  • 相关阅读:
    HDU2586 How far away?(tarjan的LCA)
    You Raise Me Up
    POJ2891 Strange Way to Express Integers(中国剩余定理)
    POJ2142 The Balance(扩展欧几里得)
    HDU 1166模仿大牛写的线段树
    NetWord Dinic
    HDU 1754 线段树裸题
    hdu1394 Minimum Inversion Number
    hdu2795 Billboard
    【完全版】线段树
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3033904.html
Copyright © 2011-2022 走看看