------- android培训、java培训、期待与您交流! ----------
IO流:
用于处理设备上数据。
流:可以理解数据的流动,就是一个数据流。IO流最终要以对象来体现,对象都存在IO包中。
流也进行分类:
1:输入流(读)和输出流(写)。
2:因为处理的数据不同,分为字节流和字符流。
字符流:
Reader:用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int)和 close()。
|---BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
|---LineNumberReader:跟踪行号的缓冲字符输入流。此类定义了方法setLineNumber(int)和getLineNumber(),它们可分别用于设置和获取当前行号。
|---InputStreamReader:是字节流通向字符流的桥梁:它使用指定的charset读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
|---FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。
|---CharArrayReader:
|---StringReader:
-------------------------------------------------
Writer:写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush()和 close()。
|---BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
|---OutputStreamWriter:是字符流通向字节流的桥梁:可使用指定的charset将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
|---FileWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。
|---PrintWriter:
|---CharArrayWriter:
|---StringWriter:
字节流:处理字节数据的流对象。设备上的数据无论是图片或者dvd,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。
那么为什么要有字符流呢?因为字符每个国家都不一样,所以涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,所以需要获取中文字节数据的同时+指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。
注意:流的操作只有两种:读和写。
流的体系因为功能不同,但是有共性内容,不断抽取,形成继承体系。该体系一共有四个基类,而且都是抽象类。
* 字节流的两个基类:InputStream OutputStream
* 字符流的两个基类:reader writer
* 在这四个系统中,它们的子类,都有一个共性特点:子类名后缀都是父类名,前缀名都是这个子类的功能名称。
* 先学习一下字符流的特点。既然IO流是操作数据的,那么数据最常见的体现形式就是文件。
* 那么先以操作文件为主来演示。
* 需求:在硬盘上,创建一个文件并写入一些文字数据。
*
* 找到一个专门操作文件的Writer子类对象,FileWriter,后缀名是父类名,前缀名是该流对象的功能。
FileWriter代码体现:
import java.io.FileWriter;
import java.io.IOException;
//FileWriter演示类
public class FileWriterDemo
{
public static void main(String[] args) throws IOException
{
//创建一个FileWriter对象,该对象一被初始化就要明确被操作的文件。
//而且该文件会被创建到指定的目录下。如果该路径下已有与指定文件名同名的文件,那么就会覆盖掉原来的那个文件。
//其实该步就是在明确数据要存放的目的地。
FileWriter f = new FileWriter("demo.txt");
//调用Write方法,将字符串写到了流中。
f.write("hello java IO");
//刷新该流的缓冲。刷新流对象中的缓冲中的数据。
//将数据刷到目的地中。
// f.flush();
//
// f.write(",hello itheima!");
// f.flush();
//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。将数据刷到指定目的地里面。
//和flush的区别在于,flush刷新后,流还可以继续使用。close刷新后会将流关闭。
f.close();
f.write("jiasududianxun!");
}
}
记住:实际开发中一定要记得关闭流资源。
流的异常处理方式:
import java.io.FileWriter;
import java.io.IOException;
/* IO异常的处理方式:抛是不合适的。
* */
public class FileWriterDemo2
{
public static void main(String[] args)
{
//创建一个写入字符流对象
FileWriter fw = null;
try
{
//创建文件
fw = new FileWriter("D:\\demo.txt");
//写入内容 hello itheima
fw.write("hello itheima!");
}
//处理IO异常
catch (IOException e)
{
sop("异常1:"+e.toString());
}
finally
{
try
{
//关闭写入流资源
if (fw != null)
fw.close();
}
//处理异常
catch (IOException e)
{
sop("异常2"+e.toString());
}
}
sop("over!");
}
//打印功能
public static void sop(Object obj)
{
System.out.println(obj);
}
}
一定要写finally,finally里面一定要有关闭流资源的动作。
FileReader:文件读取流。返回 -1,标志读到结尾。
使用FileReader读取一个文本文件。
代码体现:
/* 读取指定文件的第一种方式。
* */
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo
{
public static void main(String[] args) throws IOException
{
//1.创建一个文件读取流对象,和指定名称的文件相关联。而且要保证该文件是已经存在的,如果不存在,将会抛出异常。
//FileNotFoundException文件未找到异常。
FileReader fr = new FileReader("demo.txt");
//调用读取流对象的read()方法。read方法一次只能读一个字符。而且会自动往下读。
int ch = 0;
//字符读取流对象循环读取数据。
while ((ch = fr.read()) != -1)
//每读到一个数据就转换成字符打印到控制台
sop((char)ch);
}
//定义的打印功能
public static void sop(Object obj)
{
System.out.println(obj);
}
}
第二种方法:
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
/* 读取文件的第二种方式:通过字符数组进行读取。
* */
public class FileReaderDemo2
{
public static void main(String[] args) throws IOException
{
//创建读取字符流,并关联要读取的文件
FileReader fr = new FileReader("demo.txt");
//定义一个字符数组,存储读到的字符。该read方法返回的是读到的字符个数。
char[] ch = new char[1024];
//num变量用于记录读取到字符的个数
int num = 0;
//读取字符流循环读取字符并全部存入到字符数组当中
while ((num = fr.read(ch)) != -1)
//将数组中的字符转换成字符串从0到最大个数的打印到控制台
sop(new String(ch, 0, num));
}
//定义的打印功能
public static void sop(Object obj)
{
System.out.println(obj);
}
}
BufferedWriter:写入流缓冲区:
* 缓冲区的出现就是为了提高流的操作效率。
*
* 所以在创建缓冲区之前,必须先有流对象。
*
* 该缓冲区中提供了一个跨平台的换行方法,newLine()
代码体现:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo
{
public static void main(String[] args) throws IOException
{
//创建一个字符流写入对象
FileWriter fw = new FileWriter("buf.txt");
//为了提高写入字符流的操作效率,加入缓冲技术。只要将需要提高效率的流对象作为参数传递给缓冲区的构造函数即可。
BufferedWriter bufw = new BufferedWriter(fw);
for (int i = 0; i < 5; i++)
{
bufw.write("itheima.....");
bufw.newLine();
bufw.flush();
}
//记住::只要用到缓冲区,就需要刷新。
// bufw.flush();
//其实关闭缓冲区,就是在关闭缓冲区所操作的流对象。所以,不用再对流对象进行单独的关闭.
bufw.close();
}
}
BufferedReader:读取流缓冲区:
* 该方法提供了一次读一行的方法readLine(),方便于对文本数据的获取。
* 当返回null时,表示读到了文件的末尾。
*
* 而readLine()方法返回的时候,只返回回车符之前的数据内容,并不返回回车符。。
代码体现:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建一个读取字符流对象和要读取的文件进行关联
FileReader fr = new FileReader("buf.txt");
//为了提高效率,加入缓冲技术。将流对象作为参数传给缓冲对象的构造函数
BufferedReader bufr = new BufferedReader(fr);
// String s1 = bufr.readLine();
// System.out.println(s1);
//冷变量,用来记录读取到的一行字符串
String len = null;
//一行一行的循环读取缓冲区中的字符串,用len变量记录
while ((len = bufr.readLine()) != null)
//每读取一行字符串就打印一行
System.out.println(len);
//读取第一种方式:读一个打印一个。
// int ch = 0;
// while ((ch = bufr.read()) != -1)
// System.out.println((char)ch);
//读取第二种方式:循环读取,存入一个字符数组,再一次性打印。
// char[] arr = new char[1024];
//
// int len = 0;
// while ((len = bufr.read(arr)) != -1)
// System.out.println(new String(arr, 0, len));
//关闭流资源
bufr.close();
}
}