亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java-Io-RandomAccessFile任意位置讀寫數(shù)據(jù)的操作小結(jié)

 更新時間:2022年05月05日 10:57:27   作者:胡安民  
RandomAccessFile類支持隨機訪問方式,可以跳轉(zhuǎn)到文件的任意位置讀寫數(shù)據(jù),這個類在文件隨機讀取時有很大的優(yōu)勢,可利用多線程完成對一個大文件的讀寫,本文給大家介紹Java-Io-RandomAccessFile(任意位置讀寫數(shù)據(jù))的相關(guān)知識,需要的朋友可以參考下

介紹

RandomAccessFile是java語言中最豐富的文件訪問類。RandomAccessFile類支持隨機訪問方式,可以跳轉(zhuǎn)到文件的任意位置讀寫數(shù)據(jù),這個類在文件隨機讀取時有很大的優(yōu)勢,可利用多線程完成對一個大文件的讀寫,利用seek對文件進行切分,從大文件的不同位置開線程進行讀寫。

構(gòu)造,模式,方法

RandomAccessFile他的構(gòu)造函數(shù)只有兩種,所以僅限于操作文件,不能訪問其他io設(shè)備,比如網(wǎng)絡(luò),內(nèi)存映像等。

在這里插入圖片描述

而底層是使用c/c++進行操作的,所以無法進行自定義操作

在這里插入圖片描述

如果RandomAccessFile作為輸出流時,寫出到的文件如果不存在,則在執(zhí)行過程中自動創(chuàng)建 如果寫出到的文件存在,則會對原有文件內(nèi)容進行覆蓋。(默認情況下,從頭覆蓋)

模 式作 用
r表示以只讀方式打開,調(diào)用結(jié)果對象的任何write方法都將導(dǎo)致拋出IOException
rw打開以便讀取和寫入,如果該文件尚不存在,則嘗試創(chuàng)建該文件
rws打開以便讀取和寫入,相對于"rw",還要求對文件內(nèi)容或元數(shù)據(jù)的每個更新都同步寫入到底層存儲設(shè)備
rwd打開以便讀取和寫入,相對于"rw",還要求對文件內(nèi)容的每個更新都同步寫入到底層存儲設(shè)備
方 法作 用
void close()重要,關(guān)閉此隨機訪問文件流并釋放與該流關(guān)聯(lián)的所有系統(tǒng)資源
FileChannel getChannel()返回與此文件關(guān)聯(lián)的唯一FileChannel對象,NIO用到
long getFilePointer()返回此文件中的當(dāng)前偏移量(實時)
long length()返回此文件的長度
int read()從此文件中讀取一個數(shù)據(jù)字節(jié)
int read(byte[] b)將最多b.length個數(shù)據(jù)字節(jié)從此文件讀入byte數(shù)組,返回讀入的總字節(jié)數(shù),如果由于已經(jīng)達到文件末尾而不再有數(shù)據(jù),則返回-1。
int read(byte[] b, int off, int len)將最多l(xiāng)en個數(shù)據(jù)字節(jié)從此文件的指定初始偏移量off讀入byte數(shù)組
boolean readBoolean()從此文件讀取一個boolean,其余readByte()、readChar()、readDouble()等類似
String readLine() 從此文件讀取文本的下一行 (會亂碼)
void seek(long pos) 重要,設(shè)置到此文件開頭測量到的文件指針偏移量,在該位置發(fā)生下一個讀取或?qū)懭氩僮?字節(jié)單位)
int skipBytes(int n)重要,嘗試跳過輸入的n個字節(jié)以丟棄跳過的字節(jié),返回跳過的字節(jié)數(shù)
void write(byte[] b)將b.length個字節(jié)從指定byte數(shù)組寫入到此文件中
void write(byte[] b, int off, int len)將len個字節(jié)從指定byte數(shù)組寫入到此文件,并從偏移量off處開始
void write(int b)向此文件寫入指定的字節(jié)
void writeBoolean(boolean v)按單字節(jié)值將boolean寫入該文件,其余writeByte(int v)、writeBytes(String s)、writeChar(int v)等都類似

