接口保存返回流


最近在做一個需求時,遇到流的問題,在這總結下:
需求是,我要調別人的接口,對方給我返回一個pdf的電子發票流,我接收后進行保存到本地
首先貼一張猿友的圖,

IO流分兩種;字符流&字節流

 

百度===>字節流和字符流

 

什么是流
流是個抽象的概念,是對輸入輸出設備的抽象,輸入流可以看作一個輸入通道,輸出流可以看作一個輸出通道。
輸入流是相對程序而言的,外部傳入數據給程序需要借助輸入流。
輸出流是相對程序而言的,程序把數據傳輸到外部需要借助輸出流。

 

字節流與字符流
字節流是由字節組成的,字符流是由字符組成的

字節與字符
:數據存儲的最小單位。每個二進制數字0或者1就是1個位;
字節:8個位構成一個字節;即:1 byte (字節)= 8 bit(位);
字符:a、A、中、+、*、の......均表示一個字符;一般utf-8 編碼下,一個漢字字符占用3個字節;一般gbk 編碼下,一個漢字字符占用2個字節;

繼續百度
字節數據是二進制形式的,是我們計算機存儲的一種形式;
字符就是我們在各種客戶端看到的各種文字,是內存中的一種狀態;
字節與字符之間差了一個編碼;

 

回到最初的需求,要在別人接口中獲取一個pdf流,那么獲取到的是什么?
我們知道網絡傳輸的都是二級制數據,字符流又不是二級制,那么不論對方是怎么處理的文件,他最終傳給我的一定是字節流。
所以不管接到后怎么處理,反正直接節流就對了,

         // 獲取一個瀏覽器
            DefaultHttpClient httpclient = new DefaultHttpClient();
            // 獲取get請求
            HttpGet httpget = new HttpGet(url);
            // 請求對方服務器
            HttpResponse response = httpclient.execute(httpget);
            // 獲取返回數據
            InputStream inputStream = response.getEntity().getContent();

事實證明了上面的結論,返回的確實是字節流;

 

然后怎么處理呢?
那就直接把字節流保存吧,反正保存后也是字節,

            // new 一個本地文件
            File file = new File("D:\\11111.pdf");
            // 創建相對於程序的輸出流
            OutputStream outputStream = null;
            try {
                outputStream = new FileOutputStream(file);
                // 讀取數據
                byte[] b = new byte[1024];// b - 數據
                int off = 0;// off - 數據中的起始偏移量。
                int len = -1;// len - 要寫入的字節數。
                while ((len = inputStream.read(b)) != -1) {// 從輸入流讀取一些字節數,並將它們存儲到緩沖區b。實際讀取的字節數作為整數返回,如果沒有字節可用,因為流在文件末尾,則返回值-1;否則,讀取至少一個字節並存儲到b。
                    outputStream.write(b, off, len);// 數組b中的一些字節按順序寫入輸出流; 元素off是寫入的第一個字節,len是此操作寫入的最后一個字節。
                }
                outputStream.flush();// 刷新此輸出流並強制任何緩沖的輸出字節被寫出。
            } catch (IOException e) {
                System.out.println("異常");
                e.printStackTrace();
            } finally {
                inputStream.close();//關閉此輸入流並釋放與此流相關聯的任何系統資源。
                outputStream.close();//關閉此輸出流並釋放與此流相關聯的任何系統資源。
            }

 

然后嘗試他們的子類們,例:BufferedInputStream 與 BufferedOutputStream

            // 獲取一個瀏覽器
            DefaultHttpClient httpclient = new DefaultHttpClient();
            // 獲取get請求
            HttpGet httpget = new HttpGet(url);
            // 請求對方服務器
            HttpResponse response = httpclient.execute(httpget);
            // 獲取返回數據
            BufferedInputStream inputStream = (BufferedInputStream)response.getEntity().getContent();
            // new 一個本地文件
            File file = new File("D:\\11111.pdf");
            // 創建相對於程序的輸出流
            BufferedOutputStream outputStream = null;
            try {
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                outputStream = new BufferedOutputStream(fileOutputStream);
                // 讀取數據
                byte[] b = new byte[1024];// b - 數據
                int off = 0;// off - 數據中的起始偏移量。
                int len = -1;// len - 要寫入的字節數。
                while ((len = inputStream.read(b)) != -1) {// 從輸入流讀取一些字節數,並將它們存儲到緩沖區b。實際讀取的字節數作為整數返回,如果沒有字節可用,因為流在文件末尾,則返回值-1;否則,讀取至少一個字節並存儲到b。
                    outputStream.write(b, off, len);// 數組b中的一些字節按順序寫入輸出流; 元素off是寫入的第一個字節,len是此操作寫入的最后一個字節。
                }
                outputStream.flush();// 刷新此輸出流並強制任何緩沖的輸出字節被寫出。
            } catch (IOException e) {
                System.out.println("異常");
                e.printStackTrace();
            } finally {
                inputStream.close();//關閉此輸入流並釋放與此流相關聯的任何系統資源。
                outputStream.close();//關閉此輸出流並釋放與此流相關聯的任何系統資源。
            }

