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管理的不甚清楚。

      

  • 相关阅读:
    我的浏览器收藏夹分类
    我的浏览器收藏夹分类
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
  • 原文地址:https://www.cnblogs.com/lighten/p/7001458.html
Copyright © 2011-2022 走看看