問題解決

文件覆蓋改追加

在RandomAccessFile作為輸入流時候,第一次寫的時候會將文件從頭覆蓋,后面在寫就是追加(同一個對象) ,如果想在第一次就追加的話那么就設(shè)置寫的位置w.seek(w.length());這樣就會從文件的最后一個字節(jié)之后開始寫了

try (
         RandomAccessFile r = new RandomAccessFile(new File(readFile), "r");
         RandomAccessFile w = new RandomAccessFile(new File(writeFile), "rw");
        ){
      w.seek(w.length()); // 將指針指向文件最后,進行追加
      byte[] bytes = new byte[1024];
      int len = -1;
      while ((len = r.read(bytes)) != -1) {
        w.write(bytes);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }

案例文件讀寫

 CodeStartAndStopTimeUtil.creator(
        () -> {
          File file = ResourceFileUtil.getFile("mp4/mp4_2.zip");
          String readFile = file.getAbsolutePath();
          String writeFile = file.getParent() + File.separator + "mp4_11112.zip";
          byte[] bytes = new byte[2048];
          try (RandomAccessFile r = new RandomAccessFile(new File(readFile), "r");
              RandomAccessFile w = new RandomAccessFile(new File(writeFile), "rw"); ) {
            int len = -1;
            while ((len = r.read(bytes)) != -1) {
              w.write(bytes);
            }
          }
        });
  }

案例多線程文件讀寫

CodeStartAndStopTimeUtil.creator(
        () -> {
          File file = ResourceFileUtil.getFile("mp4/mp4.zip");
          String readFile = file.getAbsolutePath();
          String writeFile = file.getParent() + File.separator + "mp4_11112.zip";
          long length = new File(readFile).length(); // 文件一共大小
          int num = (int)length/8; // 每個線程讀寫多少字節(jié)   20971520(20mb)  2.5個g4~5秒左右
          List<long[]> longs = DataGroup.dataGroupOnce(length, num);
          List<Future<?>> futures = new ArrayList<>();
          for (long[] aLong : longs) {
            long l = aLong[0]; // 起始位置
            // 創(chuàng)建線程并運行
            Future<?> randomAccessFile =
                ExecutorUtils.createFuture(
                    "RandomAccessFile",
                    () -> {
                      byte[] bytes = new byte[num];
                      try (
                      // 在線程內(nèi)部創(chuàng)RandomAccessFile對象
                      RandomAccessFile r = new RandomAccessFile(new File(readFile), "r");
                      RandomAccessFile w = new RandomAccessFile(new File(writeFile), "rw"); ) {
                        r.seek(l);
                        int len = r.read(bytes);
                        if (len < num) {
                          // 調(diào)整數(shù)組
                          bytes = ArrayByteUtil.getActualBytes(bytes);
                        }
                        // 寫入文件
                        w.seek(l);
                        w.write(bytes);
                        System.out.println(l );
                      } catch (IOException e) {
                        e.printStackTrace();
                      }
                    });
            futures.add(randomAccessFile);
          }
          // 阻塞全部線程執(zhí)行完畢
          ExecutorUtils.waitComplete(futures);
        });

問題

多線程使用RandomAccessFile

常見的使用多線程的場景: 斷點續(xù)傳和斷點下載,或者文件加密解密等

斷點續(xù)傳原理就是:

  • 前端將文件安裝百分比進行計算,每次上傳文件的百分之一(文件分片),給文件分片做上序號
  • 后端將前端每次上傳的文件,放入到緩存目錄
  • 等待前端將全部的文件內(nèi)容都上傳完畢后,發(fā)送一個合并請求
  • 后端使用RandomAccessFile進多線程讀取所有的分片文件,一個線程一個分片
  • 后端每個線程按照序號將分片的文件寫入到目標(biāo)文件中,
  • 在上傳文件的過程中發(fā)生斷網(wǎng)了或者手動暫停了,下次上傳的時候發(fā)送續(xù)傳請求,讓后端刪除最后一個分片
  • 前端重新發(fā)送上次的文件分片

解決readLine亂碼的問題

