您好,登錄后才能下訂單哦!
這篇文章運用簡單易懂的例子給大家介紹Java如何實現(xiàn)讀取二進制文件,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
由于項目需要,需要對二進制文件進行讀寫、轉(zhuǎn)換。
文件說明:由其他程序得到的二進制文件,文件內(nèi)容為:包含23543個三角形、13270個頂點的三角網(wǎng)所對應的721組流速矢量(u、v)文件,通俗些說,一條數(shù)據(jù)包含兩個雙精度型的數(shù)值,每組數(shù)組包含23543條數(shù)據(jù),如果以一個雙精度數(shù)值為單位,則總共有23543 * 721 * 2 =33,949,006條數(shù)據(jù)。由Fortran程序以每 8 Byte存儲一個數(shù)值的二進制文件存儲,最終文件大小為下圖所示:
測試:從該文件讀出數(shù)據(jù)之后,轉(zhuǎn)換為十進制,存儲到另一個文件中。
/** * 針對大文件存儲,請依次調(diào)用beginSave、AddSave、endSave。 * * @author CK * */ public class DataUtil { DataOutputStream BinaryOut=null; BufferedWriter TextOut=null; String FilePath=null; enum SaveFileType{Text,Binary}; SaveFileType SaveFileType; /** * double轉(zhuǎn)byte[] * * @param d * @return */ public static byte[] double2Bytes(double d) { long value = Double.doubleToRawLongBits(d); byte[] byteRet = new byte[8]; for (int i = 0; i < 8; i++) { byteRet[i] = (byte) ((value >> 8 * i) & 0xff); } return byteRet; } /** * byte[]轉(zhuǎn)double * * @param arr * @return */ public static double bytes2Double(byte[] arr) { long value = 0; for (int i = 0; i < 8; i++) { value |= ((long) (arr[i] & 0xff)) << (8 * i); } return Double.longBitsToDouble(value); } /** * 大型數(shù)據(jù)存儲之開始存儲 * @param FilePath 文件路徑 * @param saveFileType 保存的文件類型,文本文件、雙精度所存的二進制文件 * @return * @throws IOException */ public boolean BeginSave(String FilePath,SaveFileType saveFileType) throws IOException { if (FilePath == "" || FilePath == null) { System.out.println("the SavePath is null."); return false; } this.FilePath=FilePath; this.SaveFileType=saveFileType; File dataFile = new File(FilePath); if (!dataFile.getParentFile().exists()) { dataFile.getParentFile().mkdirs(); } if (dataFile.exists()) { dataFile.delete(); } dataFile.createNewFile(); switch(this.SaveFileType){ case Text: TextOut= new BufferedWriter(new FileWriter(dataFile,true)); break; case Binary: BinaryOut = new DataOutputStream(new FileOutputStream(dataFile,true)); break; default: break; } return true; } /** * 大型文件存儲之追加存儲 * @param DataStr 若是文本存儲則無要求,若是雙精度的二進制文件,以若干空格隔開 * @return * @throws IOException */ public boolean AddSave(String DataStr) throws IOException{ switch(this.SaveFileType){ case Text: this.TextOut.append(DataStr); break; case Binary: DataStr=DataStr.trim(); String[] dataArray=DataStr.split("\\s+"); for(int i=0;i<dataArray.length;i++){ this.BinaryOut.write(double2Bytes(Double.parseDouble(dataArray[i]))); } break; default: break; } return true; } /** * 大型文件存儲之結(jié)束保存,清空緩存、關(guān)閉文件。 * @return * @throws IOException */ public boolean EndSave() throws IOException{ switch(this.SaveFileType){ case Text: this.TextOut.flush(); this.TextOut.close(); break; case Binary: this.BinaryOut.flush(); this.BinaryOut.close(); break; default: break; } return true; } /** * 將字符串保存為文本文件(一次完成) * * @param DataStr * 文件內(nèi)容 * @param SavePath * 文件路徑,包含文件名、后綴 * @return * @throws IOException */ public boolean saveTextFile(String DataStr, String SavePath) throws IOException { if (DataStr == "" || DataStr == null) { System.out.println("the dataStr is null."); return false; } if (SavePath == "" || SavePath == null) { System.out.println("the SavePath is null."); return false; } File dataFile = new File(SavePath); if (!dataFile.getParentFile().exists()) { dataFile.getParentFile().mkdirs(); } if (dataFile.exists()) { dataFile.delete(); } dataFile.createNewFile(); BufferedWriter out; out = new BufferedWriter(new FileWriter(dataFile)); out.append(DataStr); out.flush(); out.close(); return true; } /** * 雙精度存為二進制數(shù)據(jù)(一次存儲) * * @param DataStr 雙精度數(shù)據(jù)組成的字符串,以若干空格隔開 * @param OutputPath * @return * @throws IOException */ public boolean saveBinaryFile(String DataStr, String OutputPath) throws IOException { if (DataStr == "" || DataStr == null) { System.out.println("the dataStr is null."); return false; } if (OutputPath == "" || OutputPath == null) { System.out.println("the OutputPath is null."); return false; } File dataFile = new File(OutputPath); if (!dataFile.getParentFile().exists()) { dataFile.getParentFile().mkdirs(); } if (dataFile.exists()) { dataFile.delete(); } dataFile.createNewFile(); DataOutputStream out; out = new DataOutputStream(new FileOutputStream(dataFile)); // 數(shù)據(jù)處理 DataStr=DataStr.trim(); String[] dataArray=DataStr.split("\\s+"); for(int i=0;i<dataArray.length;i++){ out.write(double2Bytes(Double.parseDouble(dataArray[i]))); } out.flush(); out.close(); return true; } }
代碼說明:其中byte[]與double互轉(zhuǎn)為在互聯(lián)網(wǎng)上查到的方法,具體是哪位大神的我忘記了,在這里為了記錄就貼出來啦,上述代碼包含了處理小型文件時,將所有內(nèi)容存在緩存中,之后再一次性寫入文本文件、二進制文件中的方法,還包含了對較大型文件的讀寫方法,下面是自己的一個讀寫測試。
/** * 測試二進制大文件讀寫(200M左右) * @author ck * */ public class FileTest { static String inputFilePath=""; //輸入文件路徑,包含文件名后綴 static String outputFilePath=""; //輸出文件名,包含文件名后綴 public static void file2file() throws IOException{ DataUtil dataUtil=new DataUtil(); DataInputStream br=new DataInputStream( new BufferedInputStream( new FileInputStream(inputFilePath))); dataUtil.BeginSave(outputFilePath, SaveFileType.Text); //初始化,創(chuàng)建文件,采用文件追加存儲的思路 byte[] oneData=new byte[8]; int i=0,count =0 ; while(br.read(oneData, 0, 8)!=-1){ i=i+1; dataUtil.AddSave(String.valueOf(DataUtil.bytes2Double(oneData))); if(i/23543==0){ count++; System.out.println(count+"\n"); } } dataUtil.EndSave(); //將還在緩存中的數(shù)據(jù)寫入到文件中,關(guān)閉文件。 } }
此次測試代碼很快就run完了,但是輸出文件的生成大概用了近半分鐘(刻意秒表計時了一次),嘗試用一次性讀寫的辦法,卡很久,也沒有出結(jié)果。所得的十進制文本文件,大小為這么多:
關(guān)于Java如何實現(xiàn)讀取二進制文件就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。