1. 文件读写的工具
一一个很常见的程序化的任务就是读取文件到内存,修改,然后再写出。java I/O类库的问题之一就是:它需要编写相当多的代码去执行这些常用的工作–没有任何基本的帮助功能可以为我们做这一切。下面的例子是被用来简化对文件的读写操作。它包含的static方法可以向简单字符串那样写文本文件,并且可以创建一个TextFile对象,它用一个ArrayList来保存文件的若干行。
public class TextFile extends ArrayList<String> {
public static String read(String fileName) {
StringBuilder sb = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new FileReader(new File(
fileName).getAbsoluteFile()));
try {
String s;
while ((s = in.readLine()) != null) {
sb.append(s);
sb.append("n");
}
} finally {
in.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return sb.toString();
}
public static void write(String fileName, String text) {
try {
PrintWriter out = new PrintWriter(
new File(fileName).getAbsoluteFile());
try {
out.print(text);
} finally {
out.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public TextFile(String fileName, String splitter) {
super(Arrays.asList(read(fileName).split(splitter)));
if (get(0).equals(""))
remove(0);
}
public TextFile(String fileName) {
this(fileName, "n");
}
public void write(String fileName) {
try {
PrintWriter out = new PrintWriter(
new File(fileName).getAbsoluteFile());
try {
for (String item : this)
out.println(item);
} finally {
out.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
String file = read("文件路径");
write("test.txt", file);
TextFile text = new TextFile("test.txt");
text.write("test2.txt");
TreeSet<String> words = new TreeSet<String>(new TextFile("文件路径", "\\W+"));
System.out.println(words.headSet("a"));
}
read()将每行添加到StringBuffer,并且为每行加上换行符,因为在读的过程中换行符会被取出掉。接着返回一个包含整个文件的字符串。write()打开文本并将其写入文件。在这两个方法中,都要注意close()关闭文件。注意,在任何打开文件的代码在finally子句中,都需要添加close()方法,以保证文件都会被正确关闭。
1.1读取二进制文件
下面的的工具类与TextFile类似,因为它简化了读取二进制文件的过程:
public class BinaryFile {
public static byte[] read(File bFile) throws IOException{
BufferedInputStream bf = new BufferedInputStream(new FileInputStream(bFile));
try {
byte[] data = new byte[bf.available()];
bf.read(data);
read(bFile);
return data;
} finally{
bf.close();
}
}
public static byte[] read(String bFile) throws IOException{
return read(new File(bFile).getAbsoluteFile());
}
}
其中一个重载方法接受File参数,第二个重载方法接受表示文件名的String参数。这两个方法都返回产生的byte数组。available()方法被用来产生恰当的数组尺寸,并且reade()方法的特定的重载版本填充了这个数字。
2. 标准I/O类库
程序的所有输入都可以来自于标准输入,它的所有输出都可以发送到标准输出,以及所有的错误信息都可以发送到标准准成。标准I/O的一样在于:我们可以很容易地把程序串联起来,一个程序的标准输出可以称为另一程序的标准输入。
2.1从标准输入中读取
System.out已经事先被包装成了PrintStream对象。System.err同样也是PrintStream,但System.in却是一个没有被包装过的未经加工的InputStream。这意味着尽管我们可以立即使用System.out和System.err,但是在读取System.in之前必须对其进行包装。例如:
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
stdin.readLine();
System.in和大多数流一样,通常应该对它进行缓冲。
2.2将System.out转换成PrintWriter
PrintWriter有一个可以接受OutputStream作为参数的构造器。因此只要需要,就可以使用那个构造器把System.out转换成PrintWriter;示例:PrintWriter out = new PrintWriter(System.out, true)
;注意:第二个参数设为true,表示开启自动清空功能。
2.3 标准的I/O重定向
Java的System类允许我们对标准输入、输出和错误I/O流进行重定向
setIn(InputStream)
setOut(PrintStream)
setErr(PrintStream)
注意:I/O重定向操作的是字节流,而不是字符流,因为我们使用的是InputStream和OutputStream,而不是Reader和Writer。
3. 进程控制
你经常会需要在java内部执行其他操作系统的程序,并且要控制这些程序的输入和输出。java类库提供了执行这些操作的类。
public class OSExecute {
public static void command(String command) {
boolean err = false;
try {
Process process = new ProcessBuilder(command.split("")).start();
BufferedReader results = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String s;
while ((s = results.readLine()) != null)
System.out.println(s);
BufferedReader errors = new BufferedReader(new InputStreamReader(
process.getErrorStream()));
while ((s = errors.readLine()) != null) {
System.err.println(s);
err = true;
}
} catch (Exception e) {
if (!command.startsWith("CMD /C")) {
command("CMD /C" + command);
} else {
throw new RuntimeException(e);
}
}
if (err)
throw new OSExecuteException("Errors executing" + command);
}
public static void main(String[] args) {
OSExecute.command("文件路径");
}
}
要运行一个程序,你需要向OSExecute.command()传递一个command字符串,它与你在控制台上运行该程序所键入的命令相同。这个命令被传递给java.lang.ProcessBuidler构造器,然后所产生的ProcessBuidler对象被启动。为了捕获执行时产生的标准输出流,你需要调用getInputStream(),这是因为InputStream是我们可以从中读取信息的流。从程序中产生的结果每次输出一行,因此要使用readLine()来读取。