fileinputstream 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) throwsFileNotFoundException {this(name != null ? new File(name) : null);//当name不为空,就生成一个File对象 作为FileInputStream(File file)构造函数的参数

}

public FileInputStream(File file) throws FileNotFoundException;

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

源码为:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public FileInputStream(File file) throwsFileNotFoundException {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 newNullPointerException();9 }10 if(file.isInvalid()) {11 throw new FileNotFoundException("Invalid file path");12 }13 fd = newFileDescriptor();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());

参数方式启动:

048d73b20935f68c78c9bd1214e1619d.png

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

62aca401580a19e2f3018108b2a6826d.png

这时候解决方式:(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:文件描述符类的实例用作表示打开文件,开放套接字或其他字节源或信宿的底层机器特定结构的不透明句柄。 文件描述符的主要实际用途是创建一个FileInputStream或FileOutputStream来包含它。

三。FileInputStream方法

int

available()

返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。

void

关闭此文件输入流并释放与流相关联的任何系统资源。

protected void

确保当这个文件输入流的 close方法没有更多的引用时被调用。

返回表示与此 FileInputStream正在使用的文件系统中实际文件的连接的 FileDescriptor对象。

int

从该输入流读取一个字节的数据。

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 voidmain(String[] args) {

String name="C:\\Study\\2401.jpg_wh1200.jpg";//inputStream();

/*Person per=new Student();

per.doSomething();*/FileInputStream fis=null;try{

File file=newFile(name);

fis=newFileInputStream(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 classTest1 {private static String name="C:\\Study\\output.txt";

@Testpublic voidTest1() {

FileInputStream file=null;int i=0; //调用read()次数

try{

file=newFileInputStream(name);int read =0;

System.out.println("available is :"+file.available());// while(read != -1) {返回从此输入流中可以读取(或跳过)的剩余字节数的估计值 该文件输入流值为:68read=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();

}

}

}

}

}

控制台输出结果为:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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

控制台数据结果

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方法调用底层语言实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值