1. 程式人生 > >《java程式設計思想——第十八章(Java I/O系統)》

《java程式設計思想——第十八章(Java I/O系統)》

Java I/O系統##

18.1File類

  1. 目錄列表器
File path = new File(".");
list = path.list(); //檢視全部目錄
list = path.list(new DirFilter(args[0]));//檢視受限列表

class DirFilter implements FilenameFilter{
		private Pattern pattern;
		public DirFilter(String regex) {
			pattern = Pattern.compile(regex);
		}
		@Override
		public boolean accept(File dir, String name) {
			
			return pattern.matcher(name).matches();
		}
		
}

策略設計模式:一個類的行為或其演算法可以在執行時更改。這種型別的設計模式屬於行為型模式。

匿名內部類:
引數必須是final 的。

class DirFilter2 {
		public static FilenameFilter filter(final String regex) {
			return new FilenameFilter(){
				Pattern pattern = Pattern.compile(regex);
				@Override
				public boolean accept(File dir, String name) {
					return pattern.matcher(name).matches();
				};
				
			};
		}
	
	}

簡寫方式:

list = path.list( new FilenameFilter(){
				Pattern pattern = Pattern.compile(args[0]);
				@Override
				public boolean accept(File dir, String name) {
					return pattern.matcher(name).matches();
			}
				
});
  1. 目錄實用工具類
  2. 目錄的檢查及建立

18.2 輸入和輸出

  1. InputStream型別
    InputStream表示那些衝不同資料來源產生輸入的類。這些資料域包括:
    位元組陣列,String物件,檔案,管道,一個由其他種類的流組成的序列,其他資料來源(internet連線等).
    在這裡插入圖片描述

  2. OutputStream型別
    該類別的類決定了要去往的目標:位元組陣列,檔案或管道。
    在這裡插入圖片描述

18.3 新增屬性或有用的介面

  1. 通過FilterInputStream從InputStream讀取資料
    在這裡插入圖片描述
  2. 通過FilterOutputStream從OutputStream讀取資料
    在這裡插入圖片描述

18.4 Reader和Writer

Reader和Writer主要是為了支援Unicode。

  1. 資料的來源和去處

18.6 I/O典型使用方式

  1. 緩衝輸入檔案
/**
 * 緩衝輸入檔案
 * @author Administrator
 *
 */
public class BufferedInputFile {
	public static String read(String filename) throws IOException   {
		BufferedReader in = 
				new BufferedReader(new FileReader(filename));
		String s;
		StringBuilder sb = new StringBuilder();
		while ((s = in.readLine()) != null) {
			sb.append(s+"\n");
		}
		in.close();
		return sb.toString();
	}
	public static void main(String[] args) throws IOException {
		String read = read("D:/javadata/workspace/ThinkInJava/src/com/thinkinjava/c18/DirList.java");
		System.out.println(read);
	}
}

  1. 從記憶體讀入
/**
 * 從記憶體讀入
 * @author Administrator
 *
 */
public class MemoryInput {
	public static void main(String[] args) throws IOException {
		String filename = "D:/javadata/workspace/ThinkInJava/src/com/thinkinjava/c18/DirList.java";

		StringReader in = new StringReader(BufferedInputFile.read(filename));
		int c;
		while ((c = in.read()) != -1) {
			System.out.print((char)c);
		}
	}
}
  1. 格式化的記憶體讀入
/**
 *  格式化的記憶體讀入
 * @author Administrator
 *
 */
public class FormitMemoryInput {
	public static void main(String[] args) {
		String filename = "D:/javadata/workspace/ThinkInJava/src/com/thinkinjava/c18/DirList.java";
		try {
			DataInputStream in =  new DataInputStream(new ByteArrayInputStream( BufferedInputFile.read(filename).getBytes()));
			
			while (in.available() != 0) {
				System.out.print((char)in.readByte());
			}
	
		} catch (IOException e) {
		}
		
	}
}
  1. 基本的檔案輸出
/**
 * 基本的檔案輸出
 * @author Administrator
 *
 */
