首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

黑马软件工程师-面向对象:IO

2013-02-24 
黑马程序员-面向对象:IO ------- android培训、java培训、期待与您交流! ----------java.io 的描述?通过数据

黑马程序员-面向对象:IO
 ------- android培训、java培训、期待与您交流! ----------

java.io 的描述

?

通过数据流、序列化和文件系统提供系统输入和输出。

? ? ? ? (1)用来处理设备(硬盘,控制台,内存)间的数据。

(2)java中对数据的操作都是通过流的方式。

(3)java用于操作流的类都在io包中。

(4)按照流操作的数据的类型不同:分为字节流和字符流。字符流是为了方便中文的操作而来的。

(5)按照流的流向不同分为:输入流,输出流

?

?

?

?

流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。

?

?

?

Java流输入输出原理

?

Java把这些不同来源和目标的数据都统一抽象为数据流。Java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象。

在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流。

?

?

Java流的分类

按流向分:

输入流: 程序可以从中读取数据的流。

输出流: 程序能向其中写入数据的流。

按数据传输单位分:

字节流: 以字节为单位传输数据的流

字符流: 以字符为单位传输数据的流

按功能分:

节点流: 用于直接操作目标设备的流

过滤流: 是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。

?

?

java.io常用类

JDK所提供的所有流类位于java.io包中,都分别继承自以下四种抽象流类。

InputStream:继承自InputStream的流都是用于向程序中输入数据的,且数据单位都是字节(8位)。

OutputSteam:继承自OutputStream的流都是程序用于向外输出数据的,且数据单位都是字节(8位)。

(1)字节流

输出字节流:OutputStream:字节写入流抽象类

|--->FileOutputStream:

字节写入流

|--->BufferedOutputStream:

字节写入流缓冲区

|--->PrintStream:

打印流

输入字节流:InputStream:字节读取流抽象类

|--->FileInputStream:

字节读取流

|--->BufferedInputStream:

字节读取流缓冲区

(2)字符流

输出字符流:Writer:字符写入流的抽象

|--->FileWriter:

字符写入流

|--->BufferedWriter:

字符写入流缓冲区

|--->OutputStreamWriter:

字符通向字节的转换流(涉及键盘录入时用)

|--->OutputStreamWriter:

打印流,可处理各种类型的数据

输入字符流:Reader: 字符读取流的抽象类

|--->FileReader:

字符读取流

|--->LineNumberReader:

跟踪行号的缓冲字符读取流

|--->BufferedReader:

字符读取流缓冲区

|--->InputStreamReader:

字节通向字符的转换流(涉及键盘录入时用)

?

?

Reader:继承自Reader的流都是用于向程序中输入数据的,且数据单位都是字符(16位)。

Writer:继承自Writer的流都是程序用于向外输出数据的,且数据单位都是字符(16位)。

?

字符写入流:Writer:

abstract ?void close() 关闭此流,但要先刷新它。

abstract ?void flush() 刷新该流的缓冲。

void write(int c) 写入单个字符。

void write(char[] cbuf) 写入字符数组。 ? ? ? ? ?

abstract ?void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。?

void write(String str) 写入字符串。?

void write(String str, int off, int len) 写入字符串的某一部分。?

字符读取流:Reader:

abstract ?void close() 关闭该流并释放与之关联的所有资源。

int read() 读取单个字符。

int read(char[] cbuf) ?将字符读入数组

abstract ?int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。

long skip(long n) ?跳过字符。?

?

?

?

IO流常用字节流基类的子类:

**写入流:

(1)FileOutputStream:

**构造方法:

FileOutputStream(String name)?

创建一个向具有指定名称的文件中写入数据的输出文件流。

FileOutputStream(String name, boolean append)?

创建一个向具有指定 name 的文件中写入数据的输出文件流。

FileOutputStream(File file)?

创建一个向指定 File 对象表示的文件中写入数据的文件输出流。?

FileOutputStream(File file, boolean append)?

创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

**方法摘要:

public void flush()

void close() 关闭此文件输出流并释放与此流有关的所有系统资源。

void write(int b) 将指定字节写入此文件输出流。

void write(byte[] b, int off, int len)?

将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。?

void write(int b) 将指定字节写入此文件输出流。

(2)BufferedOutputStream:

**构造方法:

BufferedOutputStream(OutputStream out)?

创建一个新的缓冲输出流,以将数据写入指定的底层输出流。?

BufferedOutputStream(OutputStream out, int size)?

创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。?

**方法摘要:

void flush() 刷新此缓冲的输出流。 ? ? ? ? ?

void write(byte[] b, int off, int len)?

将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流。?

void write(int b) 将指定的字节写入此缓冲的输出流。

(3)PrintStream:打印流,可将各种类型的数据原样打印,有自动刷新功能

**构造方法:

PrintStream(String fileName)?

创建具有指定文件名称且不带自动行刷新的新打印流。

PrintStream(File file)?

