您的位置:首页 > 编程语言 > Java开发

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

2015-11-11 23:07 387 查看
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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: