------- android培训、java培训、期待与您交流! ----------
大多数的应用程序都需要实现与设备之间的数据传输,例如:键盘可以输入数据,显示器可以显示程序的运行结果等,此时,就需要用到java中的IO流操作来对数据进行处理
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的对象都在io包中
IO体系:
流按操作数据
|---字节流(InputStream OutputStream)
|---字符流(Reader Writer)
流按流向
|---输入流
|---输出流
字节流两个基类:InputStream OutputStream
字符流两个基类:Reader Writer
字符流:
字符流的特点:
既然IO流是用于操作数据的,那么数据的最常见体现形式是:文件
字符流常见的方法:
close()方法:关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地中
flush()方法:刷新流资源
close()和flush()的区别在于:flush刷新后,流可以继续使用,close刷新后,会将流关闭
IO的异常处理方式:IO流在异常处理时,必须要使用finally,因为关闭流是必须要操作的
import java.io.*;
class FileWriterDemo
{
public static void main(String[] args)
{
FileWriter fw=null;
try
{
fw=new FileWriter("demo.txt",true);
fw.write("7890123456");
}
catch (IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if(fw!=null)
{
fw.close();
}
}
catch (IOException e)
{
System.out.println(e.toString());
}
}
}
}
字符流的文本文件读取方式:
文本文件读取方式一:
read()方法:一次读一个字符,而且会自动往下读
文本文件读取方式二:
通过字符数组进行读取
拷贝文本文件图例:
字符流中加入缓冲区:
缓冲区的出现提高了对数据的读写效率
对应的类
BufferedReader
BufferedWriter
缓冲区要结合流才可以使用,只是在流的基础上对流的功能进行了增强
该缓冲区中提供了一个跨平台的换行符 newLine();
字符读取缓冲区中提供了一个一次读一行的方法,方便于对文本数据的获取。readLine
当返回null时,表示读到文件的末尾
字符流加入的例题:复制一个文本文件
import java.io.*;
class BufferedDemo
{
public static void main(String[] args) throws IOException
{
BufferedWriter buffw=new BufferedWriter(new FileWriter("demo1_copy.java"));
BufferedReader buffr=new BufferedReader(new FileReader("demo1.java"));
String line=null;
while((line=buffr.readLine())!=null)
{
buffw.write(line);
buffw.newLine();
buffw.flush();
}
buffr.close();
buffw.close();
}
}
readLine()方法返回的时候只返回回车符之前的数据内容,并不返回回车符
字节流(InputStream OutputStream)
想要操作除了文本文件之外的东西,如:图片 MP3等就要用到字节流
InputStream的三种读取方式:
(1) FileInputStream fis=new FileInputStream(“fos.txt”);
int ch=0;
while((ch=fis.read())!=-1)
{
System.out.println((char)ch)
}
fis.close();
(2) FileInputStream fis=new FileInputStream(“fos.txt”);
byte[] buf=new byte[1024];
Int len=0;
while((len=fis.read(buf))!=-1)
{
System.out.println(new String(buf,0,len));
}
fis.close();
(3) FileInputStream fis=new FileInputStream(“fos.txt”);
byte[] buf=new byte[fis.available()];
fis.read(buf);
System.out.println(new String(buf));
fis.close();
字节流加入缓冲区:
对应的类:
BufferedOutputStream
BufferedInputStream
读取键盘录入:
System.out:对应的是标准输出设备,控制台
System.in:对应的是标准输入设备,键盘
能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?
readLine方法是字符流BufferedReader类中的方法
而键盘录入的read方法是字节流InputStream的方法
那么能不能将字节流转成字符流在使用字符流缓冲区得readLine方法呢?
InputStreamReader:是字节流通向字符流的桥梁
OutputStreamWriter:是字符流通向字节流的桥梁
什么是字符流通向字节流?
就是我本身有一些我自己熟悉的文字,把它变成字节,Writer是写出去,把这些文件写出去,这些文字是以字节的形式存在的,而往里面录入的都是字符,通俗的一句话就是,往文件中录的的字符,而存在的是字节。
其实读取键盘录入的语句就是:
BufferReader bufr=new BufferedReader(new InputStreamReader(System.in));
流操作的基本规律:
最痛苦的就是流对象有很多不知道该用哪一个
通过三个明确来完成:
1、明确源和目的
源:输入流 InputStream Reader
目的:目的 OutputStream Writer
2、操作的数据是否是纯文本
是:字符流
不是:字节流
3、当体系明确后,在明确要使用哪个具体的对象
通过设备来进行区分
源设备:内存,硬盘,键盘
目的设备:内存,硬盘(文件),控制台
练习:
将一个图片文件中数据存储到另一个文件中。复制文件,要按照以上格式完成三个明确
源:因为是源,所以使用读取流InputStream Reader,
是不是操作图片,是!这时就可以选择InputStream,这样体系就明确了
接下来明确要使用该体系中的哪个对象。
明确设备:硬盘上的一个图片
Reader体系中可以操作图片的对象是InputStream
是否需要提高效率? 是,加入Reader体系中的缓冲区BufferedReader
InputStream is=new InputStream (“a.jpg”);
BufferedReader bufr=new BufferedReader(fr);
目的:OutputStream Writer
是否操作图片
是!OutputStream
设备:硬盘上的一个图片
Writer体系中可以操作图片的对象是OutputStream
是否需要提高效率? 是,加入Writer体系中的缓冲区BufferedWriter
OutputStream os=new OutputStream (“b.jpg”);
BufferedWriter bufw=new BufferedWriter(fw);
例题:将异常打印到文件上,并且显示异常的出现的时间
import java.io.*;
import java.util.*;
import java.text.*;
class ExceptionInfo
{
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 sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s=sdf.format(d);
PrintStream ps=new PrintStream("execption.log");
ps.println(ps);
System.setOut(ps);
}
catch (Exception ex)
{
throw new RuntimeException("日志文件创建失败");
}
e.printStackTrace(System.out);
}
}
}
其他流
打印流:(PrintStream PrintWriter)
该流提供了打印方法,可以将各种数据累心过的数据都原样打印
字节打印流:
PrintStream
构造函数可以接收的参数类型
1.file对象 File
2.字符串路径 String
3.字节输出流 OutputStream
字符打印流
PrintWriter
1.file对象 File
2.字符串路径 String
3.字节输出流 OutputStream
4.字符输出流 Writer
import java.io.*;
class PrintDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
PrintStream ps=new PrintStream(new FileOutputStream("c:\\a.txt"));
String line=null;
while((line=buf.readLine())!=null)
{
if("over".equals(line))
break;
ps.println(line.toUpperCase());
}
ps.close();
buf.close();
}
}
序列流(合并流):SequenceInputStream
管道流 PipedInputStream和PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用
集合中涉及IO流是Properties
管道流是涉及到多线程的IO流
RandomAccessFile:随机访问文件
特点:
该类不算是IO体系中的子类
而是直接继承自object
但是它是IO包中的成员,因为它具备读和写功能
内部封装了一个书u,而且通过指针对数组的元素进行操作
可以通过getFilePointer获取指针的位置
同时可以通过seek改变指针的位置
其实完成读写的原理就是内部封装了字节输入流和输出流
通过构造函数可以看出,该类只能操作文件
而且操作文件还有模式:只读r,读写rw等
如果模式为只读r,不会创建文件,会去读取一个已存在的文件,如果该文件不存在,则会出现异常
如果模式为读写rw,操作的文件不存在,会自动创建,如果存在不会覆盖
而且该对象的构造函数要操作的文件不存在,会自动创建,如果存在则不会覆盖
操作基本数据类型的流对象(DataStream):
DataInputStream和DataOutputStream
可以用于操作基本数据类型的数据的流对象
ByteArrayStream:
用于操作字节数字的流对象
ByteArrayInputStream:在构造的时候需要接收数据源,而且数据源是一个字节数组
ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经能够内部封装了可变长度的字节数组 这就是数据目的地
因为这两个流对象都操作的数组,并没有使用系统资源
所以要,不用进行close关闭
在流操作规律讲解时:
源设备
键盘 System.in 硬盘 FileStream 内存 ArrayStream
目的设备
控制台 System.out 硬盘 FileStream 内存 ArrayStream
------- android培训、java培训、期待与您交流! ----------