1. 程式人生 > >java輸入與輸出

java輸入與輸出

adb int files poi 都是 ext 函數 arr imp

註:本文為作者學習總結,如有錯誤請見諒與及批評指出

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輸入與輸出