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

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 block
			e.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()); // 顺序一换,就会有 EOFException
			System.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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值