黑马程序员Java笔记——IO篇之流对象

----------- android培训java培训、java学习型技术博客、期待与您交流! ---------

IO(Input Output)

 

(一)破题

 

IO流用来处理数据设备之间的数据传输;Java对数据的操作是通过流的方式;Java用于操作流的对象都在IO包中;

 

流按操作数据分为两种:字节流与字符流;

流按流向分为两种: 输入流(读取内存),输出流(写入外设);

 

数据是以(二进制)字节形式存在的。字节流可以处理所有对象。

字符流其实就是字节流+编码表;如果要操作文字数据,优先考虑字符流。

 

 

(二)简述

 

一、 IO流常用基类:

字节流的抽象基类:InputStream , OutputStream;

字符流的抽象基类:ReaderWriter.

 

这些体系中大多的子类都以父类名做后缀,子类名的前缀就是该对象的功能

 

二、 IO字符流常用子类:

 

Writer (体系)

           |——FileWriter

 

 

2 FileWriter往一个文件中写入文字数据;如果文件不存在,则会自动创建;如果存在文件则会覆盖

 

2FileWriter类中常用方法。

 

 

2.11)刷新数据flush( ); 返回值为void

 

2.12)关闭数据流 close();返回值为void

                    此方法在关闭流资源之前会先调用flush方法刷新再关闭;

 与flush方法比较:flush可以用多次,但是close方法只能用一次

 

2.13)写入数据 write();返回值为void

 

2.14)续写数据 在构造函数中加入true 可以实现续写;

FileWriter(String  FileNameboolean  true)

 

异常处理细节:

流对象一般会抛出异常,在try的外面进行对象的创建;在try内进行对象引用。

记着要判断空指针异常。

 

 

Reader (体系)

   |——FileReader

 

2.) FileReader:读取字符数据的流对象,在创建读取对象时,必须要明确被读取的文件,一定要确定该文件是存在的。

 

2.FileReader类中常用的方法

 

2.21) 读取数据 read();有重载方法,有多种返回类型

 

三、

3.)字符流缓冲区:缓冲区的出现提高了对数据的读写效率。缓冲区要结合流才可以使用。

在流的基础上对流的功能进行了增强,(虽然也可以自定义缓冲区)。

这样可以使用字符流缓冲区对外提供的方法。

 

对应类BufferedWriter  BufferedReade

 

3.1BufferedWriter (体系)

|——

 

BufferedWriter类中常用方法

 

3.11write( ) 写入数据进缓冲区

3.12flush()刷新

3.13newLine( ) 换行(此方法为BufferedWriter类特有,其他类不适用)

使用系统方法实现平台的换行操作:System.getProperty("line.separator")

 

 

 

3.2BufferedReader (体系)

|—— 3.3) LineNumberReader(子类)

 

BufferedReader类常用方法

 

3.21read( ) 读取数据进缓冲区:可读取 字符型数据;数组数据;换行标记

3.22readLine()读取一个行;返回值类型String

此方法使用读取缓冲区的read方法,将读取的字符进行缓冲并判断换行标记。将标记前的缓冲数据变成字符串返回。

此方法适用情景:对行的操作,如索引行中关键字;

 

 

了解:装饰设计模式——使用情景功能扩展

 

 装修设计模式 与通过 继承实现情景功能扩展 的区别: 只为实现功能扩展而继承使得继承体系变得越来越臃肿庞杂,不够灵活。

 将功能进行单独的封装,哪个对象需要扩展功能,就在将哪个对象和功能关联。

装饰比继承灵活 ;特点:装饰类和被装饰类必须属于同一接口或者父类。

3.3LineNumberReader类常用方法

 

3.31getLineNumber() 此方法显示行号

 

 

四、IO流字节流

 

字节流与字符流相比而言,处理的数据单元不同;操作的数据文件格式不同,字符流只能操作文本文件,而字节流可以操作媒体文件。

 

字节流基类InputStream , OutputStream;

 

IO字符流常用子类:

 

InputStream (体系)

           |——FileInputStream

 

4.1FileInputStream:往一个文件中写入文字数据;如果文件不存在,则会自动创建;如果存在文件则会覆盖

4.1FileInputStream类中常用方法。

4.11)获取字节的个数available()返回int

4.12)关闭字节流close( ); 返回值为void

 

为什么用字符流不能复制一个图片格式的文件?

 

字符流再读取源数据后,又进行匹配编码表操作,其中,可能有一些字符不被识别或替换了原有的字符,导致文件内容的变动,不能完成复制操作。

字符流是处理文本对象的专业对象,不能用来操作媒体文件。

 

关于编解码:编码——看的懂的转换为看不懂的;解码——把看不懂的转换为看得懂的。

 