public class BasicFileOutput {
	static String file = "BasicFileOutput.out";
	public static void main(String[] args) throws IOException {
		String filename = "D:/javadata/workspace/ThinkInJava/src/com/thinkinjava/c18/DirList.java";

		BufferedReader in = 
				new BufferedReader(new StringReader(
						BufferedInputFile.read(filename)));
		PrintWriter out = 
				new PrintWriter(new BufferedWriter(new FileWriter(file)));
		int linecount = 0;
		String s;
		while ((s = in.readLine()) != null) {
			out.println(linecount++ +":" +s);
		}
		out.close();
		System.out.println(BufferedInputFile.read(filename));
	}
}
  1. 儲存和恢復資料
public class StoringAndRecoveringData {
  public static void main(String[] args)
  throws IOException {
    DataOutputStream out = new DataOutputStream(
      new BufferedOutputStream(
        new FileOutputStream("Data.txt")));
    out.writeDouble(3.14159);
    out.writeUTF("That was pi");
    out.writeDouble(1.41413);
    out.writeUTF("Square root of 2");
    out.close();
    DataInputStream in = new DataInputStream(
      new BufferedInputStream(
        new FileInputStream("Data.txt")));
    System.out.println(in.readDouble());
    // Only readUTF() will recover the
    // Java-UTF String properly:
    System.out.println(in.readUTF());
    System.out.println(in.readDouble());
    System.out.println(in.readUTF());
  }
}
  1. 讀寫隨機訪問檔案
/**
 * 讀寫隨機訪問檔案
 * @author Administrator
 *
 */
public class UsingRandomAccessFile {
  static String file = "rtest.dat";
  static void display() throws IOException {
    RandomAccessFile rf = new RandomAccessFile(file, "r");
    for(int i = 0; i < 7; i++)
      System.out.println(
        "Value " + i + ": " + rf.readDouble());
    System.out.println(rf.readUTF());
    rf.close();
  }
  public static void main(String[] args)
  throws IOException {
    RandomAccessFile rf = new RandomAccessFile(file, "rw");
    for(int i = 0; i < 7; i++)
      rf.writeDouble(i*1.414);
    rf.writeUTF("The end of the file");
    rf.close();
    display();
    rf = new RandomAccessFile(file, "rw");
    rf.seek(5*8);
    rf.writeDouble(47.0001);
    rf.close();
    display();
  }
}
  1. 管道流
    主要用於任務之間的通訊。

18.8 標準I/O

  1. 從標準輸入中讀取
    System.out, System.in, System.err

18.9 程序控制

18.10 新I/O

通道和緩衝器提高了讀取的速度。

public class GetChannel {
	private static final int BSIZE = 1024;
	public static void main(String[] args) throws IOException {
		FileChannel fc = 
				new FileOutputStream("d:/data/data.txt").getChannel();
		fc.write(ByteBuffer.wrap("Some text".getBytes()));
		fc.close();
		
		fc = new RandomAccessFile("d:/data/data.txt", "rw").getChannel();
		
		fc.position(fc.size());
		fc.write(ByteBuffer.wrap("Some more".getBytes()));
		fc.close();
		
		fc = new FileInputStream("d:/data/data.txt").getChannel();
		ByteBuffer buff = ByteBuffer.allocate(BSIZE);
		fc.read(buff);
		buff.flip();
		while (buff.hasRemaining()) {
			System.out.print((char)buff.get());
		}
	}
}

  1. 轉換資料
  2. 獲取基本資料型別
    ByteBuffer通過asShortBuffer等方法獲取在改緩衝器上的檢視,然後使用put()方法放入資料。
  3. 檢視緩衝器
    檢視緩衝器可以讓我們通過某個特定的基本資料型別的視窗檢視其底層的ByteBuffer.
    位元組存放順序:big endian 高位優先 (ByteOrder.BIG_ENDIAN),little endian 低位優先(ByteOrder.LITTLE_ENDIAN)。
  4. 用緩衝器操作資料
    在這裡插入圖片描述
  5. 緩衝器的細節
    6.
  6. 記憶體對映檔案
/**
 * 記憶體對映檔案
 * @author Administrator
 *
 */
