Java中常用的I/O操作函数与注意事项
Java中的Input/Output(I/O)操作是Java编程的重要部分。Java I/O操作充分利用了Java的面向对象思想,提供了一组丰富的I/O类库,并提供了许多功能强大的类和接口,使得Java I/O操作变得更加高效、优雅、灵活和可扩展。
Java I/O类库中包含了许多知名的类,如File、InputStream、OutputStream、Reader、Writer等。这些类提供了读取和写入文件、读取和写入流、访问文件系统等众多功能,可以满足大多数Java程序中的输入输出需求。本篇文章介绍了Java中常用的I/O操作函数和注意事项,包括输入/输出流、文件处理、序列化等方面。
I/O输入/输出流
在Java中,输入/输出流分为字节流和字符流两种。字节流主要处理二进制数据,而字符流主要处理字符数据。
字节流包括InputStream、OutputStream、DataInputStream、DataOutputStream等。字符流包括Reader、Writer、BufferedReader、BufferedWriter等。下面分别对常用的I/O流进行介绍。
InputStream
InputStream是Java I/O库中的基类,它提供了从各种来源读取字节的接口。InputStream的常用方法有:
* int read():从输入流中读取一个字节,返回该字节的值,如果到达流的末尾,返回-1。
* int available():返回估计值,表示还有多少字节可以从输入流中读取。
* long skip(long n):跳过n个字节不读取输入流中的数据,返回实际跳过的字节数。
* void close():关闭该输入流并释放与之关联的所有系统资源。
OutputStream
OutputStream是Java I/O库中的基类,它提供了向各种目的地写入字节的接口。OutputStream的常用方法有:
* void write(int b):将一个字节写入到输出流中。
* void write(byte[] b):将字节数组中的所有字节写入到输出流中。
* void flush():刷新输出流,使缓冲区的数据立即写入到目的地。
* void close():关闭该输出流并释放与之关联的所有系统资源。
Reader
Reader是基于字符的输入流,可以一次读取一组字符。Reader的常用方法有:
* int read():从输入流中读取一个字符,返回该字符的值,如果到达流的末尾,返回-1。
* int read(char[] cbuf, int off, int len):从输入流中读取len个字符,并写入到字符数组cbuf中,从数组的第off个位置开始写入,返回实际读取的字符数。
* void close():关闭该输入流并释放与之关联的所有系统资源。
Writer
Writer是基于字符的输出流,可以一次写入一组字符。Writer的常用方法有:
* void write(char[] cbuf, int off, int len):将字符数组cbuf中从off位置开始的len个字符写入到输出流中。
* void flush():刷新输出流,使缓冲区的数据立即写入到目的地。
* void close():关闭该输出流并释放与之关联的所有系统资源。
文件处理
在Java中,可以使用File类来处理文件和文件夹。File类可以创建文件或文件夹、重命名文件或文件夹、删除文件或文件夹,还可以获取文件的信息,如名字、大小、修改时间等。下面介绍一下File类中常用的方法。
File(File parent, String child)
创建一个新的File实例,表示由指定父路径和子路径组成的文件。
File(String pathname)
创建一个新的File实例,表示从指定路径名字符串转换得到的文件。
boolean createNewFile()
创建一个表示文件的新文件,并返回该文件的路径名。
boolean delete()
删除这个文件或目录,并返回true如果这个删除操作成功。
boolean exists()
测试这个文件或目录是否存在,并返回true如果这个文件存在。
String[] list()
返回一个字符串数组,这些字符串指定该目录中的文件和目录。
long length()
返回此文件的长度和字节数。
boolean renameTo(File dest)
将此文件重命名为指定的文件名,如果重命名成功,则返回true,否则返回false。
序列化
序列化是Java中一种将对象转换为永久存储和网络传输的机制。 序列化可以将任何支持序列化接口的对象转换为字节数组,而反序列化就是将字节数组重新转换为对象。
Java中提供了ObjectInput/OutputStream类来实现对象的序列化和反序列化。要使类可序列化,需要在类定义中增加一个serialVersionUID字段。使用序列化时还需要注意以下几点:
* 序列化和反序列化的对象必须是同一个类的实例。
* 序列化期间,对象可以被写入/读取流。如果写入的对象是可变的,则需要记录对象的状态,以便在反序列化期间重建它。
* 在序列化期间,对象引用和静态字段不会被保存,只有对象状态才会被保存。
以下是Java中使用ObjectInput/OutputStream类进行序列化和反序列化的示例代码:
public class SerializeExample implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
SerializeExample obj = new SerializeExample();
obj.setId(1);
obj.setName("test");
// serialize
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("test.dat"));
os.writeObject(obj);
os.close();
// deserialize
ObjectInputStream is = new ObjectInputStream(new FileInputStream("test.dat"));
SerializeExample obj2 = (SerializeExample) is.readObject();
is.close();
System.out.println(obj2.getId());
System.out.println(obj2.getName());
}
}
注意事项
Java I/O操作过程中需要注意以下几点:
* 在使用I/O操作前应确保输入/输出流是可用的,否则会抛出异常。
* I/O操作通常是阻塞的,程序会在读取或写入数据时被阻塞,直到完成操作或取消操作。因此,应在新的线程中执行I/O操作,以避免阻塞主线程,影响程序的响应性能。
* 当使用内存缓冲区进行I/O操作时,应合理地设置缓冲区大小,以避免出现内存溢出或读取/写入速度缓慢的情况。