他們的子類在使用中並沒有太大的區別,網上扒了下他們各自的特點,至於具體選擇使用哪個類,可以參考這篇文章:https://www.cnblogs.com/penghuster/p/4869153.html

 

*********************************************
*******************字符流*********************
*********************************************

然后,如果接口返回的是字符串應該怎么處理呢,於是我換了一個get地址,返回的是一個字符串。
對於這樣的返回,我們一般情況下肯定是不需要保存的的,肯定是在內存中轉為字符串進行編輯展示什么的,但是為了理解流之間的關系,保存一下試試,

            // 獲取一個瀏覽器
            DefaultHttpClient httpclient = new DefaultHttpClient();
            // 獲取get請求
            HttpGet httpget = new HttpGet(url);
            // 請求對方服務器
            HttpResponse response = httpclient.execute(httpget);
            // 獲取返回數據
            InputStream inputStream = response.getEntity().getContent();
            
            InputStreamReader inputStreamReader = null;
            OutputStreamWriter outputStreamWriter = null;
            try {
                // 將返回的字節流轉為字符流
                inputStreamReader = new InputStreamReader(inputStream,"utf-8");
                // 再將轉出的字符流再轉回字節流保存到磁盤
                File file = new File("D:\\11.txt");// 二級制字節文件
                FileOutputStream fileOutputStream = new FileOutputStream(file);// 用於程序輸出的字節流
                outputStreamWriter = new OutputStreamWriter(fileOutputStream,"utf-8");// 將字符流轉為字節流
                // 讀取數據
                char[] chars = new char[1024];
                int off =0;
                int len = -1;
                while ((len=inputStreamReader.read(chars))!=-1){
                    System.out.println(len);
                    outputStreamWriter.write(chars,off,len);
                }
            } catch (IOException e) {
                System.out.println("異常");
                e.printStackTrace();
            } finally {
                // 關閉資源
                outputStreamWriter.flush();
                outputStreamWriter.close();
                inputStreamReader.close();
            }

事實證明是可以的,接口返回字節流,然后將字節流轉為我們認識的字符,再將我們認識的字符轉為二進制字節進行保存,基本可以明白流之間的關系了。

 

那么正常情況下怎么轉為字符串打印呢?

       // 獲取一個瀏覽器
            DefaultHttpClient httpclient = new DefaultHttpClient();
            // 獲取get請求
            HttpGet httpget = new HttpGet(url);
            // 請求對方服務器
            HttpResponse response = httpclient.execute(httpget);
            // 獲取返回數據
            InputStream inputStream = response.getEntity().getContent();
            
            InputStreamReader inputStreamReader = null;
            BufferedReader bufferedReader = null;
            try {
                // 將字節流轉為字符流
                inputStreamReader = new InputStreamReader(inputStream,"utf-8");
                // BufferedReader類是從字符輸入流中讀取文本並緩沖字符,以便有效地讀取字符,數組和行
                bufferedReader = new BufferedReader(inputStreamReader);
                // 創建保存字符串的StringBuffer
                StringBuffer str = new StringBuffer();
                String s = null;
                while ((s=bufferedReader.readLine())!=null){
                    str.append(s);
                }
                // 打印
                System.out.println(str.toString());
            } catch (IOException e) {
                System.out.println("異常");
                e.printStackTrace();
            } finally {
                inputStreamReader.close();
                bufferedReader.close();
            }

這里有一點點不用,不再使用輸出流,因為相對於程序沒有寫磁盤嘛,所以用不着輸出流。

使用了BufferedReader ,BufferedReader類是從字符輸入流中讀取文本並緩沖字符,以便有效地讀取字符,數組和行,具體解釋參考:https://blog.csdn.net/ai_bao_zi/article/details/81134801

還用了StringBuffer ,補充一個String,StringBuffer,StringBuilder三者的使用方法和區別:https://blog.csdn.net/qq_37856300/article/details/84340288

 


免責聲明!

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



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