public class LargeMappedFiles {
  static int length = 0x8FFFFFF; // 128 MB
  public static void main(String[] args) throws Exception {
    MappedByteBuffer out =
      new RandomAccessFile("test.dat", "rw").getChannel()
      .map(FileChannel.MapMode.READ_WRITE, 0, length);
    for(int i = 0; i < length; i++)
      out.put((byte)'x');
    print("Finished writing");
    for(int i = length/2; i < length/2 + 6; i++)
      printnb((char)out.get(i));
  }
} 

map()方法產生MappedByteBuffer可以指定對映檔案的初始位置和對映區域長度。
map()的讀寫效率比stream高。
7. 檔案加鎖

/**
 * 檔案加鎖
 * @author Administrator
 *
 */
public class FileLocking {
  public static void main(String[] args) throws Exception {
    FileOutputStream fos= new FileOutputStream("file.txt");
    FileLock fl = fos.getChannel().tryLock();
    if(fl != null) {
      System.out.println("Locked File");
      TimeUnit.MILLISECONDS.sleep(100);
      fl.release();
      System.out.println("Released Lock");
    }
    fos.close();
  }
}

fos.getChannel()呼叫tryLock()或者lock()可以獲得FileLock。
tryLock()是非阻塞式的,lock()是阻塞式的。fl.release()釋放鎖。
也可對對映部分加鎖:

FileLock fl = fc.lock(start, end, false);

18.11 壓縮

  1. 利用Gzip進行壓縮
/**
 * gzip壓縮
 * @author Administrator
 *
 */
public class GZIPcompress {
  public static void main(String[] args)
  throws IOException {
  
    BufferedReader in = new BufferedReader(
      new FileReader("D:/data/data.txt"));
    BufferedOutputStream out = new BufferedOutputStream(
      new GZIPOutputStream(
        new FileOutputStream("test.gz")));
    System.out.println("Writing file");
    int c;
    while((c = in.read()) != -1)
      out.write(c);
    in.close();
    out.close();
    System.out.println("Reading file");
    BufferedReader in2 = new BufferedReader(
      new InputStreamReader(new GZIPInputStream(
        new FileInputStream("test.gz"))));
    String s;
    while((s = in2.readLine()) != null)
      System.out.println(s);
  }
}
  1. 利用zip進行多檔案儲存
/**
 * zip進行多檔案儲存
 * @author Administrator
 *
 */
public class ZipCompress {
  public static void main(String[] args)
  throws IOException {
    FileOutputStream f = new FileOutputStream("test.zip");
    CheckedOutputStream csum =
      new CheckedOutputStream(f, new Adler32());
     ZipOutputStream zos = new ZipOutputStream(csum);
     BufferedOutputStream out =
      new BufferedOutputStream(zos);
    zos.setComment("A test of Java Zipping");
    // No corresponding getComment(), though.
    File file = new File("D:/data/excel");
    String[] list = file.list();
    for(String arg : list) {
      print("Writing file " + arg);
      BufferedReader in =
        new BufferedReader(new FileReader(arg));
      zos.putNextEntry(new ZipEntry(arg));
      int c;
      while((c = in.read()) != -1)
        out.write(c);
      in.close();
      out.flush();
    }
    out.close();
    // Checksum valid only after the file has been closed!
    print("Checksum: " + csum.getChecksum().getValue());
    // Now extract the files:
    print("Reading file");
    FileInputStream fi = new FileInputStream("test.zip");
    CheckedInputStream csumi =
      new CheckedInputStream(fi, new Adler32());
    ZipInputStream in2 = new ZipInputStream(csumi);
    BufferedInputStream bis = new BufferedInputStream(in2);
    ZipEntry ze;
    while((ze = in2.getNextEntry()) != null) {
      print("Reading file " + ze);
      int x;
      while((x = bis.read()) != -1)
        System.out.write(x);
    }
    if(args.length == 1)
    print("Checksum: " + csumi.getChecksum().getValue());
    bis.close();
    // Alternative way to open and read Zip files:
    ZipFile zf = new ZipFile("test.zip");
    Enumeration e = zf.entries();
    while(e.hasMoreElements()) {
      ZipEntry ze2 = (ZipEntry)e.nextElement();
      print("File: " + ze2);

    }
   
  }
} 

18.12 物件序列化

18.13 XML

18.14 XML