一、概述:
IO(InputOutput)流
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中
流按操作数据分为两种:字节流与字符流。
文件通常是由一连串的字节或字符构成,组成文件的字节序列称为字节流。
组成文件的字符序列称为字符流。
流按流向分为:输入流与输出流。
输入流是将文件或其它输入设备的数据加载到内存的过程。
输出流恰恰相反,是将内存中的数据保存到文件或其他输出设备。
字节流的抽象基类:
InputStream,OutputStream。
字符流的抽象基类:
Reader, Writer。
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
如:InputStream的子类FileInputStream。
如:Reader的子类FileReader。
二、字符流的读写
1、写入字符流:
1)创建一个FileWriter对象,该对象一被初始化,就必须要明确被操作的文件。且该目录下如果已有同名文件,则同名文件将被覆盖。其实该步就是在明确数据要存放的目的地。
2)调用write(Strings)方法,将字符串写入到流中。
3)调用flush()方法,刷新该流的缓冲,将数据刷新到目的地中。
4)调用close()方法,是关闭流资源。但是关闭前会刷新一次内部的缓冲数据,并将数据刷新到目的地中。
具体代码:
/*
* IO异常处理规范 try 外声明对象流引用 try 内建立对象初始化
*/
publicstaticvoid main(String argsp[]) {
FileWriter fw = null;
try {
fw = new FileWriter("demo1.txt");
fw.write("I loveJava");
fw.flush();
} catch (IOException e) {
System.out.print(e.toString());
} finally {
if(fw !=null)
try {
fw.close();
} catch (IOException e) {
//将关闭失败文件记录到日志文件中
thrownew RuntimeException("关闭失败");
}
}
}
2、读取字符流:
1)创建一个文件读取流对象,和指定名称的文件相关联。要保证该文件已经存在,若不存在,将会发生异常FileNotFoundException。
2)调用读取流对象的read()方法。read():一次读一个字符,且会继续往下读。
第一种方式:读取单个字符。第二种方式:通过字符数组进行读取。
3)读取后要将流资源关闭。
具体代码:
/*
* IO异常处理规范 try 外声明对象流引用 try 内建立对象初始化
* 使用FileReader在构建造时明确被读取的文件
* 通过FileReader读取单个字符
* 读取到什么字符,就返回什么字符,读到结尾就返回-1,用-1来就标示结束了
*/
publicstaticvoid main(String argsp[]) {
FileReader fr = null;
try {
fr = new FileReader("demo1.txt");
char[] cbuf =newchar[22];
int hasRead = 0;
while((hasRead = fr.read(cbuf))!=-1)
{
System.out.print(new String(cbuf,0,hasRead));
}
} catch (IOException e) {
System.out.print(e.toString());
} finally {
if(fr !=null)
try {
fr.close();
} catch (IOException e) {
//将关闭失败文件记录到日志文件中
thrownew RuntimeException("关闭失败");
}
}
}
三、文件的拷贝:
原理:其实就是将一个磁盘下的文件数据存储到另一个磁盘的一个文件中
步骤:
1、在D盘上创建一个文件,用于存储E盘文件中的数据
2、定义读取流和E盘文件关联
3、通过不断读写完成数据存储
方式一:读取一个字符,存入一个字符
方式二:先将读取的数据存入到内存中,再将存入的字符取出写入D盘
4、关闭流资源:输入流资源和输出流资源。
具体代码:
/*
* 复制方式二
* 使用缓冲区数组
* 使用的就是可以操作数组的读写方式
*
*/
publicstaticvoid main(String args[])
{
FileReader fr =null;
FileWriter fw = null;
try {
fr =new FileReader("Test1.txt");
fw = new FileWriter("copy_Test2.txt");
char[] buf =new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1)
{
fw.write(buf, 0, len);
}
} catch (IOException e) {
System.out.println(e.toString());
}finally{
if(fw!=null)
try {
fw.close();
} catch (IOException e) {
thrownew RuntimeException("打开文件失败");
}
if(fr!=null)
try {
fr.close();
} catch (IOException e) {
thrownew RuntimeException("读取文件失败");
}
}
}
字符流缓冲区
l 缓冲区的出现提高了对数据的读写效率。
l 对应类 BufferedWriter BufferedReader
l 缓冲区要结合流才可以使用。
在流的基础上对流的功能进行了增强
字符流缓冲区写数据:
具体代码:
publicstaticvoid main(String[] args)throws IOException {
FileWriter fw =new FileWriter("buf.txt");
BufferedWriter bufw =new BufferedWriter(fw);
bufw.write("abcdef");
bufw.flush();
bufw.close();//关闭缓冲区就是关闭缓冲区关联的流
}
利用缓冲字符流拷贝文件方法:
publicstaticvoid main(String args[]) {
FileReader fr = null;
FileWriter fw = null;
BufferedReader bufr = null;
BufferedWriter bufw = null;
try {
fr = new FileReader("Test1.txt");
fw = new FileWriter("Test2.txt");
bufr =new BufferedReader(fr);
bufw = new BufferedWriter(fw);
String len = null;
while((len=bufr.readLine())!=null)
{
bufw.write(len);
bufw.newLine();
bufw.flush();
}
} catch (IOException e) {
System.out.println(e.toString());
}finally{
if(bufr!=null)
try {
bufr.close();
} catch (IOException e) {
e.printStackTrace();
}
if(bufr!=null)
try {
bufr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
IO包中其他数据类
操作基本数据类型 DataInputStream与DataOutputStream
操作字节数组 ByteArrayInputStream与ByteArrayOutputStream
操作字符数组 CharArrayReader与CharArrayWrite
操作字符串 StringReader 与 StringWriter
编码:字符串à字节数组
解码:字节数组à字符串
复制一个Mp3
1,明确源和目的:既有源,又有目的。
源:InputStream Reader
目的:OutputStream Writer.
2,明确是否是纯文本?不是!
源:InputStream
目的:OutputStream
3,明确设备:
源:硬盘
目的:硬盘:
FileInputStream fis = new FileInputStream("1.mp3");
FileOutputStream fos = new FileOutputStrema("2.mp3");
代码实现如下所示:
//使用字节流已有的缓冲区。
public static void copy_2() throws IOException {
FileInputStream fis = new FileInputStream("0.mp3");
FileOutputStream fos = new FileOutputStream("1.mp3");
BufferedInputStream bufis = new BufferedInputStream(fis);
BufferedOutputStream bufos = new BufferedOutputStream(fos);
int by = 0;
while((by=bufis.read())!=-1){
bufos.write(by);
}
bufos.close();
bufis.close();
}
//自定义数组缓冲区的方式。
public static void copy_1() throws IOException {
//1,读取流对象,和mp3关联。
FileInputStream fis = new FileInputStream("0.mp3");
//2,写入流对象,明确存储mp3数据的目的。
FileOutputStream fos = new FileOutputStream("1.mp3");
//3,定义一个字节缓冲区。
byte[] buf = new byte[1024*8];
int len = 0;
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
fis.close();
}
需求:读取键盘录入的数据,将这些数据转成大写打印在屏幕上,如果录入的是 over, 程序结束。
思路:
1,通过键盘录入读取字节数据。
2,将这些读到的字节数据进行存储以变成字符串。
3,对这个字符串进行判断。如果不是over就将其转成大写打印。如果是over就结束。
代码具体实现如下所示:
public static void readKey() throws IOException {
//1,获取键盘录入流对象。
InputStream in = System.in;
//2,定义一个容器用于存储读取到的字节。
StringBuilder sb = new StringBuilder();
//3,循环读取键盘。
int ch = 0;
while((ch=in.read())!=-1){
//需要对读取到的字节进行判断。
//如果是/r 或者 /n,不存储,并视为一次录入内容结束符。对之前的录入数据进行判断。
if(ch=='\r')
continue;
if(ch=='\n'){
String s = sb.toString();
if("over".equals(s)){//记住:如果要使用键盘录入,一定要自定义结束标记。
break;
}
else{
System.out.println(s.toUpperCase());
//清空缓冲区。
sb.delete(0, sb.length());
}
}
else
sb.append((char)ch);
}
}
}
打印流
PrintWriter与PrintStream
可以直接操作输入流和文件。
序列流
SequenceInputStream
对多个流进行合并。
操作对象
ObjectInputStream与ObjectOutputStream
被操作的对象需要实现Serializable(标记接口);