1. 程式人生 > >Java讀寫二進制數據

Java讀寫二進制數據

java ets val zipentry har file oid pfile mon

import java.io.*;
import java.time.LocalDate;

public class Test {
    public static void main(String[] args){
        RandomAccessTest.test();
    }
}

/*
    2.3 讀寫二進制數據
 */


/*
    2.3.2 隨機訪問文件
    寫了大半天,突然發現這個實驗好像不是太嚴謹:
        1.RandomAccessFile算長度時,應該是根據字節數算出來的
        2.寫字符串時,我們只是指定了碼元數量,我們寫的是固定碼元數量的字符串
        3.這樣的化,我們記錄的Employee.RECORD_SIZE根本就代表不了一條記錄的長度
        4.但是我們最後又通過RandomAccessFile的長度和Employee.RECORD_SIZE來計算記錄數量
        5.我覺得這個實驗有問題,以後研究吧
 
*/ class Employee { private String name; private double salary; private LocalDate hireDay; public static final int NAME_SIZE = 30; public static final int RECORD_SIZE = 50; public Employee(String name, double salary, LocalDate hireDay) { this.name = name;
this.salary = salary; this.hireDay = hireDay; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double
salary) { this.salary = salary; } public LocalDate getHireDay() { return hireDay; } public void setHireDay(LocalDate hireDay) { this.hireDay = hireDay; } @Override public String toString() { return "Employee{" + "name=‘" + name + ‘\‘‘ + ", salary=" + salary + ", hireDay=" + hireDay + ‘}‘; } } class DataIO { //Java核心技術 卷二 第十版 2.3.2節 //寫出從字符串開頭開始的指定數量的碼元,如果碼元過少,該方法會用‘0’來補齊字符串 public static void writeFixedString(String s, int size, DataOutput output) throws IOException { for (int i = 0; i < size; i++) { char ch =0; if(i<s.length()) ch = s.charAt(i); output.write(ch); } } //Java核心技術 卷二 第十版 2.3.2節 //從輸入流中讀入字符,直至讀入size個碼元,或者直至遇到具有0值的字符串,然後跳出輸入字段中剩余的0值。 public static String readFixedString1(int size, DataInput in) throws IOException { StringBuilder sb = new StringBuilder(); for (int i = 0; i < size; i++) { char c; if ((c = in.readChar()) != 0) { sb.append(c); } } return sb.toString(); } //功能和上一個方法是一樣的,但是這個效率會高那麽一點點 public static String readFixedString2(int size, DataInput in) throws IOException { StringBuilder sb = new StringBuilder(); /* int i; for (i = 0; i < size; i++) { char c; if ((c = in.readChar()) == 0) { break; } sb.append(c); } in.skipBytes(2*(size-i)); //這個地方不是太嚴謹 */ //用書中代碼測試一下 int i =0; boolean more = true; while (more && i < size) { char ch = in.readChar(); i++; if (ch == 0) { more = false; } else { sb.append(ch); } } in.skipBytes(2 * (size - i)); return sb.toString(); } } class RandomAccessTest { public static void test() { Employee[] staff = new Employee[]{ new Employee("A", 10, LocalDate.now()), new Employee("B", 20, LocalDate.now()), new Employee("C", 30, LocalDate.now()) }; //寫入 try(DataOutputStream out = new DataOutputStream(new FileOutputStream("employee1.dat"))) { for (Employee e : staff) { writeData(out, e); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //讀取 try(RandomAccessFile in = new RandomAccessFile("employee1.dat","r")) { int n = (int) (in.length() / Employee.RECORD_SIZE); Employee[] newStaff = new Employee[n]; for (int i = n - 1; i >= 0; i--) { in.seek(i*Employee.RECORD_SIZE); newStaff[i] = readDate(in); } for (Employee e : newStaff) { System.out.println(e); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private static void writeData(DataOutput out, Employee employee) throws IOException { DataIO.writeFixedString(employee.getName(), Employee.NAME_SIZE, out); out.writeDouble(employee.getSalary()); LocalDate hireDay = employee.getHireDay(); out.writeInt(hireDay.getYear()); out.writeInt(hireDay.getMonthValue()); out.writeInt(hireDay.getDayOfMonth()); } private static Employee readDate(DataInput input) throws IOException { String name = DataIO.readFixedString2(Employee.NAME_SIZE, input); double salary = input.readDouble(); int y= input.readInt(), m= input.readInt(), d= input.readInt(); return new Employee(name, salary, LocalDate.of(y, m, d)); } } /* 2.3.3 ZIP文檔 ZipFile API: ZipFile(String name) ZipFile(File file) Enumeration entries() ZipEntry getEntry(String name) InputStream getInputStream(ZipEntry ze) String getName() 從這個類的API中可以看出來,還有一種使用Zip的方案。先通過ZipFile對象,得到 這個壓縮包中的每一條記錄,然後再指定某條具體的記錄,得到其中的數據。 */

《Java核心技術卷二》筆記

Java讀寫二進制數據