IO流
IO流:
IO流用来处理设备之间的数据传输
java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中
流按操作数据分为:字节流和字符流
流按流向分为:输入流和输出流
字节流:
处理字节数据的流对象。设备上的数据无论是图片或者dvd,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。
那么为什么要有字符流呢?每个国家语言都不一样,所以涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,所以需要获取中文字节数据的同时+ 指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。
IO流常用基类:
字节流的抽象基类:InputStream,OutputStream
字符流的抽象基类:Reader,Writer
注意:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
例:InputStream的子类FileInputStream
Reader的子类的FileReader
FileWriter
专门用来文件的子类对象,建立方式FileWriter fw=new FileWriter(被操作的文件)
调用write()方法写入数据,写入数据时不是直接写入文件中,而是写入流中(可以说是缓冲区)
用flush方法将流中的数据刷入文件中。
close也可以刷入数据,但是使用后不能继续写入数据,因为已经关闭了流资源。
package xiaobing.io;
import java.io.*;
public class FileWriterDemo01 {
public static void main(String[] args)
{
// TODO Auto-generated method stub
//创建一个FlieWriter对象,该对象一倍初始化就需要被操作的文件
FileWriter fw=null;
try
{
fw=new FileWriter("e:\\demo.txt");
//存入数据,写入流
fw.write("abcde");
//属性流对象中的缓冲数据
//刷入目的的中
fw.flush();
//可以继续存储
fw.write("asd");
fw.flush();
}catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(fw!=null)
//关闭资源
fw.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
IO异常的正常处理方式:
package xiaobing.io;
import java.io.*;
/*
* IO流异常处理
*/
public class Io {
public static void main(String[] args)
{
FileWriter fw=null;
try
{
fw=new FileWriter("l:\\demo.txt");
fw.write("sss");
}catch(IOException e)
{
e.printStackTrace();
}
//一定书写finally语句关闭流对象
finally
{
try
{
//一定要判断是否为空
//有几个流对象就要判断几次
if(fw!=null)
fw.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
文件续写:FileWriter fw=new FileWriter(被操作的文件,true),加上true参数,代表不覆盖已有文件,在已有文件的末尾继续写入数据
小练习:
package xiaobing.io;
import java.io.*;
/*
* 将E盘的一个文件复制到f盘
* 思路
* 1.在f盘创建文件准备存储数据
* 2.定义读取流与e盘关联
* 3.不断的读取和存入
* 4.关闭资源
*/
public class CopyDemo {
public static void main(String[] args)
{
method_1();
}
public static void method_1()
{
FileWriter fw=null;
FileReader fr=null;
try
{
fw=new FileWriter("f:\\copy.txt");//创建存储
fr=new FileReader("e:\\demo.txt");//复制的源
char[] ch=new char[1024];
int len=0;
if((len=fr.read(ch))!=-1)//读取然后存储
{
fw.write(ch,0,len);
}
}catch(IOException e)
{
e.printStackTrace();
}
finally//必须关闭流
{
if(fr!=null)
try
{
fr.close();
}catch(IOException e)
{
e.printStackTrace();
}
finally//关闭另一个
{
if(fw!=null)
try
{
fw.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
}
FileReader
读取文件流 FileReader fw=new FileReader(指定的文件)
1.用read()读取数据,一次读取一个会自动往下读,当没有数据时返回-1.
2.read(char[])读取字符个数,可以读所有数据。
package xiaobing.io;
import java.io.*;
public class FileReaderDemo {
public static void main(String[] arg)
{
//创建一个文件读取对象和指定名称的文件相关联
//要保证文件已经存在,如不存在,会发生异常
FileReader fr=null;
try
{
fr=new FileReader("e:\\demo.txt");
//读取单个字符read一次读一个,而且会自动往下读
int ch=fr.read();
System.out.println("ch.."+(char) ch);
//定义一个字符数组,用于存数得到的字符
//该read(char[])返回的是督导字符个数
char[] buf=new char[1024];
int num=fr.read(buf);
System.out.println(new String(buf,0,num));//节省空间存到指定长度即可
}catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(fr!=null)
//关闭资源
fr.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
字符流的缓冲区:
缓冲区的出现提高了对数据的读写效率。
对应类:BufferedWriter,BufferedReader
缓冲区要结合流才可以使用,就是创建缓冲区前必须要先有流对象。
在流的基础上对流的功能进行了增强
package xiaobing.io;
import java.io.*;
public class BufferedWriterDemo01 {
public static void main(String[] args)throws IOException//这里抛出了异常
{
//创建一写入流
FileWriter fw=new FileWriter("e:\\xiaobing.txt");
//为了提高字符写入效率,假如缓冲
//只需要将流对象作为参数传递给构造函数作为参数即可
BufferedWriter bfw=new BufferedWriter(fw);
bfw.write("abcdfer");
bfw.newLine();//newLine是换行符
bfw.write("111");
//只要用到缓冲区,就需要刷新
bfw.flush();
//关闭资源
bfw.close();//缓冲区操作流,关闭后fw就关闭了
}
}
package xiaobing.io;
import java.io.*;
public class BufferedReaderDemo {
public static void main(String[] args)throws Exception
{
//创建读取流对象和文件相关联
FileReader fr=new FileReader("e:\\CopyDemo.java");
//加入缓冲
BufferedReader bfr=new BufferedReader(fr);
//读取数据
String line=null;
while((line=bfr.readLine())!=null)//读取一行数据
{
System.out.println(line);
}
}
}
将上面的例子加入缓冲区:
package xiaobing.io;
import java.io.*;
public class BufferedDemoText01 {
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
FileWriter fw=new FileWriter("abcdefg.txt");
BufferedReader bfr=new BufferedReader(new FileReader("ListDemo.java"));
BufferedWriter bwr=new BufferedWriter(new FileWriter("ListDemo_copy.txt"));
String s1=null;
while((s1=bfr.readLine())!=null){
bwr.write(s1);
bwr.newLine();
bwr.flush();
}
}
}
扩展:
LineNumberReader:跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。
字节流OutputStream和InputStream
这个流是用来操作字节的操作图片、等大数据文件可以用这个类。
读取键盘的录入:
System.out:对应的是标准的输出设备,控制台
System.in:对应的是标准的输入设备,键盘
package xiaobing.io;
import java.io.*;
/*
* 读取键盘录入的数据,并将其大写返回
*/
public class SystemInDemo {
public static void main(String[] args)throws Exception
{
InputStream in=System.in;
StringBuilder sb=new StringBuilder();
while(true)
{
int ch=in.read();
if(ch=='\r')//读到\r跳出继续循环
continue;
if(ch=='\n')//读到\你时就集合前面输出的数据
{
String s=sb.toString();
if("over".equals(s))
break;
System.out.println(s.toUpperCase());
}
sb.append((char)ch);
}
}
}
流的转换:
键盘的常见写法:BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
流操作的基本规律:
选择哪个流对象操作,通过两个明确来完成
1.明确源和目的
源:输入流:InputStream,Reader
目的:输出流,OutputStream,Writer
2.操作的是否为为纯文本。
是:字符流
不是:字节流
3.当体系明确后,再明确使用哪个具体的对象
通过设备来区分
原设备:内存、硬盘、键盘
目的设备:内存、硬盘、控制台
例子:
1.将一个文本文件中数据存储到另一个文件中,复制文件。
分析:
是源:选择InputStream或Reader
是操作文本文件,选择字符流,即Reader
明确设备是硬盘,Reader体系中可以操作文件的对象时FileReader.
FileReader fr=new FileReader("a.txt")
目的:OutputStream,Writer
也是纯文本,Writer
Writer中可以操作文件的对象时FileWriter
FileWriter fw=new FileWriter("b.txt")
最后判断是否要提高效率,是就假如Reader体系中的缓冲区BufferedReader
练习:讲一个图片存储到另一个文件中:
package xiaobing.io;
import java.io.*;
/*
* 分析:
* 源:选择InputStream,Reader
* 操作的不是文本,使用InputStream
* 设备是硬盘,就是FileInputStream
* 需要提高效率加入缓冲区:BufferedInputStream
* 目的为BufferedOutputStream
*/
public class CopyPicDemo {
public static void main(String[] args) throws Exception
{
BufferedOutputStream bfo=new BufferedOutputStream(new FileOutputStream("e:\\234.png"));
BufferedInputStream bfi=new BufferedInputStream(new FileInputStream("e:\\123.png"));
int by=0;
while((by=bfi.read())!=-1)
{
bfo.write(by);
}
bfo.close();
bfi.close();
}
}
扩展:改变标准输入输出设备
System类中有setIn(InputStream in),setOut(OutputSteam out)来改变标准的输入出的方法,这样就可以用这个
方法来制作异常日志:
package xiaobing.io;
import java.io.*;
import java.util.*;
import java.text.*;
public class SystemLogDemo {
public static void main(String[] args)throws IOException
{
try
{
int[] arr=new int[2];
System.out.println(arr[3]);
}
catch(Exception e)
{
try
{
//在日志中加入日期
Date d=new Date();
SimpleDateFormat si=new SimpleDateFormat("yyyy--MM--dd HH:mm:ss");
String s=si.format(d);
PrintStream ps=new PrintStream("e:\\log.txt");
ps.println(s);
//改变标准输出流
System.setOut(ps);
}
catch(IOException ex)
{
throw new RuntimeException("日志创建失败");
}
e.printStackTrace(System.out);
}
}
}