JAVA 复习(Think In Java, 4th) -- File I/O -- Part 1

来源:互联网 发布:杭州淘宝大学在哪里 编辑:程序博客网 时间:2024/05/19 12:11

File 类的 list() 方法,会将该路径下的所有档案(file)、文件夹(directory)等都列出来,比如说下面的代码便是用递归(recursive)的方式,在特定路径下,去列出包含特定字符串的档名。(後来看了下,其实用 File类的 listFiles() 去实现会更方便些 Orz ) 

private static void searchFiles(String filePath, String keyword) {File f = new File(filePath);String[] files = f.list();if (files == null) {return;}for (String file : files) {StringBuilder sb = new StringBuilder(filePath);sb.append('/').append(file);String newPath = sb.toString();File g = new File(newPath);if (g.isDirectory()) {searchFiles(newPath, keyword);} else {if (file.contains(keyword)) {System.out.println(newPath);}}}}

设计 Reader和 Writer等类主要就是为了支持国际化,旧的 I/O 流结构只支持8位字节流。由於 Unicode用於字符国际化( Java 本身的 char也是 16位 Unicode,和 C语言的 8位元Char并不同,详阅http://www.kuqin.com/shuoit/20141102/343002.html)大多数情况下,我们一般采用面向字符的方式读写,但是也有例外的情况,比如说 zip相关的读写。我们可以使用 FileReader 类来读取档案内容,然後使用 BufferedReader 来做缓冲,这样能提高 I/O 的效率,下面这例子便是将一个档案的内容打印出来的方法。同时,我们为了确保每次能将 BufferedReader 类关闭,避免因为发生异常,而没有关闭(调用 close()),导致内存泄漏的情况,所以我们在范例中做了如下的処理:

private static void cat(String filePath) {if (filePath == null || filePath.isEmpty()) {System.out.println("No file path specified");return;}BufferedReader br = null;try {br = new BufferedReader(new FileReader(filePath));StringBuilder sb = new StringBuilder();String s;while ((s = br.readLine()) != null) {s = s.toUpperCase();sb.append(s + '\n');}System.out.print(sb.toString());} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {closeReader(br);}}private static void closeReader(Closeable reader) {if (reader == null)return;try {reader.close();} catch (IOException e) {// do nothing}}

从内存输入

我们用 StringReader将档案内容读入到内存中,再用 StringReader 一一自内存中读出

下面是个简单范例:

private static void catWithString(final String filePath) {StringReader sr = new StringReader(cat(filePath));int in;try {while ((in = sr.read()) != -1) {System.out.print((char) in);}} catch (IOException e) {// do nothing}}private static String cat(String filePath) {String result = "";if (filePath == null || filePath.isEmpty()) {System.out.println("No file path specified");return result;}BufferedReader br = null;try {br = new BufferedReader(new FileReader(filePath));StringBuilder sb = new StringBuilder();String s;while ((s = br.readLine()) != null) {sb.append(s + '\n');}result = sb.toString();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {closeClosable(br);}return result;}private static void closeClosable(Closeable reader) {if (reader == null)return;try {reader.close();} catch (IOException e) {// do nothing}}

我们也能将字符串转成 byte以後,导入 ByteArrayInputStream,再使用 DataInputStream 去读取,范例如下:

private static void catWithByte(final String filePath) {DataInputStream dis = new DataInputStream(new ByteArrayInputStream(cat(filePath).getBytes()));char c = 0;try {while (dis.available() > 0) {c = (char) dis.readByte();System.out.print(c);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}

储存文件,有分成二种,以 Binary 的方式或者是以可读字符串内容的方式,先介绍用可读字符串内容的写入档案的方式,从下面的范例可以看出,首先是用 FileWriter开启一个新档案准备写入,再使用 BufferWriter 来作缓存,最後再使用 PrintWriter 以可读性较佳的方式一一写入。PrintWriter有一个很方便的构造函数,就是将缓存及写入档案的这二个过程封装起来了,如下:
private static void saveFile(final String oldFilePath, final String newFilePath) {BufferedReader br = null;PrintWriter pw = null;try {String s = "";br = new BufferedReader(new FileReader(oldFilePath));// pw = new PrintWriter(new BufferedWriter(new// FileWriter(newFilePath)));pw = new PrintWriter(newFilePath); // 这样写也行int lineNum = 0;while ((s = br.readLine()) != null) {lineNum++;pw.println(lineNum + " " + s);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {closeClosable(br);closeClosable(pw);System.out.println("Save File Finished!");}}

以 Binary 的方式写入的话,就需要用到 “Stream” 的方式,从 FileOutputStream,BufferedOutputStream, 一直到将数据写入的 DataOutputStream。

这边需要注意的是,写入和读取的类型顺序一致很重要,如下,如果不一致的话,便会有 EOFException。

private static void saveFile2(final String newfilePath) {DataOutputStream out = null;DataInputStream in = null;try {out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(newfilePath)));out.writeUTF("===Test Content===");out.writeInt(123);out.writeFloat(1.0f);out.writeDouble(1.1232);out.close();in = new DataInputStream(new BufferedInputStream(new FileInputStream(newfilePath)));System.out.println(in.readUTF()); // 顺序一换,就会有 EOFExceptionSystem.out.println(in.readInt());System.out.println(in.readFloat());System.out.println(in.readDouble());} catch (IOException e) {e.printStackTrace();} finally {closeClosable(out);}}

System.in 和 System.out

标准输入(Standard input)即为程序(Program)所使用的数据流,所有程序的输入来自於标准输入;而所有程序的输出,可以导致标准输出(Standard output);
所有错误讯息可以导致 Standard Error。一个程序的 Standard output 可以成为另一个程序的 Standard input 这是一个很强大的工具。
比如说下面是将输入存至某路径的涵数:

public static void getInputAndSave(final String newFilePath) {BufferedReader br = null;PrintWriter pw = null;br = new BufferedReader(new InputStreamReader(System.in));String s = "";try {pw = new PrintWriter(newFilePath);while ((s = br.readLine()) != null) {pw.println(s);}} catch (IOException e) {e.printStackTrace();} finally {closeClosable(br);closeClosable(pw);}}



0 0
原创粉丝点击