程序中所有的数据都是以“流”的方式进行传输和保存的,程序需要数据要使用输入流读取数据,程序需要将一些数据保存起来时,就要使用输出流。
按处理的数据类型分:
- 字节流:主要操作 byte 数据类型,以 byte 数组为主,主要的操作类是OutputStream类 和 InputStream类
- 字符流:主要操作char 数据类型,以char,char[],String为主,主要的操作类是Writer 和 Reader.
按流向分:
- 输入流:程序从输入流读取数据源,数据源包括外界(键盘,文件,网络....),即将数据源读入到程序的通信通道。
- 输出流:程序向输出流写入数据, 将程序中的数据输出到外界(显示器,打印机,文件,网络...)等通信通道。
1.字节输出流:OutputStream(抽象类)
OutputStream 是整个IO 中字节输出流的最大父类(抽象类),要使用此类,则必须通过其子类实例化对象。
OutputStream 定义如下:
public abstract class OutputStream implements Closeable, Flushable
OutputStream 常用方法:
public void close() throws IOException //关闭输出流
public void flush() throws IOException //刷新缓冲区
public void write(byte[] b) throws IOException //将一个byte数组写入数据流
public void write(byte[],int off,int len) throws IOExcetption //将一个指定范围的byte数组写入数据流
public abstract void write(int b) throws IOException //将一个字节数据写入数据流
OutputStream 子类 FileOutputStream 实现向文件中写入字符串
/**
* 向文件中写入字符串
*
* @author lyh
*
*/
public class OutputStreamDemo1 {
public static void main(String args[]) throws Exception {
File file = new File("d:" + File.separator + "OutputStreamDemo-test.txt");
//恢复现场
if(file.exists()) file.delete();
OutputStream out = null;
out = new FileOutputStream(file);
String str = "Hello world !!";
// 只能输出byte数组,所以将字符串变为byte数组
byte[] b = str.getBytes();
// 将内容输出
// out.write(b);
// 以循环的方式输出内容
for (int i = 0; i < b.length; i++) {
out.write(b[i]);
}
// 关闭输出留
out.close();
// 追加新内容
out = new FileOutputStream(file, true);
String str2 = "追加Hello world second!!!";
out.write(str2.getBytes());
// 换行,追加内容
String str3 = "\r\n this is new line";
out.write(str3.getBytes());
out.close();
}
}
2.字节输入流: InputStream(抽象类)
InputStream 定义如下:
public abstract class InputStream extends Object implements Closeable
InputStream 类的常用方法:
public int avaiable() throws IOException //取得输入文件的大小
public void close() throws IOException //关闭输入流
public abstract int read() throws IOException //以数字的方式读取内容
public int read(byte[] b) throws IOException // 将内容读到byte[] 数组,同时返回读入的个数
InputStream 子类 FileInputStream 实现读取文件中的数据
/**
* 通过read() 读取数据
*
* @author lyh
*
*/
public class InputStreamDemo1 {
public static void main(String args[]) throws Exception {
File file = new File("d:" + File.separator + "OutputStreamDemo-test.txt");
InputStream in = null;
in = new FileInputStream(file);
// 用循环的方法为byte b[] 赋值
/*byte b[] = new byte[(int) file.length()];
for (int i = 0; i < b.length; i++) {
b[i] = (byte) in.read();
}
*/
int len = 0;
byte b[] = new byte[1024];
int temp = 0; // 接收读取的每一个内容
while ((temp = in.read()) != -1) {
b[len] = (byte) temp; // 将每次读取的内容给temp,如果temp不等于-1,表示文件没有读完
len++;
}
in.close(); // 关闭流
System.out.println("内容是:" + new String(b));
}
}
3.字符输出流 Writer(抽象类)
Writer (抽象类):
public abstract class Writer extends Object implements Appendable, Closeable,Flushable
Writer类常用方法
public abstract void close() throws IOException //关闭输出流
public void write(String str) throws IOException //将字符串输出
public void write(char[] cbuf) throws IOException //将字符数组输出
public abstract void flush() throws IOException //强制性清空缓存
(Writer的子类,转换流) OutputStreamWriter的子类 FileWriter 实现向文件中写入数据
public class WriteDemo1 {
public static void main(String args[]) throws Exception {
File f1 = new File("D:" + File.separator + "writeDemo.txt");
Writer out = null;
out = new FileWriter(f1);
String str = "Hello World";
out.write(str); // 写入内容
out.close();
// 追加内容
out = new FileWriter(f1, true); // 将append的值设置为true
String str2 = "\r\n Hello world agant!!!";
out.write(str2);
out.close();
}
}
4.字符输入流 Reader
Reader(抽象类)
public abstract class Reader extends Object implements Readable,Closeable
Reader类常用方法
public abstract void close() throws IOException //关闭输入流
public int read() throws IOException //读取单个字符
public int read(char[] cbuf) throws IOException //将字符读到字符数组中,返回读入的长度
(Reader的子类,转换流)InputStreamReader的子类 FileReader类实现从文本中读取数据
public class ReaderDemo1 {
public static void main(String args[]) throws Exception{
File f1 = new File("D:"+File.separator+"writeDemo.txt");
if(!f1.exists()){
System.out.println("文件:"+f1+"不存在");
}else{
Reader reader = null;
reader = new FileReader(f1);
char c[]=new char[1024];
//方法1
//int len = reader.read(c);
//方法2 利用for循环为char c[] 赋值
int len = 0;
int temp = 0;
while((temp = reader.read())!=-1){
c[len] =(char)temp;
len++;
}
reader.close();
System.out.println("内容为:"+ new String(c,0,len));
}
}
}
字节流与字符流的区别:
实际上字节流操作不会用到缓冲区(内存),是在文件本身直接操作,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件。如若在不关闭操作流的前提下(实际开发中不允许操作为流后不关闭流),用字节流和字符流分别向 type.txt, char.txt文件中写入数据"abc",直接打开文件,会发现type.txt中已被写入数据abc,而char.txt文件却没有,只有在用字符流调用flush(),强制性地将缓冲区中的内容输出,才能在char.txt中看到内容(关闭字符流时会强制性地将缓冲区中的内容输出)。
FileWriter并不直接是Writer的子类,而是OutputStreamWriter的子类,而FileReader也不直接是Reader的子类,是InputStreamReader的子类,从这俩个类的继承关系就能看出,不管是使用字符流还是字节流,实际上最终都是以字节流的方式在操作输入/输出流。
使用字符流好还是字节流好?
当然是具体情况具体分析,但是,所有文件在硬盘或在传输时都是以字节的方式进行的,包括图片等都是按字节的方式存储的,而字符只有在内存中才会形成,所以在实际的开发中,字节流会应用得比较多一些。
5.转换流-OutputStreamWriter and InputStreamReader
OutputStreamWriter: 是Writer 的子类 ,将输出的字符流变为字节流,即将一个字符流的输出对象变为字节流输出对象。
InputStreamReader: 是Reader的子类,将输入的字节流变为字符流,即将一个字节流的输入对象变为字符流输入对象。
6.内存操作流 ByteArrayOutputStream,ByteArrayInputStream
内存操作流一般在生成一些临时文件是才会使用,如果是直接使用将临时文件保存在文件的话,则代码执行完后还得删除这个临时文件,所以在此场景中使用内存操作流是最合适的。
ByteArrayInputStream 常用方法:
public ByteArrayInputStream(byte[] buf) //将全部内容写入内存中
public ByteArrayInputStream(byte[] buf,int offset,int length) //将指定范围的内容写入到内存中
ByteArrayOutputStream 常用方法:
public ByteArrayOutputStream() //创建对象
public void write(int b) //将内容从内存中输出
内存操作流实现大写字母转换为小写字母
public class ByteArrayDemo {
public static void main(String args[]){
String str = "THIS IS A TEST FOR BYTEARRAYDEMO!";
ByteArrayInputStream in = null;
ByteArrayOutputStream out = null;
in = new ByteArrayInputStream(str.getBytes());
out = new ByteArrayOutputStream();
int temp = 0;
while((temp=in.read())!=-1){
out.write(Character.toLowerCase(temp));
}
String result = out.toString();
try{
in.close();
out.close();
}catch(IOException e){
e.printStackTrace();
}
System.out.println("转换后的结果为 "+result);
}
}
7.管道流- 管道输出流(PipedOutputStream),管道输入流(PipedInputStream)
管道流主要作用于两个线程之间的通信,如果要进行管道输出,则必须把输出流连在输入流上。
管道流实现两个线程的通信
class Send implements Runnable{ //实现Runnable接口
private PipedOutputStream out= null;
public Send(){
this.out = new PipedOutputStream(); //实例化输出流
}
public void run(){
String str = "Hello , this is out speacking!";
try{
this.out.write(str.getBytes()); //输出信息
}catch(IOException e){
e.printStackTrace();
}
try{
out.close(); //关闭流
}catch(IOException x){
x.printStackTrace();
}
}
public PipedOutputStream getOut(){
return out;
}
}
class Recevie implements Runnable{
private PipedInputStream in = null;
public Recevie(){
this.in = new PipedInputStream();
}
public void run(){
byte b[] = new byte[1024];
int len = 0;
try{
len = this.in.read(b); //接收数据
}catch(IOException e){
e.printStackTrace();
}
try{
this.in.close();
}catch(IOException e){
e.printStackTrace();
}
System.out.println("接收到的内容为:" + new String(b,0,len));
}
public PipedInputStream getIn(){
return in;
}
}
public class PipedDemo {
public static void main(String args[]) {
Send s = new Send();
Recevie r = new Recevie();
try{
s.getOut().connect(r.getIn()); //连接管道
}catch(IOException e){
e.printStackTrace();
}
new Thread(s).start();
new Thread(r).start();
}
}
8.打印流
打印流提供了非常方便的的打印功能,可以打印任何的数据类型,如小数,整数,字符串等。
字节打印流 PrintStream 是 OutputStrram 的子类,其常用方法有:
public PrintStream(File file) throws FileNotFoundException //通过一个File对象实例化PrintStream类
public PrintStream(OutputStream out) //接收OutputStram对象,实例化PrintStram类
public PrintStream printf(Locate I,String format,Object..args) //根据指定的Locate进行格式化输出
public PrintStream printf(String format,Object..args) //根据本地环境格式化输出
public void print(boolean b) //此方式被重载很多次,输出任意数据
public void println(boolean b) //此方式被重载很多次,输出任意数据后换行
PrintStream实现格式化输出:
public class PrintDemo {
public static void main(String arg[]) throws Exception{
PrintStream ps = null;
ps = new PrintStream(new FileOutputStream(new File("d:"+File.separator+"text.txt")));
ps.print("hello ");
ps.println("world !!!");
ps.println("1+1="+ 2);
/**
* 格式化输出
* %s 表示输出字符串
* %c 表示输出字符
* %d 表示输出整数
* %f 表示输出小数
*/
String name = "李白"; //字符串
int age = 30; //整数
float score = 55.34f; //小数
char sex = 'M'; //字符
ps.printf("name:%s;age:%d;score:%f;sex:%c",name,age,score,sex);
ps.close();
}
}
**************************test.txt 结果内容为**********************************************
hello world !!!
1+1=2
name:李白;age:30;score:55.340000;sex:M
**********************************************************************************************
9.字符缓存流 BufferedReader,BufferedWriter
BufferedReader类用于从缓存区中读取数据,所有的输入字节数据都放在缓冲区中。
BufferedReader类常用方法
public BufferedReader(Reader in) //接收一个Reader类的实例
public String readLine() throws IOException //一次性将缓冲区中内容全部读出
BufferedReader 实现接收键盘的输入,将信息打印出来
public class BufferedReaderDemo {
public static void main(String args[]){
BufferedReader buf = null;
//由于System.in是字节流,而new BufferedReader()的参数为字符流,所以需要用转换流将字节流转换成字符流
buf = new BufferedReader(new InputStreamReader(System.in));
String str = null;
System.out.print("请输入内容:");
try{
str=buf.readLine(); //读取输入内容
}catch(IOException e){
e.printStackTrace();
}
System.out.println("输入的内容为:"+ str);
}
}