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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM