zoukankan      html  css  js  c++  java
  • Java之IO(六)FileInputStream和FileOutputStream

      转载请注明源出处:http://www.cnblogs.com/lighten/p/7001458.html

    1.前言

      前五章按照JDK的类顺序介绍了几种流,第五章讲了Java的文件系统。本章介绍Java的第一个真正意义的流源头:文件流。之前介绍的都是一些流的装饰类,主要作用是更好的处理流的内容,比如缓存,读取内容等。ByteArray流可以说是一个伪源,其接受一个字节数组作为数据源。毫无疑问文件流涉及操作系统的文件,肯定是通过native方法进行读取。下面对其有些什么操作进行介绍。

    2.FileInputStream

      FileInputStream是真正的输入源,不同于其它流,所以其不继承FilterInputStream,而是直接继承抽象父类InputStream。其构造函数如下:

      接收一个文件路径,或者是一个File实例,或者是一个FileDescriptor实例。这个类的介绍看第四小节。

      所有覆写抽象类的方法最终调用的都是native方法,所以也没有什么好说明的。唯一值得说明的就是close方法,其不止调用了native的close方法,还关闭了所有具有相同FileDescriptor实例的流。

    3.FileOutputStream

      FileOutputStream的构造方法和输入流的差不多,但是区别在于多了一个boolean参数,也就是是否是追加模式。了解C语言的都知道,文件写入默认情况下都会丢弃之前文件中的内容,但是对文件也有追加的模式,就是在原内容最后继续写。Java也就是实现了相同的功能,默认也是false,即不追加,覆盖原文件内容。

      除了这一点,其它的也和FileInputStream的情况一样,覆写父类的方法都是调用了native方法,没有什么好讲的地方。

    4 相关类介绍

    4.1 FileDescriptor

      该类的实例被看作成一个不透明的句柄,句柄指向一个底层的机器特定的结构,可能表示一个打开的文件,一个打开的socket套接字,一个其它源或者是一些字节。主要实际的作用是用来创建一个FileInputStream或FileOutputStream实例并持有它。这个类结构比较简单,只有一个空参的构造函数,但是理解起来不太容易。先看一个例子再来理解其使用方法。

        @Test
    	public void test() throws IOException {
    		FileDescriptor descriptor = new FileDescriptor();
    		FileInputStream fis = new FileInputStream(descriptor);
    		try {
    			System.out.println(fis.read());
    		} catch (IOException e) {
    			System.out.println("fis执行异常");
    		} 
    		String path = FileDescriptorTest.class.getClassLoader().getResource("").getPath()+"test.txt";
    		File file = new File(path);
    		fis = new FileInputStream(file);
    		descriptor = fis.getFD();
    		FileInputStream nfis = new FileInputStream(descriptor);
    		System.out.println("nfis>>>"+nfis.read());
    		FileInputStream sfis = new FileInputStream(descriptor);
    		System.out.println("sfis>>>"+sfis.read());
    		System.out.println("nfis>>>"+nfis.read());
    		nfis.close();
    		try {
    			System.out.println("sfis>>>"+sfis.read());
    		} catch(Exception e) {
    			System.out.println("nfis执行异常");
    		}
    		sfis.close();
    		fis.close();
    	}
    

      运行结果是:

      这个例子可以看出几点:1.直接new创建的FileDescriptor实例,生成的流是无效流。2.通过一个有效流获取的FileDescriptor可以用作生成一个新的流。3.所有共用相同FileDescriptor实例的流,其操作是相互影响的,比如A流读了一个字节,B流再读是读取下一个字节,如果A流关闭了,B流也会关闭。这个就是FileDescriptor的作用,其是一个句柄,可以被很多个流实例共享,但是操作是相互影响的。

      代码的逻辑很简单,但是看不出相互关联。网上找了一下,大致的意思是这个类是一个文件描述符或者说是一个句柄。按照我个人的理解就是这个类其实对应着硬件的一个资源,我们所创建的文件流其实只是一个Java实例,其与一个文件句柄相关联。如果不同的流有同一个文件句柄,那么操作就会互相干扰。至于文件句柄对应一个文件,负责真正的文件资源,打开,读取,写入,关闭,不在意是哪个流实例操作的,但是这个会对其它持有相同句柄的Java流产生影响,这个观点可能有所错误,如有清楚的,请指教一下。Java代码中流并没有对这个实例进行操作,只是调用native方法,也就调用attch方法与具体的流实例相互关联了,这个操作是不是JVM管理的不甚清楚。

      

  • 相关阅读:
    高并发系统设计(十九)【注册中心】:微服务架构结合RPC框架如何做到分布式系统寻址?
    高并发系统设计(十八):【RPC框架】10万QPS下如何实现毫秒级的服务调用?
    you-get 库的使用方法
    vue 全局注册signalr
    将Minio.exe注册成windows服务
    NPOI 常用方法封装
    利用NPOI给excel文件中添加图片
    Oss 对象服务存储前端方法封装
    C# 常用方法扩展及封装记录
    PostgreSQL配置密码复杂度策略
  • 原文地址:https://www.cnblogs.com/lighten/p/7001458.html
Copyright © 2011-2022 走看看