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:\Study\2401.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

原文地址:https://www.cnblogs.com/shaoxiaohuan/p/11273273.html

时间: 2024-10-19 09:09:13

java基础学习_io流之FileInputStream的相关文章

java基础学习总结——流

永不放弃,一切皆有可能!!! 只为成功找方法,不为失败找借口! java基础学习总结——流 一.JAVA流式输入/输出原理 流是用来读写数据的,java有一个类叫File,它封装的是文件的文件名,只是内存里面的一个对象,真正的文件是在硬盘上的一块空间,在这个文件里面存放着各种各样的数据,我们想读文件里面的数据怎么办呢?是通过一个流的方式来读,咱们要想从程序读数据,对于计算机来说,无论读什么类型的数据都是以010101101010这样的形式读取的.怎么把文件里面的数据读出来呢?你可以把文件想象成一

java 基础学习 IO流 学习总结

File类概述和构造方法: File类的概述 文件和目录路径名的抽象表示形式  构造方法 public File(String pathname) public File(String parent,String child) public File(File parent,String child) 创建功能 public boolean createNewFile() public boolean mkdir() public boolean mkdirs() 删除功能 public boo

JAVA基础学习day22--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码

一.对象序列化 1.1.对象序列化 被操作的对象需要实现Serializable接口 1.2.对象序列化流ObjectOutputStream与ObjectInputStream ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化. ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的

JAVA基础学习---IO流总结

Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作.   IO流的分类 根据处理数据类型的不同分为:字符流和字节流 根据数据流向不同分为:输入流和输出流 字符流和字节流 字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象.本质其实就是基于字节流读取时,去查了指定的码表. 字节流和字符流

JAVA基础学习day21--IO流三-File、Properties、PrintWriter与合并、分割流

一.File 1.1.File概述 文件和目录路径名的抽象表示形式. 用户界面和操作系统使用与系统相关的路径名字符串 来命名文件和目录.此类呈现分层路径名的一个抽象的.与系统无关的视图.抽象路径名 有两个组件: 一个可选的与系统有关的前缀 字符串,比如盘符,"/" 表示 UNIX 中的根目录,"\\\\" 表示 Microsoft Windows UNC 路径名. 零个或更多字符串名称 的序列. 字段摘要 static String pathSeparator 与系

JAVA基础学习day19--IO流一、FileWrite与FileReader

一.IO简述 1.1.简述 IO:input/output IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的对象都在IO包中. 1.2.结构 字节流抽象类: InputStream,OutputStream 字符流抽象类: Reader.Writer. ps:由这四4个派生出来子类名称都是以父类名作为子类名的后缀 如:InputStream的子类FileInputStream 如:Reader的子类FileReader; 1.3.分类 按操作数据方式为两

JAVA基础学习之流的简述及演示案例、用缓冲区方法buffer读写文件、File类对象的使用、Serializable标记接口(6)

1.流的简述及演示案例输入流和输出流相对于内存设备而言.将外设中的数据读取到内存中:输入将内存的数写入到外设中:输出.字符流的由来:其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表.获取对应的文字.在对这个文字进行操作.简单说:字节流+编码表字节流的两个顶层父类:1,InputStream 2,OutputStream.字符流的两个顶层父类:1,Reader 2,Writer String filePath = "F:\\demo.txt"; FileWriter f

Java基础学习总结——Java对象的序列化和反序列化

一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中: 2) 在网络上传送对象的字节序列. 在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存.比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些s

转载:java基础学习总结——java读取properties文件总结

java基础学习总结--java读取properties文件总结 一.java读取properties文件总结 在java项目中,操作properties文件是经常要做的,因为很多的配置信息都会写在properties文件中,这里主要是总结使用getResourceAsStream方法和InputStream流去读取properties文件,使用getResourceAsStream方法去读取properties文件时需要特别注意properties文件路径的写法,测试项目如下: 1.1.项目的