黑马程序员——java---IO

来源:互联网 发布:unity3d场景资源包 编辑:程序博客网 时间:2024/05/01 19:26
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

 

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

流按操作数据分两种:字节流、字符流

流按流向分为:输入流、输出流

字符流融合了编码表,用于处理文字。字节流用于处理图片、文字。通用的是字节流。

程序从输入流中读取数据,向输出流中写入数据。

在数据类型上,read()方法在作提升,write()方法在做强转,以保证原数据的不变化。

IO流常用基类:

字节流的抽象基类:InputStreamOutputStream

字符流的抽象基类:ReaderWriter

字符流:FileWriterFileReader  (缓冲区:BufferedWriterBufferedReader

字节流:FileOutputStreamFileInputStream

(缓冲区:BufferedOutputStreamBufferedInputStream)

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

egInputStream的子类FileInputStream

Reader的子类FileReader

转换流:

InputStreamReader : 字节转字符

OutputStreamWriter:字符转字节

使用:

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

流对象的基本规律:

通过三个明确来完成。确定使用哪个体系、使用哪个对象。

1) 明确源和目的

 

源:输入流àInputStreamReader

目的:输出流àOutputStreamWriter

2) 明确操作的数据是否为纯文本

 

纯文本:字符流

非纯文本:字节流

 

3) 当体系明确后,在明确要使用的那个具体对象

通过设备来进行区分:126 / 196 

 

源设备:内存(简写:ArrayStream)、硬盘(简写:FileStream)、键盘(System.in)

目的设备:内存(简写:ArrayStream)、硬盘(简写:FileStream)、控制台(System.out)

字节流和字符流

 

二者仅仅是操作单位不一样。

InputStreamReader所有输入流的基类,他们都是抽象类,本身不能创建实例,但是他们是所有输入流的模板。

一般来说处理字符或字符串时使用字符流,处理字节或二进制对象时应使用字节流;

备注:字符流必须关闭资源,因为它中间有缓冲区!而字节流不需要!但是一般都会(最后)关闭资源!

 

字节流

字节流主要是操作byte(字节)的类型数据:

字节输出流:OutputStream

字节输入流:InputStream

 

字符流

Java中的字符是Unicode编码,是双字节的,1个字符 等于 2个字节;

使用字节来处理字符文本就不太方便了,此时可以考虑使用字符流;

字符流主要是操作char的类型数据:

字符输出流:Writer

字符输入流:Reader

 

 

字节流和字符流的区别

 

字节流和字符流在使用上的代码结构都是非常类似的,但是其内部本身也是有区别的,因为在进行字符流操作的时候会使用到缓冲区(内存中),而字节流操作的时候是不会使用到缓冲区的。

在输出的时候,OutputStream类即使最后没有关闭内容也可以输出。但是如果是Writer的话,则如果不关闭,最后一条内容是无法输出的,因为所有的内容都是保存在了缓冲区之中,每当调用了close()方法就意味着清空缓冲区了。那么可以证明字符流确实使用了缓冲区:

字节流:程序 → 文件

字符流:程序 → 缓冲区(内存中) → 文件

 

如果现在字符流即使不关闭也可以完成输出的话,则必须强制性清空缓冲区:

方法:public void flush() throws IOException

 

我的总结:

两者相比,肯定使用字节流更加的方便,而且在程序中像图片、MP3等都是采用字节的方式的保存,那么肯定字节流会比字符流使用的更广泛。

但是需要说明的是,但是如果要是想操作中文的话,字符流肯定是最好使的。(字节流的话可能会出现乱码(一个汉字分成了两份)!)

字符流示例:

文件拷贝。

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class DeMo3 {/** * 文件拷贝。 * @throws IOException  */public static void main(String[] args) throws IOException {// TODO Auto-generated method stub//定义源。FileReader fr = new FileReader("f:\\info.txt");//定义目的。FileWriter fw = new FileWriter("f:\\1.txt");//byte[] buf = new byte[1024];int line = 0;//遍历源中文件吧源写到目的中去。while((line = fr.read())!=-1){fw.write(line);}fr.close();fw.close();System.out.println("拷贝成功!");}}



 

字节流示例:

图片拷贝。

import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class DeMo4 {/** * 图片拷贝。 *  * @throws IOException */public static void main(String[] args) throws IOException {// TODO Auto-generated method stub//定义源。InputStream ins = new FileInputStream("f:\\1.png");//定义目的。OutputStream ous = new FileOutputStream("f:\\2.png");byte[] buf = new byte[1024];//先存储到一个数组中为了提高效率。int len = 0;while ((len = ins.read(buf)) != -1) {ous.write(buf, 0, len);}ins.close();ous.close();}}



 

字节→字符转换流

 

OutputStreamWriter:把字节输出流对象转成字符输出流对象

InputStreamReader:把字节输入流对象转成字符输入流对象

FileWriterFileReader分别是OutputStreamWriterInputStreamReader的直接子类,而不是WriterReader的直接子类,区别于FileInputStream InputStream

 

我的总结:无论使用字节流还是字符流实际上在内存中最终都是通过字节的形式来操作流的。

所以并没有字符流转换字节流。

 

 

Eg

//构建一个字节输出流对象

OutputStream out = new FileOutputStream("");

//把字节输出流转成字符输出流

Writer w  = new OutputStreamWriter(out);

//然后的操作和使用字符输出流的操作一样

---------------------------------------------

//构建一个字节输入流对象

InputStream is = new FileInputStream("");

//把字节输入流转成字符输入流

Reader r = new InputStreamReader(is);

//然后的操作和使用字符输入流的操作一样

内存操作流

 

操作内存流的时候(从读取出来,注意一定要把真正的数据toByteArray或者toCharArray将数据读出来

之前的文件操作流是以文件的输入输出为主的,当输出的位置变成了内存,那么就称为内存操作流。此时要使用内存流完成内存的输入和输出操作。

如果程序运行过程中要产生一些临时文件,可采用虚拟文件方式实现;

直接操作磁盘的文件很耗性能,使用内存流可以提升性能;jdk里提供了内存流可实现类似于内存虚拟文件的功能。

ByteArrayInputStream:将内容写到内存中     CharArrayReader

ByteArrayOutputStream:将内存中的数据写出      CharArrayWriter

ByteArrayInputStream:构造方法:

public ByteArrayInputStream(byte[] buf):全部内容

public ByteArrayInputStream(byte[] buf,int offset,int length):指定范围的内容

ByteArrayOutputStream:

public ByteArrayOutputStream()

 

 

我的总结:内存流操作:先把数据写到内存中去,然后再从内存中读取出来!提升了性能!

示例

此处用的是内存字节流(写入加输出)

import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;public class DeMo5 {/** * @param args * @throws IOException  */public static void main(String[] args) throws IOException {// TODO Auto-generated method stubString str = "黑马程序员我来的!";ByteArrayOutputStream bos = new ByteArrayOutputStream();bos.write(str.getBytes());byte[] buf = bos.toByteArray();ByteArrayInputStream bis = new ByteArrayInputStream(buf);byte[] b = new byte[32];int len = 0;while((len = bis.read(b))!=-1){System.out.println(new String(b,0,len));}}}

打印流

(只有两个,PrintWriterPrintStream

思考:如果现在要想完成一个字符串或者是boolean型或者是字符型的数据输出使用OutputStream是否方便?

肯定是不方便的,因为OutputStream中只能操作字节数据,所以其他的数据类型很难操作,那么在JavaIO包中为了解决这种问题增加了两种类:PrintStreamPrintWriter

打印流有非常好的打印功能,可以打印任何的数据类型。如,整数,小数,字符串等。

观察PrintStream类的构造:

public PrintStream(File file) throws FileNotFoundException

public PrintStream(OutputStream out)

虽然PrintStreamOutputStream的子类,但是在实例化的时候依然需要一个OutputStream的对象。

 

PrintWriterPrintStream都属于输出流,分别针对字符和字节。

PrintWriterPrintStream重载的print()println()用于多种数据类型的输出。

print()里的参数不能为空;println()可以

PrintWriterPrintStream输出操作不抛出异常

PrintStream调用println方法有自动flush功能;

标准流

标准输入流:  System.in   默认表示的是键盘录入

标准输出流:  System.out  默认表示的是屏幕输出

缓冲流

 

缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写效率,同时增加了一些新的方法。

四种缓冲流

BufferedReader(Reader in)

BufferedReader(Reader in,int sz)//sz表示自定义缓冲区大小

BufferedWriter(Writer out)

BufferedWriter(Writer out,int sz)

BufferedInputStream(InputStream in)

BufferedInputStream(InputStream in,int sz)

BufferedOutputStream(OutputStream out)

BufferedOutputStream(OutputStream out,int sz)

 

BufferedReader提供readLine方法用于读取一行字符串。

BufferedWriter提供了newLine方法用于写入一个行分隔符。等价于//.writer("\r\n");

对于输出的缓冲流,写出的数据会先在内存中缓冲,使用flush方法将会使内存中的数据立刻写出。

我的总结:在后续的学习中,缓冲流用到的会很多,因为效率高!

用缓冲区拷贝一个文件:

示例

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class DeMo6 {/** * 用缓冲区拷贝一个文件: * @throws IOException  */public static void main(String[] args) throws IOException {// TODO Auto-generated method stub//定义源。因为是纯文本文件所以使用reader。为了提高效率加入缓冲区。BufferedReader bufr = new BufferedReader(new FileReader("f:\\java总结大全.txt"));//定义目的。BufferedWriter bufw = new BufferedWriter(new FileWriter("f:\\javadaquan.txt"));//byte[] buf = new byte[1024];String line =null;//如果源中内容不为空就把源中数据写到目的中去。while((line = bufr.readLine())!=null){bufw.write(line);bufw.newLine();//字符中特有的换行功能。bufw.flush();//刷新}//关流防止内存溢出。bufr.close();bufw.close();}}



 

用缓冲区拷贝一个图片:

示例

import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import javax.imageio.stream.FileImageInputStream;public class DeMo7 {/** * 用缓冲区拷贝一个图片: * @throws IOException  */public static void main(String[] args) throws IOException {// TODO Auto-generated method stub//定义源,因为不是文本内容所以使用字节流,加入高效。BufferedInputStream bufi = new BufferedInputStream(new FileInputStream("f:\\1.png"));//定义目的。BufferedOutputStream bufo = new BufferedOutputStream(new FileOutputStream("f:\\2.png"));byte[] buf = new byte[1024];//定义一个数组来装内容减少了cup来回的折腾次数。int len = 0;while((len = bufi.read(buf))!=-1){bufo.write(buf,0,len);bufo.flush();}//关流防止内存溢出。bufi.close();bufo.close();}}

合并流(SequenceInputStream)

 

需要两个源文件,还有输出的目标文件

 

SequenceInputStream

将两个文件的内容合并成一个文件

该类提供的方法:

SequenceInputStream(InputStream s1, InputStream s2) :根据两个字节输入流对象来创建合并流对象。

示例:

将三个文件组成一个文件。

import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.Enumeration;import java.util.Vector;import javax.sound.midi.Sequence;public class DeMo8 {/** *将三个文件组成一个文件。 * @throws IOException  */public static void main(String[] args) throws IOException {// TODO Auto-generated method stub//合并文件用到了合并流。用于合并的集合就只有enumeration只有vector中有所以用vector。Vector<FileInputStream> v = new Vector<FileInputStream>();//把碎片文添加到vector中去。v.add(new FileInputStream("d:\\1.txt"));v.add(new FileInputStream("d:\\2.txt"));v.add(new FileInputStream("d:\\3.txt"));//迭代集合。类似于迭代器。Enumeration< FileInputStream> em = v.elements();SequenceInputStream sis = new SequenceInputStream(em);FileOutputStream fos = new FileOutputStream("d:\\4.txt");//把迭代完的文件存到一个文件中。byte[] buf = new byte[1024];int len;while((len = sis.read(buf))!=-1){fos.write(buf,0,len);}sis.close();fos.close();}}

0 0
原创粉丝点击