创建具有指定文件且不带自动行刷新的新打印流。

PrintStream(OutputStream out)?

创建新的打印流。

PrintStream(OutputStream out, boolean autoFlush) (当autoFlush为true时具有自动刷新功能)

创建新的打印流。

**方法摘要:

PrintStream append(char c)?

将指定字符添加到此输出流。

void close()?

关闭流。?

void flush()?

刷新该流的缓冲。

void print(各种类型的数据:)?

打印各种类型的数据?

void println(各种类型的数据:):自动换行

打印各种类型的数据?

void write(byte[] buf, int off, int len)?

将 len 字节从指定的初始偏移量为 off 的 byte 数组写入此流。?

void write(int b)?

将指定的字节写入此流。?

?

**读取流:

(1)FileInputStream:

**构造方法:

FileInputStream(String name)?

通过打开一个到实际文件的连接来创建一个 FileInputStream,

该文件通过文件系统中的路径名 name 指定。

FileInputStream(File file)?

通过打开一个到实际文件的连接来创建一个 FileInputStream,

该文件通过文件系统中的 File 对象 file 指定。

**方法摘要:

int available() (字节读取流特有方法!!!)

返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。

int read()?

从此输入流中读取一个数据字节。?

int read(byte[] b)?

从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。?

int read(byte[] b, int off, int len)?

从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。?

long skip(long n)?

从输入流中跳过并丢弃 n 个字节的数据。?

(2)BufferedInputStream:

**构造方法:

BufferedInputStream(InputStream in)?

创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。?

BufferedInputStream(InputStream in, int size)?

创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。?

**方法摘要:

int available() (字节读取流特有方法!!!)

返回可以从此输入流读取(或跳过)、且不受此输入流接下来的方法调用阻塞的估计字节数。?

int read()?

参见 InputStream 的 read 方法的常规协定。?

int read(byte[] b, int off, int len)?

从此字节输入流中给定偏移量处开始将各字节读取到指定的 byte 数组中。?

long skip(long n)?

参见 InputStream 的 skip 方法的常规协定。

?

?

?

IO流转换流的字符编码

(1)字符流的出现为了方便操作字符,更重要的是加入了编码转换

(2)通过子类转换流来完成

InputStreamReander

OutputStreamWriter

(3)在两个子类对象进行构造的时候可以加入编码表

(4)编码表:

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

(5)常见的编码表:

**ASCII:美国标准信息交换码,用一个字节的七位表示

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

**GB2312:中文编码表,用两个字节表示

**GBK:中文编码表升级,融合录入更多的中文字符,用两个字节表示,为避免和老美重复

? ? ? 两字节的最高位都是1,即汉字都是用负数表示

**Unicode:国际标准码,融合了多种文字,所有文字都用两个字节表示

**UTF-8:用一个字节到三个字节表示。

注:Unicode能识别中文,UTF-8也能识别中文,但两种编码表示一个汉字所用的字节数不同

Unicode用两个字节,UTF-8用三个字节,故涉及到编码转换。

(6)在流中涉及编码表的转换只有转换流:

InputStreamReander

OutputStreamWriter

(7)代码示例:

public static void write() throws IOException

{

OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"GBK");

osw1.write("你好");

osw1.close();

?

OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("utf-8.txt"),"UTF-8");

osw2.write("你好");

osw2.close();

}

public static void read() throws IOException

{

InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk.txt"),"GBK");

byte[] buf = new byte[1024];

int len = isr.read(buf);

sop(new String(buf,0,len));

}

(8)编码解码

编码:字符串变成字节数组:String-->getBytes()-->byte[]()

解码:字节数组变成字符串:byte[]-->new String(byte[],0,len)-->String

(9)代码示例:

public static void main(String[] args)

{

//编码解码1:默认编码

String str1 = "你好";

byte[] buf1 = str1.getBytes();//默认解码:Unicode,四个字节

?

//编码解码2:指定编码

String str2 = "你好";

byte[] buf2 = str2.getBytes("UTF-8");//指定解码:UTF-8,六个字节

?

?

//编码解码3:编码正确解码错误

String str3 = "你好";

byte[] buf3 = str3.getBytes("GBK");//指定编码:GBK,四个字节

String str3 = new String(buf3,"ISO8859-1");//错误解码

?

//编码解码4:错误编码正确解码

String str4 = "你好";

byte[] buf4 = str4.getBytes("ISO8859-1");//错误编码

String str4 = new String(buf4,"GBK");//正确解码,读不出来

?

//编码解码5:编码对了,但是解码错误了,怎么办呢?

//此时可以将错误的解码再错编回去,载用正确编码解码

String str5 = "你好";

byte[] buf5 = str5.getBytes("GBK");//正确编码

String str6 = new String(buf5,"ISO8859-1");//错误解码,读不出来

byte[] buf6 = str6.getBytes("ISO8859-1");//再错误编码

String str7 = new String(buf6,"GBK");//再正确解码,这样就可以读出来了

热点排行