转换流:

 

字节流与字符流之间的转换;他们转换的关键问题就是编码表;

(字符流实质就是字节流+编码表)

 

InputStream (体系)

            |——InputStreamReader

 

InputStreamReader 类是字节流同乡字符流的桥梁,他使用 指定的charset读取字节并将其解码为字符。它使用的字符集可以由名称指定或显示给定,或者接受平台默认的字符集。

 

4.2)  InputStreamReader 常用方法

 

      4.21)  InputStreamReader( InputStream  in) 构造方法

字符流与字节流之间的转换

 

OutputStream;

|——OutputStreamWriter

 

OutputStreamWriter 类是字符流通向字节流的桥梁;他使用 指定的charset读取字节并将其编码为字符。它使用的字符集可以由名称指定或显示给定,或者接受平台默认的字符集。

 

4.3OutputStreamWriter 常用方法

 

4.31OutputStreamWriter( OutputStream out) 构造方法

 

五、流操作中的规律

 

转换流: InputStreamReader : 字节到字符的桥梁。——解码

OutputStreamWriter : 字符到字节的桥梁。——编码

 

规律: (1)明确源和目的(汇)

源 涉及的体系:InputStream Reader

汇 涉及的体系:OutputStream Writer

 

(2)明确数据是否是纯文本数据

源 是纯文本:Reader

否:InputStream

 

汇 是纯文本:Writer

否:OutputStream

 

(3)明确具体的设备

源设备:

硬盘:File

                                  键盘:System,in

     内存:数组

   网络:Socker

 

汇设备:

    硬盘:File

控制台:System.out

内存:数组

网络:Socker 

 

(4)是否需要额外对象

1.是否需要高效(缓冲区)—— buffer


六、Test 小练习

6.1

 

package com.IO;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

 

/**

 * 需求:复制一个文本文件

 * 

 * 思路:

 * 1.明确源和目的源 InputStream Reader;目的 OutputStream Writer

 * 2.是否为纯文本源:Reader 目的 :Writer

 * 3.明确具体设备源:硬盘:File目的:硬盘:File

 * 4.扩展额外功能需要 缓冲区

 * @author ASUS

 *

 */

public class CopyTextTest{

 

/**

 * @throws IOException 

 */

public static void main(String[] args) throws IOException {

 

//1.确定源和目的对象

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));

BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));

//2.判断条件,循环写入,刷新缓冲

String line;

while((line = bufr.readLine())!= null){

//读行

bufw.write(line);

//换行

bufw.newLine();

//刷新

bufw.flush();

}

//3.缓冲关流

bufr.close();

bufw.close();

}

}

6.2package com.IO;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStreamReader;

 

/**

 * 需求2:读取键盘录入信息,并写入一个文件中

 * 思路:

 * 1.明确源和目的;源——InputStream Reader 目的——OutputStream Writer

 * 2.是否是纯文本:是源——Reader目的——Writer

 * 3.明确设备 源——键盘:System.in目的——硬盘:File

 * 4.是否需要功能高效——缓冲区;转换——字节流转换为字符流 

 */

public class ReadKeyText {

 

/**

 * @param args

 * @throws IOException 

 */

public static void main(String[] args) throws IOException {

 

//创建字节输入源对象,并关联键盘

InputStreamReader isr = new InputStreamReader(System.in);

//创建目标接收字符流对象并关联目标文件

FileWriter fw = new FileWriter("c.txt");

//高效读取缓冲区

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

//高效写入缓冲区

BufferedWriter bufw = new BufferedWriter(new FileWriter("c.txt"));

//变量

int ch = 0;

//循环 判断 写入 刷新

while((ch = bufr.read())!= -1){

bufw.write((char)(ch));

bufw.flush();

}

//关闭流资源

bufw.close();

bufr.close();

}

 

}

 

 

6.3

package com.IO;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.OutputStreamWriter;

 

/**

 * 需求:将文本文件数据显示在控制台上

 * 1.明确源和目的:源——InputStream Reader   目的——OutputStream  Writer

 * 2.是否为纯文本:源——Reader 目的——Writer

 * 3.明确具体设备: 源——硬盘 File;目的——控制台

 * 4.额外功能:转换

 */

public class ReadKeyText02 {

 

/**

 * @param args

 * @throws IOException 

 */

public static void main(String[] args) throws IOException {

 

//创建读取流对象,并关联文件,缓冲区提高效率

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));

//创建输出流对象,并关联输出设备,缓冲区提高效率

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

int ch = 0;

while((ch = bufr.read())!= -1){

bufw.write((char)(ch));

bufw.flush();

}

bufw.close();

bufr.close();

}

 

}

 

