输入/输出流的分类:
java.io包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同的角度对其进行分类:
- 按数据流的方向不同可以分为输入流和输出流
- 按处理数据单位不同可以分为字节流和字符流
- 按功能不同分为节点流和处理流
输入和输出都是站在程序的角度上来说的。
J2SDK所提供的所有流类型位于包java.io内都继承自一下四种抽象类型:
字节流 | 字符流 | |
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
//读取一个字节并以正数的形式返回(0-255),如果返回-1,表示已经到输入流的末尾
int read() throws IOException
//读取一系列字节并存储到一个数组buffer,返回实际读取的字节数,如果读取前已到输入流的末尾返回-1
int read(byte[] buffer) throws IOException
//读取length个字节,并存储到一个字节数组buffer,从length位置开始,返回实际读取的字节数,
//如果读取前已到输入流的末尾,返回-1
int read(byte[] buffer, int offset, int length) throws IOException
//关闭流释放内存资源
void close() throws IOException
//跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException
OutputStream的基本方法:
//向输出流写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException
//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
//将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void write(byte[] b, int off, int len) throws IOException
//关闭流释放内存资源
void close() throws IOException
//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
Reader的基本方法:
//读取一个字符以整数的形式返回(0-255),如果返回-1表示已经到输入流的末尾
int read() throws IOException
//读取一系列字符并存储到一个数组buffer,返回实际读取的字符数,如果读取前已经到输入流的末尾返回-1
int read(char[] cbuf) throws IOException
//读取length个字符,并存储到一个数组buffer,从length位置开始,返回实际读取的字符数,如果读取前已经到输入流的末尾,返回-1
int read(char[] cbuf, int offset, int length) throws IOException
//关闭流释放内存资源
void close() throws IOException
//跳过n个字符不读,返回实际跳过的字节数
long skip(long n) throws IOException
Writer的基本方法:
<pre name="code" class="java">//向输出流写入一个字符数据,该字节数据为参数b的低16位
void write(int c) throws IOException
//将一个字符类型的数组中的数据写入输出流
void write(byte[] cbuf) throws IOException
//将一个字符类型的数组中的从指定位置(offset)开始的length个字节写入到输出流
void write(byte[] cbuf, int offset, int length) throws IOException
//将一个字符串中的字符写入到输出流
void write(String string) throws IOException
//将一个字符串从offset开始的length个字符写入到输出流
void write(String string, int offset, int length) throws IOException
//关闭流释放内存资源
void close() throws IOException
//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
例子:
import java.io.*;
public class TestFileOutputStream {
public static void main(String args[]){
int b = 0;
FileInputStream fis =null;
FileOutputStream fos = null;
try{
fis = new FileInputStream("I:/pinglun.txt");
fos = new FileOutputStream("I:/pinglunCopy.txt");
while((b = fis.read()) != -1){
fos.write(b);
}
fis.close();
fos.close();
}catch(FileNotFoundException e1){
System.out.println("找不到指定文件");
System.exit(-1);
}catch(IOException e2){
System.out.println("文件复制错误!");
System.exit(-1);
}
System.out.println("文件已复制!");
}
}
缓冲流:
- 缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些些的方法。
J2SD提供了四种缓存流,其常用的构造方法为:
BufferedReader(Reader in);
BufferedReader(Reader in,int sz); //sz为自定义缓存区的大小
BufferedWriter(Writer out);
BufferedWriter(Writer out,int sz);
BufferedIntegerStream(InputStream in);
BufferedInputStream(InputStream in);
BufferedOutputStream(InputStream in,int size);
BufferedOutputStream(OutputStream out);
BufferedOutputStream(OutputStream out,int size);
缓冲输入流支持其父类的mark和reset方法。
BufferedReader提供了readLine方法用语读取一行字符串(以\r或\n分隔)。
BufferedWriter提供了newLine用于写入一个行分隔符。
对于输入的缓冲流,写出的数据会先在内存中缓存,使用flush方法将会使内存中的数据立刻写出。
转换流:
- InputStreamReader和OutputStreamWriter用于字节数据到字符数据之间的转换。
- InputStreamReader需要和InputStream“套接”
- OutputStreamWriter需要和OutputStream“套接”
转换流在构造时可以指定其编码集合,例如:
InputStream isr = new InputStreamReader(System.in,"ISO8859_1");
转换流例子:
import java.io.*;
public class TestTransForm {
public static void main(String[] args) {
try{
FileInputStream fis = new FileInputStream("I:/pinglun.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String s = null;
s = br.readLine();
while(s != null){
if(s.equalsIgnoreCase("exit")){
System.exit(-1);
}
System.out.println(s);
s = br.readLine();
}
}catch(FileNotFoundException ef){
System.out.println("文件没有找到!");
System.exit(-1);
}catch(IOException e){
e.printStackTrace();
}
}
}
数据流:
- DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,它属于处理流,需要分别“套接”在InputStream和OutputStream类型的节点流上。
- DataInputStream和DataOutputStream提供了可以存取与机器无关的java原始类型数据(如int,double等)的方法。
DataInputStream和DataOutputStream的构造方法为:
DataInputStream(InputStream in);
DataOutputStream(OutputStream out);
数据流例子:
其中ByteArrayInputStream/ByteArrayOutputStream是对内存进行读写
import java.io.*;
public class TestDataStream {
public static void main(String args[]){
ByteArrayOutputStream baos = new ByteArrayOutputStream(); //在内存中创建一个ByteArray,相当于是从程序中输出到内存中
DataOutputStream dos = new DataOutputStream(baos);
try{
dos.writeDouble(Math.random());
dos.writeInt(1);
dos.writeBoolean(true);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); //从内存中输入到程序中
System.out.println(bais.available()); //计算总字节数
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readDouble());
System.out.println(dis.readInt());
System.out.println(dis.readBoolean());
dos.close();
dis.close();
}catch(IOException e){
System.out.println(e.getStackTrace());
}
}
}
Print流:
- PrintWriter和PrintStream都属于输出流,分别针对于字符和字节。
- PrintWriter和PrintStream提供了重载的print
- Println方法用于多种数据类型的输出
- PrintWriter和PrinterStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息。
- PrintWriter和PrinterSteam有自动flush功能。
其常用的构造方法为:
PrintWriter(Writer out);
PrintWriter(Writer out,boolean autoFlush);
PrintWriter(OutputStream out);
PrintWriter(OutputStream out,boolean autoFlush);
PrintStream(OutputStream out);
PrintStream(OutputStream out,booleanautoFlush);
例子1:
import java.io.*;
public class TestPrintStream {
public static void main(String[] args) {
PrintStream ps = null;
try{
FileOutputStream fos = new FileOutputStream("I:/log.dat");
ps = new PrintStream(fos);
}catch(IOException e){
e.printStackTrace();
}
if(ps != null){
System.out.println("a");
System.setOut(ps); //重定向屏幕输出到ps对象中
}
int In = 0;
for(char c = 0;c<=60000;c++){
System.out.print(c+" ");
if(In++> 100){System.out.println();} In = 0;
}
}
}
例子2:
import java.io.*;
public class TestPrintStream2 {
public static void main(String[] args) {
String filename = args[0]; //输入的为读取文件的路径
if(filename != null){
list(filename,System.out);
}
}
public static void list(String f,PrintStream fs){
try{
BufferedReader br = new BufferedReader(new FileReader(f));
String s = null;
while((s = br.readLine()) != null){
fs.println(s);
}
br.close();
}catch(IOException e){
fs.print("无法读取文件!");
}
}
}
例子3(写日志):
import java.io.*;
import java.util.Date;
public class TestPrintStream3 {
public static void main(String[] args) {
String s = null;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
try{
FileWriter fw = new FileWriter("I:/logfile.log",true);
PrintWriter log = new PrintWriter(fw);
while((s = br.readLine()) != null){
if(s.equalsIgnoreCase("exit")) break;
System.out.println(s.toUpperCase());
log.println("------");
log.println(s.toUpperCase());
log.flush();
}
log.println("===" + new Date() + "===");
log.flush();
log.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
Object流:
直接将Object写入或读出:
- translent关键字
- serializable接口
- externalizable接口
import java.io.*;
public class TestObjectIO {
public static void main(String[] args) throws Exception{
T t = new T();
t.k = 8;
FileOutputStream fos = new FileOutputStream("I:/ObjectStreamIO.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(t);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("I:/ObjectStreamIO.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
T tReaded = (T)ois.readObject();
System.out.println(tReaded.i +" " + tReaded.j + " " + tReaded.d + " " + tReaded.k);
}
}
class T implements Serializable{
int i = 10;
int j = 9;
double d = 2.3;
transient int k = 14; //修饰的成员变量在序列化的时候不予考虑,读取的时候默认是0
}