黑马程序员---java基础之IO(字符流和字节流)

时间:2023-02-25 18:50:34

------- android培训java培训、期待与您交流! ----------

IO(Input Output)流

IO流用来处理设备之间的数据传输
java对数据的操作是通过流的方式
java用于操作流的对象都在IO包中
按操作数据分为两种:字节流与字符流
按流向分为:输入流,输出流.
IO流常用基类
*字节流的抽象基类:
InputStream和OutputStream
*字符流的抽象基类:
Reader和Writer.
注意:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀.

字符流

既然IO流是用于操作数据的,
那么数据的最常见体现形式是:文件。

写入FileWriter

找到一个专门用于操作文件的Writer子类对象。FileWriter。  后缀名是父类名。 前缀名是该流对象的功能。

1----创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
//其实该步就是在明确数据要存放的目的地。
2.调用write方法,将字符串写入到流中。
3.刷新流对象中的缓冲中的数据。将数据刷到目的地中。
4.关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。将数据刷到目的地中。
//close和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
续写:
在创建对象时,在文件名后,传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。
****************************
在linux中  \n:代表换行   *
在windows中 \r\n:代表换行  *
****************************
class Main{
public static void main(String[] args){
FileWriter fw = null;//声明流.
try {
fw = new FileWriter("Demo.txt",true);//关联文件,并选择续写
for(int x=0;x<10;x++){
fw.write(x);//写入数据
fw.flush();//刷新流
}
} catch (IOException e) {
e.printStackTrace();
}finally{//关流一定要执行
try {
if(fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

读取FileReader
1.创建一个文件读取流对象,和指定名称的文件相关联。
要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
2.调用读取流对象的read方法。
//read():一次读一个字符。而且会自动往下读。

class Main{
public static void main(String[] args){
FileReader fr = null;//声明流.
try {
fr = new FileReader("Demo.txt");//关联文件
int len = 0;//定义标记
while((len = fr.read()) != -1){
System.out.println((char)len);//打印读取到的数据
}
} catch (IOException e) {
e.printStackTrace();
}finally{//关流一定要执行
try {
if(fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符流缓冲区

缓冲区的出现提高了对数据的读写效率.
对应类
BufferedWriter
BufferedReader
缓冲区要结合流才可以使用.
在流的基础上对流的功能进行了增强.


缓冲区的出现是为了提高流的操作效率而出现的。
所以在创建缓冲区之前,必须要先有流对象。
该缓冲区中提供了一个跨平台的换行符。
newLine();
字符读取流缓冲区:
该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。
当返回null时,表示读到文件末尾。
readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。
BufferedWriter步骤:
1.创建一个字符写入流对象.
2.创建一个BufferedWriter写入流缓冲区对象与写入流关联
3.写入流缓冲区写入.
4.写入流缓冲区刷新
5.写入流缓冲区关闭.其实关闭缓冲区,就是在关闭缓冲区中的流对象。

class  BufferedWriterDemo
{
public static void main(String[] args) throws IOException
{
//创建一个字符写入流对象。
FileWriter fw = new FileWriter("buf.txt");
//为了提高字符写入流效率。加入了缓冲技术。
//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
BufferedWriter bufw = new BufferedWriter(fw);
for(int x=1; x<5; x++){
bufw.write("abcd"+x);
bufw.newLine();
bufw.flush();
}
//其实关闭缓冲区,就是在关闭缓冲区中的流对象。
bufw.close();
}
}

BufferedReader步骤
1.创建一个字符读取流对象.
2.创建一个BufferedReader读取流缓冲区对象与读取流关联
3.读取流缓冲区读取;一行,readLine();
4.写入流缓冲区关闭.其实关闭缓冲区,就是在关闭缓冲区中的流对象。

class  BufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建一个读取流对象和文件相关联。
FileReader fr = new FileReader("buf.txt");
//为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
BufferedReader bufr = new BufferedReader(fr);
String line = null;
while((line=bufr.readLine())!=null){
System.out.print(line);
}
bufr.close();
}
}
********************************
只要用到缓冲区写入,就要记得刷新。
************************************

综合应用;复制一个文本文件,用缓冲区

class Main{
public static void main(String[] args){
BufferedWriter bw = null;//声明字符写入缓冲区
BufferedReader br = null;//声明字符读取缓冲区
try {
br = new BufferedReader(new FileReader("Main.class"));//将读取缓冲区与文件关联
bw = new BufferedWriter(new FileWriter("Main.txt",true));//将写入缓冲区与文件关联
String line = null;
while((line =br.readLine()) != null ){
bw.write(line);//写入一行
bw.newLine();//换行
bw.flush();//刷新流
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try{
if(br != null)
br.close();//关闭读取流
}catch(IOException e){
e.printStackTrace();
}finally{
try {
if(bw != null)
bw.close();//关闭写入流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

字节流

和字符流很像,只不过操作的是字节,而不是字符 操作文件的两个基类: FileOutputStream,写入流
FileOutputStream fos = new FileOutputStream("fos.txt");
fos.write("abcde".getBytes());
fos.close();
FileInputStream,读取流
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();
字节流的缓冲区: BufferedInputStream
BufferedOutputStream
实例:复制一个图片文件
class  CopyPic
{
public static void main(String[] args){
FileOutputStream fos = null;
FileInputStream fis = null;
try{
fos = new FileOutputStream("2.bmp");//定义写入目的地,也就是写入文件
fis = new FileInputStream("1.bmp");//定义源,也就是读取文件
byte[] buf = new byte[1024];//定义缓冲区
int len = 0;
while((len=fis.read(buf))!=-1){//循环读取写入
fos.write(buf,0,len);
}
}
catch (IOException e)
{
throw new RuntimeException("复制文件失败");
}
finally
{
try
{
if(fis!=null)
fis.close();
}
catch (IOException e)
{
throw new RuntimeException("读取关闭失败");
}
try
{
if(fos!=null)
fos.close();
}
catch (IOException e)
{
throw new RuntimeException("写入关闭失败");
}
}
}
}

注意:

字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。
而在写入数据时,只写该int类型数据的最低8位。


转换流:

InputStreamReader 

是字节流通向字符流的桥梁

//获取键盘录入对象。
InputStream in = System.in;
//将字节流对象转成字符流对象,使用转换流。InputStreamReader
InputStreamReader isr = new InputStreamReader(in);
//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
BufferedReader bufr = new BufferedReader(isr);
//键盘录入的最常见写法。
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));

OutputStreamWriter 

是字符流通向字节流的桥梁

OutputStream out = System.out;//获取屏幕输出对象
OutputStreamWriter osw = new OutputStreamWriter(out);//将字节流对象转成字符流对象,使用转换流。
BufferedWriter bufw = new BufferedWriter(osw);//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
//以上内容的简写形式
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流。

######IO流操作的基本规律######
流操作的基本规律:
最痛苦的就是流对象有很多,不知道该用哪一个。
通过三个明确来完成。
1,明确源和目的。
源:输入流。InputStream  Reader
目的:输出流。OutputStream  Writer。
2,操作的数据是否是纯文本。是否需要高效
是:字符流。Reader,Writer
不是:字节流。InputStream ,OutputStream
3,当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘。键盘
目的设备:内存,硬盘,控制台。


------- android培训java培训、期待与您交流! ----------