6.4package com.IO;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

 

/**

 *需求:读取键盘录入数据,显示在控制台上

 *思路:

 *1.明确源和目的:源——InputStream Reader 目的——OutputStream Writer

 *2.是否为纯文本:是 源——Reader目的——Writer

 *3.明确设备:源——键盘目的——控制台

 *4.扩充功能: 缓冲转换

 */

public class ReadKey04 {

 

/**

 * @param args

 * @throws IOException 

 */

public static void main(String[] args) throws IOException {

 

//读取字节

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

//输出字符

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

String line;

while((line = bufr.readLine())!= null){

bufw.write(line);

bufw.newLine();

bufw.flush();

}

bufw.close();

bufr.close();

}

 

}


FileWriter:其实就是转换流指定了本机默认码表的体现。而且这个转换流的子类对象,可以方便操作文本文件。(操作文件的字节流+本机默认的编码表),这是按照默认编码表来操作文件的便捷类。但是如果,操作文本文件明确了编码表就不行了,需要用字节流

 

GDK码表中:一个汉字两个字节;UTF-8:一个汉字三个字节;

一般打开文件是一堆中文乱码,那么极可能是用录入时用其他码表,而用GDK来解码的文件。

如果打开文件是一堆符号,那么极可能是用GDK来录入,而用其他码表解码的。

 

转换流使用的情景:

1.源 或者 汇 的对应设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁。

2.一旦操作文本涉及到指定编码表时,必须使用转换流。


Properties集合对IO流的操作

Properties集合是Map集合的子类,可记录键值对,多用于配置文件的设置;

 

方法store()

setProperties方法()


打印流:1.PrintStream:提供打印的方法,可以为多种数据类型提供打印方法

        2.不抛IOException

 

构造函数,接收三种类型的值

1.字符串路径

2.File对象

3.字节流

 

Out.write();的特点:只写8

 

字符打印流:printWriter

 

序列流:有序的排列 一个流对象关联一个源,我有多个数据,关联多个流;

(集合容器封装多个流)

 

文件切割

1.确定切割条件(按大小;按切割个数)

2.一个源文件流;多个输出流(有几个目的文件关联几个流)

3.自定义缓冲区

关键:设置配置文件获取文件切割个数,及后缀名;键值对Properties对象,在切割时生成

 

文件合并

1.获取配置文件对象2.判断配置文件个数3.读取配置文件信息4.把切割后文件匹配配置文件信息 5.将碎片文件和流对象关联并使用集合对象存储 6.合并文件多个流合并成一个序列流

关键:通过过滤器来获取配置文件(配置文件要唯一);来确定需合并的个数和合并后源文件类型

序列化

 

操作对象的流:对象的序列化,实质:把存入硬盘的对象进行排列

对象的序列化;对象的反序列化

操作情景:

 

ObjectInputStreamObjectOutputStream

被操作的对象需要实现Serializable (标记接口);

 

RandomAccessFile

随机访问文件,自身具备读写的方法。

通过skipBytes(int x),seek(int x)来达到随机访问。

特点:

1.该对象即能读又能写

2.该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素

3.可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置

4.其实该对象就是将字节输入流和输出流进行了封装。

5.该对象的源或者目的只能是文件,通过构造函数就可以看出。

 

 

管道流

PipedInputStreamPipedOutputStream

输入输出可以直接进行连接,通过结合线程使用。

 

 

操作基本数据类型

DataInputStreamDataOutputStream

操作字节数组

ByteArrayInputStreamByteArrayOutputStream

操作字符数组

CharArrayReaderCharArrayWrite

操作字符串

StringReader 与 StringWriter

 

字符编码

字符流的出现为了方便操作字符。

更重要是的加入了编码转换。

通过子类转换流来完成。

InputStreamReader

OutputStreamWriter

在两个对象进行构造的时候可以加入字符集

 

计算机只能识别二进制数据,早期由来是电信号。

为了方便应用计算机,让它可以识别各个国家的文字。

就将各个国家的文字用数字来表示,并一一对应,形成一张表。

这就是编码表。

 

ASCII:美国标准信息交换码。

用一个字节的7位可以表示。

ISO8859-1:拉丁码表。欧洲码表

用一个字节的8位表示。

GB2312:中国的中文编码表。

GBK:中国的中文编码表升级,融合了更多的中文文字符号。

Unicode:国际标准码,融合了多种文字。

所有文字都用两个字节来表示,Java语言使用的就是unicode

UTF-8:最多用三个字节来表示一个字符。

......

 

可以将字符以指定编码格式存储。

可以对文本数据指定编码格式来解读。

指定编码表的动作由构造函数完成。

你可能感兴趣的:(Java笔记)