要执行这些 Java 程序,你需要遵循以下步骤。这些程序涵盖了 Java I/O 操作的核心类,包括 File、字节流、字符流、缓冲流、序列化等。
1. 环境准备与编译
首先,确保你已安装 Java 开发工具包 (JDK)。然后,为每个程序创建独立的 .java 文件并编译。
1.1 创建与编译文件
将每个 listing 的代码分别保存为对应的 .java 文件。例如:
bash
# 创建并编译 FileDemo.java
cat > FileDemo.java << 'EOF'
// Demonstrate File.
import java.io.File;
class FileDemo {
static void p(String s) {
System.out.println(s);
}
public static void main(String args[]) {
File f1 = new File("/java/COPYRIGHT");
p("File Name: " + f1.getName());
p("Path: " + f1.getPath());
p("Abs Path: " + f1.getAbsolutePath());
p("Parent: " + f1.getParent());
p(f1.exists() ? "exists" : "does not exist");
p(f1.canWrite() ? "is writeable" : "is not writeable");
p(f1.canRead() ? "is readable" : "is not readable");
p("is " + (f1.isDirectory() ? "" : "not" + " a directory"));
p(f1.isFile() ? "is normal file" : "might be a named pipe");
p(f1.isAbsolute() ? "is absolute" : "is not absolute");
p("File last modified: " + f1.lastModified());
p("File size: " + f1.length() + " Bytes");
}
}
EOF
javac FileDemo.java
注意 :listing 3 (OnlyExt.java) 是一个过滤器类,需要先编译,因为它被 listing 4 (DirListOnly.java) 依赖。
bash
# 编译过滤器类
cat > OnlyExt.java << 'EOF'
import java.io.*;
public class OnlyExt implements FilenameFilter {
String ext;
public OnlyExt(String ext) {
this.ext = "." + ext;
}
public boolean accept(File dir, String name) {
return name.endsWith(ext);
}
}
EOF
javac OnlyExt.java
1.2 依赖关系与编译顺序
部分程序之间存在依赖关系,编译顺序如下:
| 程序文件 | 依赖项 | 编译顺序 |
|---|---|---|
OnlyExt.java (Listing 3) |
无 | 1 |
DirListOnly.java (Listing 4) |
OnlyExt.class |
2 |
SerializationDemo.java (Listing 23) |
MyClass (内部类) |
独立编译 |
| 其他程序 | 无 | 任意 |
2. 程序执行与结果分析
执行程序前,请根据代码中的文件路径(如 /java/COPYRIGHT)确保相应文件或目录存在,或修改路径为本地有效路径。
2.1 文件与目录操作 (Listing 1, 2, 4)
FileDemo(Listing 1) :输出指定文件(如/java/COPYRIGHT)的属性信息。如果文件不存在,exists()将返回false,length()等方法可能返回0或默认值。DirList(Listing 2) :列出指定目录(如/java)下的所有文件和子目录,并区分类型。DirListOnly(Listing 4) :依赖OnlyExt过滤器,仅列出指定目录中扩展名为.html的文件。
2.2 字节流操作 (Listing 5-13)
FileInputStreamDemo(Listing 5) :读取自身源文件,演示available()、read()、skip()等方法。FileOutputStreamDemo(Listing 6 & 7) :将字符串写入三个文件。Listing 6 使用传统try-catch-finally关闭资源,Listing 7 使用 try-with-resources 语法(Java 7+),这是更推荐的自动资源管理方式 。ByteArrayInputStreamDemo(Listing 8) 与ByteArrayInputStreamReset(Listing 9) :演示从字节数组读取数据,以及reset()方法重置流。ByteArrayOutputStreamDemo(Listing 10):演示将数据写入内部字节数组,并可转换为字符串或写入其他输出流。BufferedInputStreamDemo(Listing 11) 与PushbackInputStreamDemo(Listing 12):演示缓冲流和回退流,用于标记读取和回退操作。SequenceInputStreamDemo(Listing 13):将多个输入流串联成一个流顺序读取。
2.3 字符流与高级 I/O (Listing 14-22)
PrintfDemo(Listing 14) :演示System.out.printf()的格式化输出功能。DataIODemo(Listing 15) :使用DataOutputStream和DataInputStream读写基本数据类型。FileReaderDemo(Listing 16) 与FileWriterDemo(Listing 17):字符流方式读写文件。CharArrayReaderDemo(Listing 18) 与CharArrayWriterDemo(Listing 19):字符数组的读写操作。BufferedReaderDemo(Listing 20) 与PushbackReaderDemo(Listing 21):字符缓冲流和回退流。ConsoleDemo(Listing 22) :从控制台读取输入(注意:在某些 IDE 中System.console()可能返回null)。
2.4 对象序列化 (Listing 23)
SerializationDemo(Listing 23) :演示对象的序列化(写入serial文件)与反序列化(从serial文件读取)。MyClass必须实现Serializable接口。
3. 关键注意事项与最佳实践
- 路径问题 :将代码中的绝对路径(如
/java)替换为你本地存在的目录路径,或使用相对路径(如./test.txt)。 - 资源管理 :对于所有
InputStream、OutputStream、Reader、Writer等资源,务必确保关闭 。优先使用 try-with-resources 语法(如 Listing 7, 15, 16 所示),它可以自动关闭资源,避免内存泄漏 。 - 异常处理 :I/O 操作必须处理
IOException。示例中使用了try-catch,生产代码可能需要更精细的处理。 - 缓冲区使用 :大量 I/O 操作时,务必使用缓冲流(如
BufferedInputStream、BufferedReader)包装底层流,可显著提升性能 。 - 序列化版本 :
SerializationDemo中,若修改了MyClass的字段,反序列化可能因serialVersionUID不匹配而失败。可显式定义private static final long serialVersionUID来保持版本兼容。
4. 快速执行脚本示例
你可以创建一个 Shell 脚本(如 run_all.sh)来批量编译和运行。以下是一个简化示例:
bash
#!/bin/bash
# 编译所有Java文件
javac *.java 2>/dev/null
# 运行FileDemo (修改路径为你本地存在的文件)
echo "=== Running FileDemo ==="
java FileDemo 2>&1 | head -5
# 运行DirList (修改路径为你本地存在的目录)
echo -e "
=== Running DirList ==="
java DirList 2>&1# 运行DataIODemo
echo -e "
=== Running DataIODemo ==="
java DataIODemo
#清理class文件
# rm *.class
注意:由于部分程序依赖特定文件或路径,直接全部运行可能报错。建议根据你的环境单独编译和运行感兴趣的示例。