java輸入與輸出
註:本文為作者學習總結,如有錯誤請見諒與及批評指出
1.輸入輸出流
計算機存儲文件在物理上都是以二進制的形式存儲,根據邏輯上的不同一般分為以下兩種:
文本文件:每個字符對應一個ASCII(Unicode)碼,用二進制形式寫入磁盤,即文本與二進制之間是以Unicode(ASCII)等常見編碼方式翻譯。文本編輯器能夠打開文本文件。
二進制文件:磁盤同樣以二進制保存,但是翻譯不再是Unicode(ASCII)等常見編碼方式,不同程序自己定義。文本編輯器打開的是亂碼文件。
文本文件用字符流(基於字符char)進行讀寫,二進制文件用字節流(基於字節byte)進行讀寫。圖1為常見的字節流各個類,圖2為常見的字符流各個類,圖3為輸入輸出流中常用的一些接口。
圖1 常見字節流層次結構
圖2 常見字符流層次結構
圖3 輸入輸出流常見接口
2.文本文件讀寫
Reader(抽象類)是字符輸入流的父類,Writer(抽象類)是字符輸出流的父類。字符流是以字符(char)為單位讀寫數據的,一次處理一個unicode,且其底層仍然是基本的字節流。通俗的說,寫入時采用某種編碼方式把字符轉換成二進制存入磁盤中,讀取時按照同樣的編碼方式把二進制讀取出來並且轉換成字符。因此,字符流只能操作文本文件。
2.0 字符轉換流原理
InputStreamReader:可以設置字符集,按照此編碼方式將字節轉換為字符並且讀取。構造函數:InputStreamReader(InputStream in,String charsetName)和InputStreamReader(InputStream in)--系統默認字符集
OutputStreamWriter:可以設置字符集,按照此編碼方式將字符轉換為字節並且寫出。構造函數:OutputStreamWriter(OutputStream out,String charsetName)和OutputStreamWriter(OutputStream out)--系統默認字符集
2.1 文本輸出(PrintWriter)
常見構造器:
PrintWriter(File file) PrintWriter(String filename) PrintWriter(File file,String encoding) PrintWriter(String filename,String encoding) PrintWriter(Writer writer) PrintWriter(Writer writer,boolean autoFlush) PrintWriter(OutputStream out) PrintWriter(OutputStream out,boolean autoFlush)
常見方法:
void print(Object obj) //打印obj的toString後的字符串 void print(String s) void println(String s) void print(char[] s) void print(char c) void print(int i) void print(long l) void print(float f) void print(double d) void print(boolean b) //以文本格式打印 void print(String format,Object... args) //按指定格式打印字符串
例子:
PrintWriter out=new PrintWriter("C:\\Users\\Administrator\\Desktop\\raf.dat","UTF-8"); PrintWriter out=new PrintWriter(new OutputStreamWriter(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\raf.dat"),"UTF-8"),true);
2.2 文本讀入
(1)Scanner類(Scanner(InputStream in,String charsetName))
try(Scanner in=new Scanner(new FileInputStream("C:\\Users\\Administrator\\Desktop\\raf.dat"),"UTF-8"))
{ while(in.hasNextLine()){ System.out.println(in.nextLine()); } }
(2)短小文本讀入一個字符串中
String content=new String(Files.readAllBytes(Paths.get("C:\\Users\\Administrator\\Desktop\\raf.dat")),"UTF-8");
(3)短小文本一行一行地讀
List<String> lines=Files.readAllLines(Paths.get("C:\\Users\\Administrator\\Desktop\\raf.dat"),StandardCharsets.UTF_8); for(String s:lines){ System.out.println(s); }
(4)大文件將行惰性處理成一個Stream<String>對象(JDK1.8)
try(Stream<String> lines=Files.lines(Paths.get("C:\\Users\\Administrator\\Desktop\\raf.dat"),StandardCharsets.UTF_8)){ ... }
(5)BufferedReader類
FileInputStream fin=new FileInputStream("C:\\Users\\Administrator\\Desktop\\raf.dat"); InputStreamReader isr=new InputStreamReader(fin,StandardCharsets.UTF_8); try(BufferedReader in=new BufferedReader(isr);){ String line; while((line=in.readLine())!=null){ System.out.println(line); } }
3.二進制文件讀寫
3.0 DataInput和DataOutput接口
DataInput接口:用於讀取二進制格式的數字(組)、字符、boolean和字符串。
常用方法:writeByte、writeInt、writeShort、writeLong、writeFloat、writeDouble、writeChar、writeBoolean、writeChars、writeUTF(只在寫出用於java虛擬機的字符串)
DataOutput接口:用於以二進制格式寫數字(組)、字符、boolean和字符串。
常用方法:readByte、readInt、readShort、readLong、readFloat、readDouble、readChar、readBoolean、readUTF、skipBytes(int n)
3.1 DataInputStream和DataOutputStream實現讀寫
try(DataOutputStream out=new DataOutputStream(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\raf.dat"))){ out.writeInt(222); out.writeDouble(222.22); out.writeUTF("郭無"); } //////////////////////////////////////////////////////////////////////// try(DataInputStream in=new DataInputStream(new FileInputStream("C:\\Users\\Administrator\\Desktop\\raf.dat"))){ System.out.println(in.readInt()+","+in.readDouble()+","+in.readUTF()); }
3.2 RandomAccessFile實現讀寫
RandomAccessFile同時實現了DataInput和DataOutput接口,可以使用構造器第二個參數r/rw指定打開方式。有一個表示下一個將被讀入或者寫出的字節所處位置的文件指針。
常用構造器:
RandomAccessFile(File file,String mode) RandomAccessFile(String filename,String mode) //mode:r rw
額外常用方法:
seek(Long long):把文件指針設置到任意字節位置(0到文件字節長度) getFilePointer:返回文件指針當前位置 length()文件字節總數
skipBytes(int n):跳過n個字節
例子:
try(RandomAccessFile raf=new RandomAccessFile("C:\\Users\\Administrator\\Desktop\\raf.dat","rw")){ raf.writeInt(123); raf.writeDouble(123.56); raf.writeUTF("郭文景"); } ///////////////////////////////////////////////////////////////////////////////// try(RandomAccessFile raf=new RandomAccessFile("C:\\Users\\Administrator\\Desktop\\raf.dat","rw")){ System.out.println(raf.readInt()+","+raf.readDouble()+","+raf.readUTF()); }
3.3 ZIP文檔
java操作zip文檔主要涉及以下四個類:ZipInputStream、ZipOutStream、ZipEntry、ZipFile
(1)寫入zip文件
FileOutputStream fOutputStream = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\gwj1.zip"); ZipOutputStream zoutput = new ZipOutputStream(fOutputStream); String line="gwj"; for(int i=0;i<3;i++){ byte[] bytes=(line+i).getBytes(); ZipEntry zEntry = new ZipEntry("no"+i+".txt"); zoutput.putNextEntry(zEntry); zoutput.write(bytes); zoutput.closeEntry(); } zoutput.close();
(2)讀取zip文件(ZipFile和ZipInputStream都行)
ZipFile zipfile=new ZipFile("C:\\Users\\Administrator\\Desktop\\gwj1.zip"); ZipEntry entry; Enumeration e = zipfile.entries(); while(e.hasMoreElements()){ entry = (ZipEntry) e.nextElement(); System.out.println("-------"+entry.getName()+"-------"); InputStreamReader isr=new InputStreamReader(zipfile.getInputStream(entry),StandardCharsets.UTF_8); try(BufferedReader in=new BufferedReader(isr);){ String line; while((line=in.readLine())!=null){ System.out.println(line); } } }
3.4 對象系列化
(1)對象系列化使用
Employee harry = new Employee("Harry Hacker", 50000, 1989, 10, 1); Manager carl = new Manager("Carl Cracker", 80000, 1987, 12, 15); carl.setSecretary(harry); Manager tony = new Manager("Tony Tester", 40000, 1990, 3, 15); tony.setSecretary(harry); Employee[] staff = new Employee[3]; staff[0] = carl; staff[1] = harry; staff[2] = tony; String name="郭文景"; // save all employee records to the file employee.dat try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\employee.dat"))) { out.writeObject(staff); out.writeUTF(name); } try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("C:\\Users\\Administrator\\Desktop\\employee.dat"))) { Employee[] newStaff = (Employee[]) in.readObject(); newStaff[1].raiseSalary(10); for (Employee e : newStaff) System.out.println(e); System.out.println(in.readUTF()); }
註:Employee需要實現Serializable接口。Employee implements Serializable
(2)對象系列化原理
- 對象系列化的文件格式
java輸入與輸出