zoukankan      html  css  js  c++  java
  • java基础学习_io流之FileInputStream

    一。FileInputStream属性:

    /* File Descriptor - handle to the open file */
    private final FileDescriptor fd;

    /*用来标识输入流的状态*/

    private final String path; //文件的路径信息 

    private FileChannel channel = null;

    private final Object closeLock = new Object();//关闭时的同步锁 
    private volatile boolean closed = false;

    二。FileInputStream重载了3个构造方法。能够通过以下三种方式初始输入流: 

     

    • public FileInputStream(String name) throws FileNotFoundException; 

    :以路径的方式初始一个输入流。其内部调用的是以下的构造方法 

     public FileInputStream(String name) throws FileNotFoundException {
            this(name != null ? new File(name) : null);//当name不为空,就生成一个File对象 作为FileInputStream(File file)构造函数的参数 
        }
    • public FileInputStream(File file) throws FileNotFoundException; 

    :以File实例的方法初始一个输入流 

    源码为:

     1   public FileInputStream(File file) throws FileNotFoundException {
     2         String name = (file != null ? file.getPath() : null);
     3         SecurityManager security = System.getSecurityManager();
     4         if (security != null) {
     5             security.checkRead(name);
     6         }
     7         if (name == null) {
     8             throw new NullPointerException();
     9         }
    10         if (file.isInvalid()) {
    11             throw new FileNotFoundException("Invalid file path");
    12         }
    13         fd = new FileDescriptor();
    14         fd.attach(this);
    15         path = name;
    16         open(name);
    17     }
    FileInputStream(File file) 构造方法

     构造方法内部解析

     SecurityManager security = System.getSecurityManager();

    其中 当运行未知的Java程序的时候,该程序可能有恶意代码(删除系统文件、重启系统等),为了防止运行恶意代码对系统产生影响,需要对运行的代码的权限进行控制,这时候就要启用Java安全管理器(SecurityManager)。

    1.默认的安全管理器配置文件是 $JAVA_HOME/jre/lib/security/java.policy,即当未指定配置文件时,将会使用该配置。

    使用之前需要启动SecurityManager,启动有两种方式:参数方式、编码方式

        启动程序的时候通过附加参数启动安全管理器:

        -Djava.security.manager

        若要同时指定配置文件的位置那么示例如下:

        -Djava.security.manager -Djava.security.policy="E:/java.policy"
        "="表示这个策略文件将和默认的策略文件一同发挥作用; "=="表示只使用指定的策略文件 。如 -Djava.security.policy==E:/temp/test1.policy或者 -Djava.security.policy=bin/com/test/test1.policy 
        编码方式(不建议):
        System.setSecurityManager(new SecurityManager());

    参数方式启动:

    保存后在运行security就不为null了 ,走进security.checkRead(name); 抛错(使用了默认配置文件)

    
    

     这时候解决方式:(1)关闭安全管理器;(2)赋予该程序读取文件权限

    打开管理器配置文件添加:

    grant { 
    
    permission java.io.FilePermission "C:\Study\*", "read";
    permission java.io.FilePermission "C:\Study\2401.jpg_wh1200.jpg", "write";
    
    };

    给程序添加文件读权限

    其中    permission java.io.FilePermission "C:Study2401.jpg_wh1200.jpg", "read";    一个反斜杠是错误的

    权限项中出现的项目必须按指定顺序出现(permission,permission_class_name,”target_name”,”action” 和 signedBy “signer_names”)。分号表示项终止。

    大小写对于标识符(permission、signedBy、codeBase 等)来说并不重要,但对于 permission_class_name 或作为值传递过来的字符串而言就很重要了。

    有关 Windows 系统上文件路径规范的注意事项

    请注意:在指定 java.io.FilePermission 时,”target_name” 是文件路径。在 Windows 系统上,无论何时在字符串中(而不是在 codeBase URL 中)直接指定文件路径,路径中都需要两个反斜杠来代表一个实际的反斜杠;

    • public FileInputStream(FileDescriptor fdObj)

    :以FileDescriptor实例初始一个输入流(FileDescriptor是一个文件描写叙述符

    FileDescriptor:文件描述符类的实例用作表示打开文件,开放套接字或其他字节源或信宿的底层机器特定结构的不透明句柄。 文件描述符的主要实际用途是创建一个FileInputStreamFileOutputStream来包含它。

    三。FileInputStream方法

    int available()
    返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。
     
    void close()
    关闭此文件输入流并释放与流相关联的任何系统资源。
     
    protected void finalize()
    确保当这个文件输入流的 close方法没有更多的引用时被调用。
     
    FileChannel getChannel()
    返回与此文件输入流相关联的唯一的FileChannel对象。

    https://www.cnblogs.com/duanxz/p/6759814.html

    关于FileChannel可以参考以上博客

    FileDescriptor getFD()
    返回表示与此 FileInputStream正在使用的文件系统中实际文件的连接的 FileDescriptor对象。
     
    int read()
    从该输入流读取一个字节的数据。
     
    int read(byte[] b)
    从该输入流读取最多 b.length个字节的数据为字节数组。
     
    int read(byte[] b, int off, int len)
    从该输入流读取最多 len字节的数据为字节数组。
     
    long skip(long n)
    跳过并从输入流中丢弃 n字节的数据。
     

    available():要一次读取多个字节时,经常用到InputStream.available()方法,这个方法可以在读写操作前先得知数据流里有多少个字节可以读取。需要注意的是,如果这个方法用在从本地文件读取数据时,一般不会遇到问题,但如果是用于网络操作,就经常会遇到一些麻烦。比如,Socket通讯时,对方明明发来了1000个字节,但是自己的程序调用available()方法却只得到900,或者100,甚至是0,感觉有点莫名其妙,怎么也找不到原因。其实,这是因为网络通讯往往是间断性的,一串字节往往分几批进行发送。本地程序调用available()方法有时得到0,这可能是对方还没有响应,也可能是对方已经响应了,但是数据还没有送达本地。对方发送了1000个字节给你,也许分成3批到达,这你就要调用3次available()方法才能将数据总数全部得到。能否使用取决于实现了InputStream这个抽象类的具体子类中有没有实现available这个方法。如果实现了那么就可以取得大小,如果没有实现那么就获取不到。例如FileInputStream就实现了available方法,那么就可以用new byte[in.available()];这种方式。但是,网络编程的时候Socket中取到的InputStream,就没有实现这个方法,那么就不可以使用这种方式创建数组。

    public static void main(String[] args) {
                 String name="C:\Study\2401.jpg_wh1200.jpg";
    //        inputStream();
            /*Person per=new Student();
            per.doSomething();*/
            FileInputStream fis=null;
            try {
                File file=new File(name);
                fis=new FileInputStream(file);
                int available = fis.available();
                System.out.println(available);
                long n=500000;
                fis.skip(n);
                int available2 = fis.available();
                System.out.println("available2 is  "+available2 );
                
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            }finally {
                if(fis!= null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    控制台执行结果:

    532598
    available2 is 32598

    read()方法:从此输入流中每次只读取读取一个数据字节。如果没有输入可用,则此方法将阻塞。 指定者:类 InputStream 中的 read  返回:下一个数据字节;如果已到达文件末尾,则返回 -1。

    1、此方法是从输入流中读取一个数据的字节,效率会非常低,更好的方法是用InputStream.read(byte[] b)或者InputStream.read(byte[] b,int off,int len)方法,一次读取多个字节。通俗点讲,即每调用一次read方法,从FileInputStream中读取一个字节。

      2、返回下一个数据字节,如果已达到文件末尾,返回-1,这点除看难以理解,通过代码测试理解不难。

    3、如果没有输入可用,则此方法将阻塞。这不用多解释,大家在学习的时候,用到的Scannner sc = new Scanner(System.in);其中System.in就是InputStream(为什么?不明白的,请到System.class查阅in是个什么东西!!),大家都深有体会,执行到此句代码时,将等待用户输入   摘自 JAVA-FileInputStream之read方法 博客

    本地测试代码如下:

    public class Test1   {
        
        private static String name="C:\Study\output.txt";
        @Test
        public void Test1() {
    
            FileInputStream file=null;
            int i=0; //调用read()次数
            try {
                file=new FileInputStream(name);
                int read =0;
                System.out.println("available is :"+file.available());//
                while(read != -1) {返回从此输入流中可以读取(或跳过)的剩余字节数的估计值  该文件输入流值为:68
                    read= file.read();
                    i++;
                    System.out.println(read+"    and   i="+i);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }catch (IOException e) {
                e.printStackTrace();
            }finally {
                if( file != null ) {
                    try {
                        file.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
        

    控制台输出结果为:

    available is :68
    228    and   i=1
    189    and   i=2
    160    and   i=3
    229    and   i=4
    165    and   i=5
    189    and   i=6
    239    and   i=7
    188    and   i=8
    140    and   i=9
    230    and   i=10
    136    and   i=11
    145    and   i=12
    230    and   i=13
    152    and   i=14
    175    and   i=15
    229    and   i=16
    188    and   i=17
    160    and   i=18
    228    and   i=19
    184    and   i=20
    137    and   i=21
    32    and   i=22
    230    and   i=23
    136    and   i=24
    145    and   i=25
    228    and   i=26
    187    and   i=27
    138    and   i=28
    229    and   i=29
    164    and   i=30
    169    and   i=31
    229    and   i=32
    190    and   i=33
    136    and   i=34
    229    and   i=35
    188    and   i=36
    128    and   i=37
    229    and   i=38
    191    and   i=39
    131    and   i=40
    229    and   i=41
    146    and   i=42
    140    and   i=43
    228    and   i=44
    189    and   i=45
    160    and   i=46
    231    and   i=47
    186    and   i=48
    166    and   i=49
    228    and   i=50
    188    and   i=51
    154    and   i=52
    32    and   i=53
    232    and   i=54
    175    and   i=55
    183    and   i=56
    229    and   i=57
    164    and   i=58
    154    and   i=59
    229    and   i=60
    164    and   i=61
    154    and   i=62
    230    and   i=63
    140    and   i=64
    135    and   i=65
    230    and   i=66
    149    and   i=67
    153    and   i=68
    -1    and   i=69
    控制台数据结果

    对于文件系统中的文件。都能够使用FileInputStream流类以二进制的形式进行读取。可是因为Java本身的定位在JVM之上,没有处理计算机底层的能力。因此一些涉及底层处理的方法都是使用native方法调用第三方底层语言进行处理的。 

    • private static native void initIDs(); 
    • private native void close0() throws IOException; 
    • private native void open0(String name) throws FileNotFoundException;   :打开文件 
    • private native int read0() throws IOException;   :读取一个字节
    • private native int readBytes(byte b[], int off, int len) throws IOException;  :读取指定字节数  
    • public native long skip(long n) throws IOException;     丢弃指定字节,下次读取时,从丢弃后的位置開始读取 
    • public native int available() throws IOException; 

    FileInputStream内部,有几个native类型的方法,用于调用底层语言来完整对于文件系统的操作: 

    FileInputStream流类内部提供了一种对于文件操作的机制,可是因为Java语言的局限,FileInputStream须要通过native方法调用底层语言实现

    Java层调用Native层函数两种方式

    什么是native

     

  • 相关阅读:
    能帮你找到网页设计灵感的16个网站
    [转]自定义SqlMembershipProvider方法
    C#实现的根据年月日计算星期几的函数
    分享一个我自己写的支持多条件组合查询的分页存储过程
    史上最强的福克斯遥控钥匙失灵解决方案(zt)
    在页面实现数据还原,在终止数据库进程时,报不能用kill来终结自己的进程
    ViewState使用兼谈序列化
    jQuery 的上传图片预览插件
    Asp.net 备份、还原Ms SQLServer及压缩Access数据库
    aspnet_Membership表的意义
  • 原文地址:https://www.cnblogs.com/shaoxiaohuan/p/11273273.html
Copyright © 2011-2022 走看看