黑马程序员--java笔记12--IO流

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

IO 流

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

输入流和输出流相对于内存设备而言。

将外设中的数据读取到内存中:输入。

将内存的数写入到外设中:输出。

字符流与字节流的联系:(按操作数据分)

字符流的由来:字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字。再对这个文字进行操作。简单说:字节流+编码表。

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

字符流的抽象基类:Reader,Writer。

P.S.

由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。

如果要操作文字数据,建议优先考虑字符流。

而且要将数据从内存写到硬盘上,要使用字符流中的输出流:Writer。硬盘的数据基本体现是文件,希望找到一个可以操作文件的Writer:FileWriter。

P.S.

1. close方法只能用一次。

2. 流关闭以后不能,不能再调用write方法,否则会报异常错误:如果构造函数中加入true,可以实现对文件进行续写。

IO流的异常处理方式:为防止代码异常导致流无法关闭,因此在finally中对流进行关闭。

需求:读取一个文文件,将读取到的字符打印到控制台。(使用FileReader)

第一种读取方式:使用read()方法读取文本文件数据。

第二种读取方式:使用read(char[])方法读取文本文件数据

字符流缓冲区:

字符流的缓冲区:缓冲区的出现提高了对数据的读写效率。

对应类:BufferedWriter、BufferedReader

P.S.缓冲区要结合流才可以使用。

只有BufferedReader有读取一行readLine()方法

作用:在流的基础上对流的功能进行了增强。

写入换行使用BufferedWriter类中的newLine()方法。

读取一行数据使用BufferedReader类中的readLine()方法。

bufr.read():这个read方法是从缓冲区中读取字符数据,所以覆盖了父类中的read方法。

bufr.readLine():另外开辟了一个缓冲区,存储的是原缓冲区一行的数据,不包含换行符。

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

LineNumberReader

跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。

装饰设计模式

装饰和继承都能实现一样的特点:进行功能的扩展增强。

区别

首先有一个继承体系:

Writer

|--TextWriter:用于操作文本

|--MediaWriter:用于操作媒体

如果想要对操作的动作进行效率的提高,按照面向对象,可以通过继承的方式对具体的对象进行功能的扩展,那么就需要加入缓冲技术。

Writer

|--TextWriter:用于操作文本

|--BufferTextWriter:加入了缓冲技术的操作文本的对象

|--MediaWriter:用于操作媒体

|--BufferMediaWriter:加入了缓冲技术的操作媒体的对象

以上方式并不理想,如果这个体系需要再进行功能扩展,又多了更多流对象。这样就会发现只为提高功能,导致继承体系越来越臃肿,不够灵活。

Writer

|--TextWriter:用于操作文本

|--MediaWriter:用于操作媒体

|--BufferedWriter:用于提高效率

可见:装饰比继承灵活。

特点:装饰类和被装饰类都必须所属同一个接口或者父类。

字节流

基本操作与字符流类相同。但它不仅可以操作字符,还可以操作其他媒体文件。

FileOutputStream、FileInputStream的flush方法内容为空,没有任何实现,调用没有意义

流的操作规律:

1.明确源和目的

源:InputStream Reader

目的:OutputStream Writer

2.明确是否是纯文本

是:源: Reader目的:Writer

否:源:InputStream目的:OutputStream 

3.明确具体设备

源设备:

键盘:System.in硬盘:File内存:数组 网络:Socket流

目的设备:

控制台:System.out硬盘:File内存:数组 网络:Socket流

4.是否需要额外功能

是否需要加缓冲区Buffered

转换流:字符流与字节流之间的桥梁

应用:字节流中都是字符时,转成字符流操作更高效

InputStreamReader:字节流转字符流,解码(读取文件等)

OutputStreamWriter:字符流转字节流,编码(输出文件等)

P.S.

获取键盘录入时,System类的setIn(),setOut()方法可以改变默认设备

System.setIn(new FileInputStream(“1.txt”));//将1.txt作为源

应用了缓冲区及转换流的输入输出

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

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

什么情况使用转换流

1.源或目的对用的是字节流对象,操作却是文本

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

例:BufferedWriter bufw=new BufferedWriter(

new OutputStreamWriter(new FileOutputStream(“a.txt”),charseNamegpp));

File类:

