Java IO
Java中的输入是指从数据源等读到Java程序中,这里的数据源可以是文件,内存或网络连接,输出则是指从Java程序中写到目的地。
输入输出流可以分为以下几种类型(暂时不考虑File类)
类名 | 中文名 |
---|---|
InputStream |
字节输入流 |
OutputStream |
字节输出流 |
Reader |
字符输入流 |
Writer |
字符输出流 |
Java IO共涉及40多个类,下图是字节流各个类之间的关系
abstract int read()
abstract int write()
read方法和Write方法在执行时都将阻塞
InputStream
InputStream、OutputStream、Reader、Writer都实现了Closeable接口,该接口拥有close()
OutputStream、Writer还实现了Flushable接口,该接口有flush()
InputStream
InputStream的子类及其说明有如下所示
名称 | 说明 |
---|---|
BufferedInputStream |
为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。 |
ByteArrayInputStream |
包含一个内部缓冲区,该缓冲区包含从流中读取的字节。 |
DataInputStream |
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。 |
FileInputStream |
从文件系统中的某个文件中获得输入字节。 |
FilterInputStream |
包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。 |
ObjectInputStream |
对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。 |
PipedInputStream |
管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。 |
PushbackInputStream |
为另一个输入流添加性能,即“推回 (push back)”或“取消读取 (unread)”一个字节的能力。 |
SequenceInputStream |
表示其他输入流的逻辑串联。 |
组合流过滤器
FileInputStream
FileOutputStream
提供一个磁盘文件的输入输出流,只支持字节级别的读写
FileInputStream fin = new FileInputStream("test.txt");
byte by =(byte) fin.read();
蕴含着装饰着模式的设计思想
嵌套过滤器来实现多重功能
文本输入输出
PrintWriter以文本格式打印字符串和数字,
PrintWriter out = new PrintWriter("test.txt");
out.print("hello ");
out.println(123);
将hello 123写入文本文件test.txt
OutputStream
OutputStream的子类及其说明有如下所示
名称 | 说明 |
---|---|
BufferedOutputStream |
该类实现缓冲的输出流。 |
ByteArrayOutputStream |
此类实现了一个输出流,其中的数据被写入一个 byte 数组。 |
DataOutputStream |
数据输出流允许应用程序以与机器无关方式将基本 Java 数据类型写入输出流中。 |
FileOutputStream |
文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。 |
FilterOutputStream |
此类是过滤输出流的所有类的超类。 |
ObjectOutputStream |
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。 |
PipedOutputStream |
可以将管道输出流连接到管道输入流来创建通信管道。 |
PrintStream |
为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。 |
对于类中方法的熟悉不详述了,可以参照JDK文档,或者可以试着在IDE中,实例化上面的类,使用此类对象时,按下.之后,会出现提示框,再一个一个熟悉就好了。
简单示例
下面以文件数据的输入输出说明以上类的使用。
1.在java程序中生成1~20的平方数,并输出到文件中。
package com.songpu;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
public class MyFileOutputStream {
public static void main (String[] args) throws IOException{
try{
FileOutputStream fos = new FileOutputStream("F:\test1.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos,1024);
PrintStream ps = new PrintStream(bos,false);
System.setOut(ps);
for(int i= 0;i<20;i++){
System.out.println(i*i);
}
ps.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
2.将刚才生成的文件中的数据输入到程序,并将其打印到屏幕
package com.songpu;
import java.io.*;
public class MyFlieInputStream {
public static void main(String[] args) throws IOException {
File file = new File("F:\test1.txt");
FileInputStream in = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(in);
byte[] bytes = new byte[(int) file.length()];
do {
bis.read(bytes);
System.out.println(new String(bytes));
}while (bis.read() != -1);
bis.close();
in.close();
}
}
再以序列化与反序列化的例子说明ObjectInputStream和ObjectOutputStream的使用
Java序列化是将对象变成二进制形式的一连串字符描述的过程,反序列化就是序列化的相反过程,把这些字符重建为对象。
序列化和反序列化的作用,是保存对象到文件或数据库中,使对象能够传输,序列化的要求是实现Serializable接口,代码如下所示
package com.songpu.serial;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
/*
* 待序列化的类,实现序列化接口
*/
class Person implements Serializable{
public String name;
public int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/*
* 测试类
*/
public class SerialTest{
public static void main(String[] args) throws IOException, ClassNotFoundException{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\test.txt"));
Person p0 = new Person("tangsong",21);
oos.writeObject(p0);
oos.flush();
oos.close();
deserial();
}
public static void deserial() throws ClassNotFoundException, IOException{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\test.txt"));
Person p1 = (Person)ois.readObject();
ois.close();
System.out.println("Name="+p1.getName()+";Age="+p1.getAge());
}
}
前面的博文介绍了字节流,那字符流又是什么流?从字面意思上看,字节流是面向字节的流,字符流是针对unicode编码的字符流,字符的单位一般比字节大,字节可以处理任何数据类型,通常在处理文本文件内容时,字符流可以一个一个字符的读取,也可以一行一行字符的读取。
字符流类型包括Writer和Reader及其子类如图所示
Writer的子类
名称 | 说明 |
---|---|
BufferedWriter |
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 |
CharArrayWriter |
此类实现一个可用作 Writer 的字符缓冲区。 |
FileWriter |
用来写入字符文件的便捷类。 |
FilterWriter |
用于写入已过滤的字符流的抽象类。 |
OutputStreamWriter |
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。 |
PipedWriter |
传送的字符输出流。 |
PrintWriter |
向文本输出流打印对象的格式化表示形式。 |
StringWriter |
一个字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。 |
Reader的子类
名称 | 说明
--------------|---------
BufferedReader
| 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
CharArrayReader
| 此类实现一个可用作字符输入流的字符缓冲区。
FileReader
|用来读取字符文件的便捷类。
FilterReader
|用于读取已过滤的字符流的抽象类。
InputStreamReader
| InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
LineNumberReader
|跟踪行号的缓冲字符输入流。
PipedReader
| 传送的字符输入流。
PushbackReader
|允许将字符推回到流的字符流 reader。
StringReader
| 其源为一个字符串的字符流。
下面的例子是FileWriter将字符输出到流中,再冲刷到文件中,文件中的字符通过FileReader读入到Java程序,然后显示在屏幕。
package com.songpu.io;
import java.io.*;
public class MyWriter {
/*
* 将字符输出到文本文件中
* 并将文本文件中的字符输入到屏幕
*
*/
public static void main(String[] args) throws IOException{
File f = new File("F:\test3.txt");
FileWriter fw =new FileWriter(f);
fw.write("hahahahahahahaha
");
fw.write("xixixixixixixi
");
//将流中的信息冲刷到文件中
fw.flush();
fw.close();
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
String s =null;
while((s = br.readLine()) != null){
System.out.println(s);
}
fr.close();
br.close();
}
}
字节流和字符流的连接
InputStreamReader、OutputStreamWriter是连接字节流和字符流的桥梁以一个简单的例子来说明InputStreamReader的用法。
package com.songpu.io;
import java.io.*;
public class ByteToChar {
public static void main(String[] args) throws IOException{
File f = new File("H:\Programming\Java\JavaTest\src\com\songpu\io\ByteToChar.java");
FileInputStream fis = new FileInputStream(f);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String s = null;
while((s = br.readLine()) != null){
System.out.println(s);
}
br.close();
isr.close();
fis.close();
}
}
File类
File类直接继承至Object类,并且实现了Serializable和Comparable接口。对于File类只需知道它的方法,熟悉这些方法,可以参照我们平时操作文件或目录时候
做法
- 包含的方法
- 创建方法
- 删除方法
- 判断方法
- 获取方法
- 设置方法
- 文件过滤
创建方法
方法 | 说明 |
---|---|
boolean createNewFile() |
当且仅当不存在具有此抽象路径名指定名称的文件时,创建一个新的空文件 |
boolean mkdir() |
创建此抽象路径名指定的目录 |
boolean mkdirs() |
创建此抽象路径名指定的目录,包括所有必需的父目录(不存在) |
static File createTempFile(String prefix, String suffix) |
在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。 |
static File createTempFile(String prefix, String suffix, File directory) |
在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称 |
boolean renameTo(File dest) |
重新命名此抽象路径名表示的文件 |
删除方法
方法 | 说明 |
---|---|
boolean delete() |
删除此抽象路径名表示的文件或目录 |
void deleteOnExit() |
在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。 |
判断方法
方法 | 说明 |
---|---|
boolean canExecute() |
判断应用程序是否可以执行此抽象路径名表示的文件。 |
boolean canRead() |
判断 应用程序是否可以读取此抽象路径名表示的文件。 |
boolean canWrite() |
判断应用程序是否可以修改此抽象路径名表示的文件。 |
boolean exists() |
判断此抽象路径名表示的文件或目录是否存在。 |
boolean isAbsolute() |
判断此抽象路径名是否为绝对路径名。 |
boolean isDirectory() |
判断此抽象路径名表示的文件是否是一个目录。 |
boolean isFile() |
判断此抽象路径名表示的文件是否是一个标准文件。 |
boolean isHidden() |
判断此抽象路径名指定的文件是否是一个隐藏文件。 |
获取方法
方法 | 说明 |
---|---|
String getAbsolutePath() |
返回此抽象路径名的绝对路径名字符串。 |
File getCanonicalFile() |
返回此抽象路径名的规范形式。 |
String getCanonicalPath() |
返回此抽象路径名的规范路径名字符串。 |
long getFreeSpace() |
返回此抽象路径名指定的分区中未分配的字节数。 |
String getName() |
返回由此抽象路径名表示的文件或目录的名称。 |
String getParent() |
返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。 |
File getParentFile() |
返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null |
String getPath() |
将此抽象路径名转换为一个路径名字符串。 |
long getTotalSpace() |
返回此抽象路径名指定的分区大小。 |
long getUsableSpace() |
返回此抽象路径名指定的分区上可用于此虚拟机的字节数。 |
File getAbsoluteFile() |
返回此抽象路径名的绝对路径名形式。 |
long lastModified() |
返回此抽象路径名表示的文件最后一次被修改的时间。 |
long length() |
返回由此抽象路径名表示的文件的长度。 |
String[] list() |
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。 |
String[] list(FilenameFilter filter) |
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。 |
设置方法
方法 | 说明 |
---|---|
boolean setExecutable(boolean executable) |
设置此抽象路径名所有者执行权限的一个便捷方法。 |
boolean setExecutable(boolean executable, boolean ownerOnly) |
设置此抽象路径名的所有者或所有用户的执行权限。 |
boolean setLastModified(long time) |
设置此抽象路径名指定的文件或目录的最后一次修改时间。 |
boolean setReadable(boolean readable) |
设置此抽象路径名所有者读权限的一个便捷方法。 |
boolean setReadable(boolean readable, boolean ownerOnly) |
设置此抽象路径名的所有者或所有用户的读权限。 |
boolean setReadOnly() |
标记此抽象路径名指定的文件或目录,从而只能对其进行读操作。 |
boolean setWritable(boolean writable) |
设置此抽象路径名所有者写权限的一个便捷方法。 |
boolean setWritable(boolean writable, boolean ownerOnly) |
设置此抽象路径名的所有者或所有用户的写权限。 |
String toString() |
返回此抽象路径名的路径名字符串。 |
文件过滤
方法 | 说明 |
---|---|
File[] listFiles() |
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。 |
File[] listFiles(FileFilter filter) |
返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。 |
File[] listFiles(FilenameFilter filter) |
返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。 |
static File[] listRoots() |
列出可用的文件系统根。 |
随机访问文件
RandomAccessFIle类
可以在文件中的任何位置查找或写入数据