RandomAccessFile 讀寫文件時,不管文件中保存的數(shù)據(jù)編碼格式是什么 使用 RandomAccessFile對象方法的 readLine() 都會將編碼格式轉(zhuǎn)換成 ISO-8859-1 所以 輸出顯示是還要在進行一次轉(zhuǎn)碼

//需要重新轉(zhuǎn)碼才能正常顯示
   System.out.println( 
   new String(r.readLine().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)
   );

多線程讀寫亂碼的問題

RandomAccessFile對象是不能線程共享的,一個RandomAccessFile對象的文件指針只有一個,多個線程如果都去操作這個指針進行seek的話,那么讀寫就會被來回的跳轉(zhuǎn),導(dǎo)致多個線程的讀寫混亂,所以每個線程必須在線程內(nèi)部創(chuàng)建RandomAccessFile,這樣每個線程都有一個自己的文件指針了, 正確案例

在這里插入圖片描述

到此這篇關(guān)于Java-Io-RandomAccessFile(任意位置讀寫數(shù)據(jù))的文章就介紹到這了,更多相關(guān)Java-Io-RandomAccessFile內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot分頁查詢功能的實現(xiàn)方法

    SpringBoot分頁查詢功能的實現(xiàn)方法

    在實際的項目開發(fā)過程中,分頁顯示是很常見的頁面布局,所以學(xué)習(xí)如何實現(xiàn)分頁也是必要的,下面這篇文章主要給大家介紹了關(guān)于SpringBoot分頁查詢功能的實現(xiàn)方法,需要的朋友可以參考下
    2022-06-06
  • Spring讀取配置文件屬性實現(xiàn)方法

    Spring讀取配置文件屬性實現(xiàn)方法

    這篇文章主要介紹了Spring讀取配置文件屬性實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Java新手學(xué)習(xí)之IO流的簡單使用

    Java新手學(xué)習(xí)之IO流的簡單使用

    IO主要用于設(shè)備之間的數(shù)據(jù)傳輸,Java將操作數(shù)據(jù)流的功能封裝到了IO包中,這篇文章主要給大家介紹了關(guān)于Java新手學(xué)習(xí)之IO流簡單使用的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • java實現(xiàn)快速排序圖文詳解

    java實現(xiàn)快速排序圖文詳解

    網(wǎng)上關(guān)于快速排序的算法原理和算法實現(xiàn)都比較多,不過java是實現(xiàn)并不多,而且部分實現(xiàn)很難理解,和思路有點不搭調(diào)。所以整理了這篇文章。如果有不妥之處還請建議
    2021-08-08
  • 詳解mybatis generator代碼生成器的使用

    詳解mybatis generator代碼生成器的使用

    MyBatis Generator(MBG)是MyBatis MyBatis 和iBATIS的代碼生成器。這篇文章主要介紹了mybatis generator代碼生成器的使用,需要的朋友可以參考下
    2021-09-09
  • java安全停止線程的方法詳解

    java安全停止線程的方法詳解

    這篇文章主要介紹了java安全停止線程的方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • myeclipse10配置tomcat教程詳解

    myeclipse10配置tomcat教程詳解

    這篇文章主要為大家詳細介紹了myeclipse10配置tomcat的教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 深度理解SpringMVC中的HandlerMapping

    深度理解SpringMVC中的HandlerMapping

    這篇文章主要介紹了深度理解SpringMVC中的HandlerMapping,HandlerMapping的作用根據(jù)request找到對應(yīng)的處理器Handler,在HandlerMapping接口中有一個唯一的方法getHanler,需要的朋友可以參考下
    2023-09-09
  • OpenFeign在傳遞參數(shù)為對象類型是為空的問題

    OpenFeign在傳遞參數(shù)為對象類型是為空的問題

    這篇文章主要介紹了OpenFeign在傳遞參數(shù)為對象類型是為空的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Default Methods實例解析

    Default Methods實例解析

    這篇文章主要介紹了Default Methods實例解析,介紹了默認方法的相關(guān)問題,以及與普通方法的區(qū)別,具有一定參考價值,需要的朋友可以了解下。
    2017-09-09

最新評論