用来将文件或文件夹封装成对象,以方便对其属性信息的操作

File类对象可以作为参数传递给流的构造函数

P.S.:流只能操作数据,不能操作文件

File对象常用方法:

1.获取

File

getAbsoluteFile() 返回此抽象路径名的绝对路径名形式。

String

getAbsolutePath() 返回此抽象路径名的绝对路径名字符串。

String

getName() 返回由此抽象路径名表示的文件或目录的名称。

String

getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。

File

getParentFile() 返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。

String

getPath() 将此抽象路径名转换为一个路径名字符串。

2.创建和删除

boolean

createNewFile() 当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。

boolean

delete() 删除此抽象路径名表示的文件或目录。

boolean

mkdir() 创建此抽象路径名指定的目录。

3.判断

boolean

isAbsolute() 测试此抽象路径名是否为绝对路径名。

boolean

isDirectory() 测试此抽象路径名表示的文件是否是一个目录。

boolean

isFile() 测试此抽象路径名表示的文件是否是一个标准文件。

boolean

isHidden() 测试此抽象路径名指定的文件是否是一个隐藏文件。

4.重命名

boolean

renameTo(File dest) 重新命名此抽象路径名表示的文件。

 

5.系统根目录和容量获取

long

getFreeSpace() 
返回此抽象路径名指定的分区中未分配的字节数。

long

getTotalSpace() 
返回此抽象路径名指定的分区大小。

long

getUsableSpace() 
返回此抽象路径名指定的分区上可用于此虚拟机的字节数。

String[]

list() 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。

File[]

listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。

static File[]

listRoots() 列出可用的文件系统根。

 

递归

函数自身直接或者间接的调用到了自身。

一个功能在被重复使用,并每次使用时,参与运算的结果和上一次调用有关。这时可以用递归来解决问题。

P.S.

1、递归一定明确条件,否则容易栈溢出。

2、注意一下递归的次数。

Properties集合

Map

|--Hashtable

|--Properties

特点:

1. 该集合中的键和值都是字符串类型。

2. 集合中的数据可以保存到流中,或者从流中获取。

3. 通常该集合用于操作以键值对形式存在的配置文件。

 IO包中的其他类

打印流

PrintWriter与PrintStream:可以直接操作输入流和文件。

PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。

与其他输出流不同,PrintStream永远不会抛出IOException。

PrintStream打印的所有字符都使用平台的默认字符编码转换为字节。

在需要写入字符而不是写入字节的情况下,应该使用PrintWriter类。

PrintStream:

1. 提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式

2. 它不抛IOException

PrintWriter:字符打印流

序列流

SequenceInputStream:对多个流进行合并。

使用ArrayList将各序列流添加进去(或Vector枚举,效率稍低)

Enumeration :实现 Enumeration 接口的对象,它生成一系列元素,一次生成一个。

 

练习:文件切割器(Properties集合)。文件合并器(序列流)。

操作对象流 ObjectInputStream与ObjectOutputStream

P.S.

被操作的对象需要实现Serializable,即序列化。

类通过实现java.io.Serializable接口以启用序列化功能,Serializable只是一个标记接口。

Serializable:用于给被序列化的类加入ID号,用于判断类和对象是否是同一个版本。

writeObject方法不能写入类及其所有超类型的瞬态和静态字段的值。

RandomAccessFile

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

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

特点:

1. 该对象即能读,又能写。

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

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

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

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

P.S.RandomAccessFile不是io体系中的子类。

管道流:

PipedInputStream和PipedOutputStream

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

操作基本数据类型

DataInputStream与DataOutputStream

操作字节数组

ByteArrayInputStream与ByteArrayOutputStream

P.S.关闭字节数组输出输出流无效,因为它们没有调用底层资源,所有的操作都是在内存中完成的。

编码表

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

常见的编码表

ASCII:美国标准信息交换码,用一个字节的7位可以表示。

ISO8859-1:拉丁码表。欧洲码表,用一个字节的8位表示。

GB2312:中国的中文编码表。

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

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

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

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

......

如果编码编错了,解不出来。

如果编对了,解错了,有可能有救。

如果编对了,解错了,也可能没救了。

实验:联通乱码问题。

原因在于这两个字的编码以后的二进制都符合utf-8的解码需求,直接用了utf-8解码

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值