Ø Java.io包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同
的角度对其进行分类:
l 按数据流的方向不同可以分为输入流和输出流(站在程序角度而言);
l 按处理数据单位不同可以分为字节流和字符流;
l 按功能不同可以分为节点流和处理流。
Ø J2SDK 所提供的所有流类型位于java.io内部都分别继承自以下四种抽象流类
型。
| 字节流 | 字符流 |
输入流 | InputStream(字节8bit) | Reader(字符,2个字节) |
输出流 | OutputStream | Writer |
说明:节点流为可以从一个特定的数据源(节点)读写数据; 处理流是”连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
Ø 继承自InputStream的流都是用于向程序中输入数据,数据单位为字节(8bit)
InputStream基本方法:
Ø 继承自OutputStream的流都是用于向程序中输出数据,数据单位为字节(8bit)
OutputStream的基本方法:
说明:良好的编程习惯是在close数据流之前先调用flush()方法将缓冲区的数据全部先写到目的地。
Ø 继承自Reader的流都是用于向程序中输入数据,数据单位为字符(16bit)
Reader的基本方法:
Ø 继承自Writer的流都是用于向程序中输出数据,数据单位为字符(16bit)
Writer的基本方法:
Ø 节点流类型
Ø 测试FileInputStream
public class TestFileInput {
public static void main(String[] args) {
int b;
long num = 0;
try {
FileInputStream fis = new FileInputStream
("D://java+必备软件//java//01//ToString.java");
while((b=fis.read()) != -1) {//读完后会自动指向下一个字节数据
System.out.print((char)b);
//得到的b的值为字符对应的ASCII码,现在将b强制转换成字符类型
num ++;
}
fis.close();
System.out.println();
System.out.println("共读取了" + num + "个字节");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
说明:Window下的文件分隔符除了使用上述的”//”外,还可以使用”/”
Ø 测试FileOutputStream
public class TestFileOutput {
public static void main(String[] args) {
int b;
long num = 0;
try {
FileInputStream fis = new FileInputStream
("D://java+必备软件//java//01//Cat.java");
//输出流在文件不存在的情况下会自动创建,但不会自动创建文件夹。
FileOutputStream fos = new FileOutputStream
("D://java+必备软件//java//01//Cat11.java");
while((b=fis.read())!=-1) {//-1为读到文件结尾
fos.write(b);
num ++;
}
fis.close();
fos.close();
System.out.println();
System.out.println("共读取了" + num + "个字节");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
说明:上述的Stream不会得到中文,因为他们是按照字节单位读取的,要想打印出中文,必须使用Writer、Reader
Ø 测试FileReader(可以读取到中文)
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class TestFileReader {
public static void main(String[] args) {
int b;
try {
FileReader fr = new FileReader
("D://java+必备软件//java//16//ExTest.java");
while((b=fr.read()) != -1) {
System.out.print((char)b);
}
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
Ø 测试FileWriter(可以写入中文)
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class TestFielWriter {
public static void main(String[] args) {
int b;
try {
FileReader fr = new FileReader
("D://java+必备软件//java//16//ExTest.java");
FileWriter fw = new FileWriter
("D://java+必备软件//java//16//ExTest1.java");
while((b=fr.read()) != -1) {
fw.write(b);
}
fr.close();
fw.close();
System.out.println("文件复制完毕!");
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("找不到指定文件!");
} catch(IOException e) {
e.printStackTrace();
System.out.println("输入输出错误!");
}
}
}
Ø 处理流类型
Ø 缓冲流
Ø 测试BufferedInputStream
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class TestBufferStream {
public static void main(String[] args) {
int b;
try {
FileInputStream fis = new FileInputStream
("D://java+必备软件//java//16//ExTest.java");
BufferedInputStream bis = new BufferedInputStream(fis);
System.out.println(bis.markSupported());
//并不是所有的stream都支持mark()方法,该语句可以进行查看是否支持。
bis.mark(20);
//在当前位置做标志,参数20为在标志位置失效前可以读取字节的最大限制
//不要理解成在第20个字符位置做标志
bis.skip(20);//跳过20个字符,即在第21个字符位置开始读取
System.out.println("NO.1-----------------");
for(int i=0; i<20 && (b=bis.read())!=-1; i++) {
System.out.print((char)b);
}
bis.reset();//回到前面标志mark的位置
System.out.println();
System.out.println("NO.2-----------------");
for(int i=0; i<20 && (b=bis.read())!=-1; i++) {
System.out.print((char)b);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出实例(中间正好遇到回车(13)换行(10)符):
true
NO.1-----------------
class MyException
NO.2-----------------
import java.util.*;
Ø 测试BufferedWriter、BufferedReader
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class TestBufferWriter {
public static void main(String[] args) {
String s;
try {
BufferedWriter bw = new BufferedWriter
(new FileWriter("D://java+必备软件//java//16//data1.txt"));
BufferedReader br = new BufferedReader
(new FileReader("D://java+必备软件//java//16//data1.txt"));
for(int i=0; i<10; i++) {
bw.write(String.valueOf(Math.random()));
bw.newLine();//写入一换行
}
bw.write("爱的翅膀");//写入中文
bw.flush();
while((s=br.readLine())!=null) {
//读取一行,该stream拥有的很好的一种使用方法
System.out.println(s);
}
bw.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ø 转换流
l InputStreamReader和OutputStreamWriter用于字节数据到字符数据的转换;
l InputStreamReader需要和InputStream”套接”;
l OutputStreamWriter需要和OutputStream”套接”;
l 转换流在构造时可以指定其编码集合,例如:
InputStreamReader isr = new InputStreamReader(System.in, “ISO8859-1”);
Ø 测试OutputStreamWriter(必须调用flush()方法才能将数据写入)
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class TestOutputStreamWriter {
public static void main(String[] args) {
int b;
try {
OutputStreamWriter osw = new OutputStreamWriter
(new FileOutputStream("D://java+必备软件//java//16//data1.txt"));
osw.write("Hello -- 你好!");//可以直接写字符串
osw.flush();//必须调用flush()方法才能将数据写到文件中
System.out.println(osw.getEncoding());//默认为BGK
BufferedReader br = new BufferedReader
(new FileReader("D://java+必备软件//java//16//data1.txt"));
System.out.println(br.readLine());//读取一行
FileReader fr = new FileReader
("D://java+必备软件//java//16//data1.txt");
while((b=fr.read())!=-1) {
System.out.print((char)b);
}
System.out.println();
//参数true表示追加数据,而不是覆盖,”ISO8859-1”是指定的编码,西方语言集合
osw = new OutputStreamWriter(new FileOutputStream
("D://java+必备软件//java//16//data1.txt", true), "ISO8859-1");
osw.write("我也好!");
osw.flush();//必须调用flush()方法才能将数据写到文件中
System.out.println(br.readLine());
System.out.println(osw.getEncoding());
osw.close();
br.close();
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
打印结果:
GBK
Hello -- 你好!
Hello -- 你好!
????
ISO8859_1
Ø 测试InputStreamReader
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class TestInputStreamReader {
public static void main(String[] args) {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
String strin = br.readLine();//阻塞式的方法
while(!strin.equalsIgnoreCase("exit")) {
System.out.println(strin.toUpperCase());
strin = br.readLine();
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
说明:System.in指的是连通Console的一个InputStream,通过这条Stream我们就可以读取输入到命令框的值了。同理,存在System.out
import java.io.IOException;
import java.io.OutputStreamWriter;
public class TestSystemout {
public static void main(String[] args) {
OutputStreamWriter osw = new OutputStreamWriter(System.out);
try {
//将值输出到Console框,作用相当于System.out.println(“…”);
osw.write("您好!");
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ø 数据流
Ø 测试DataInputStream和DataOutputStream
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestDataStream1 {
public static void main(String[] args) {
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("D://java+必备软件//java//16//data1.txt"));
dos.writeDouble(23);
dos.writeUTF("您好");
dos.writeBoolean(true);
DataInputStream dis = new DataInputStream(new FileInputStream("D://java+必备软件//java//16//data1.txt"));
System.out.println(dis.readDouble());
System.out.println(dis.readUTF());
System.out.println(dis.readBoolean());
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:写入文件data1.txt的数据并不是像写入的那样,但是由DataOutputStream读出显示的数据就是原来输入的数据。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class TestDataStream {
public static void main(String[] args) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeDouble(Math.random());
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.readBoolean());
dos.close();
dis.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
打印结果:
9
0.17502217440874912
True
Ø Print流
Ø 测试PrintStream
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
public class TestPrintStream {
public static void main(String[] args) {
PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream
("D://java+必备软件//java//16//data1.txt");
ps = new PrintStream(fos);
} catch(IOException e) {
e.printStackTrace();
}
if(ps != null) {
System.setOut(ps);//将System.out的输出对象改变了
}
int ln = 0;
for(char c=0; c<=60000; c++) {
System.out.print(c + "");//将不再输出到console窗口
if(ln++ >= 100) {
System.out.println();
ln = 0;
}
}
}
}
Ø Object流
直接将Object写入或读出(该Object必须先实现serializable/序列化接口,该接
口没有任何实现的方法,属于标志性接口)
ü 测试ObjectOutputStream、ObjectInputStream
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TestObjectStream {
public static void main(String[] args) {
T t = new T();
t.k = 8;
try {
FileOutputStream fos = new FileOutputStream
("D://java+必备软件//java//16//data1.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(t);//直接写入对象
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream
("D://java+必备软件//java//16//data1.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
T tReaded = (T)ois.readObject();
System.out.println
(tReaded.i + " " + tReaded.j + " " + tReaded.d + " " + tReaded.k);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
} catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class T implements Serializable {
int i = 10;
int j = 9;
double d = 2.3;
int k = 23;
}
打印结果:10 9 2.3 8
注意1:如果类中某个值在序列化的时候不想予以考虑,可以使用transient关键字,如:transient int k = 23;则此时打印结果为:10 9 2.3 0
注意2:serializable接口只将对象进行了序列化,但是具体是如何序列化的用户不清楚,为了实现用户能够自己进行序列化,提供了externalizable接口,里面主要有两个方法:
void readExternal(ObjectInput in)
void writeExternal(ObjectOutput out)