java-io

Io流:★★★★★,用于处理设备上数据。

流:可以理解数据的流动,就是一个数据流。IO流最终要以对象来体现,对象都存在IO包中。

流也进行分类:

1:输入流(读)和输出流(写)。

2:因为处理的数据不同,分为字节流和字符流。

3:按照实现功能不同可以分为:节点流和处理流。


字节流:处理字节数据的流对象。设备上的数据无论是图片或者dvd,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。

那么为什么要有字符流呢?因为字符每个国家都不一样,所以涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,所以需要获取中文字节数据的同时+ 指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。

注意:流的操作只有两种:读和写。

流的体系因为功能不同,但是有共性内容,不断抽取,形成继承体系。该体系一共有四个基类,而且都是抽象类。

字节流:InputStream OutputStream

字符流:Reader Writer

在这四个系统中,它们的子类,都有一个共性特点:子类名后缀都是父类名,前缀名都是这个子类的功能名称


字节流:一次读入或读出是8位二进制。

字符流:一次读入或读出是16位二进制。

字节流和字符流的原理是相同的,只不过处理的单位不同而已。后缀是Stream是字节流,而后缀是ReaderWriter是字符流。

节点流:直接与数据源相连,读入或读出。

直接使用节点流,读写不方便,为了更快的读写文件,才有了处理流。

处理流(装饰流):与节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。

字节输入流:

102351836.jpg

字节输出流:

102351496.jpg

字符输入流:

102351475.jpg

字符输出流:

102351991.jpg



103355126.jpg

对文件进行操作:FileInputStream(字节输入流),FileOutputStream(字节输出流);FileReader(字符输入流),FileWriter(字符输出流)

字符流的基本实现:InputStreamReader 完成 byte 流解析为 char 流, 按照编码解析 OutputStreamWriter 提供 char 流到 byte 流, 按照编码处理


字节流(InputStream, OutputStream)

FileInputStream(字节输入流) 具体实现了在文件上读取数据。

FileOutputStream 实现了向文件中写出 byte 数据的方法。


字符流(Reader Writer)

1) 字符的处理,一次处理一个字符(unicode 编码)

2) 字符的底层仍然是基本的字节流

3) 字符流的基本实现

InputStreamReader 完成 byte 流解析为 char 流, 按照编码解析

OutputStreamWriter 提供 char 流到 byte 流, 按照编码处理

4) 字符流的过滤器

是字符读写的功能扩展, 极大的方便了文本的读写操作

BufferedReader : readLine() 一次读取一行

PrintWriter: println() 一次打印一行

5)读取一个文本文件

InputStream is = new FileInputStream("gbk.txt");

Reader in = new InputStreamReader(is);

BufferedReader reader = new BufferedReader(in);

or

BufferedReader in = new BufferedReader(new FileReader(filename));

6) 写出一个文本文件

PrintWriter out = new PrintWtirer(new FileWriter(filename));

or

PrintWriter out = new PrintWtirer(

new OutputStreamWriter(

new FileOutputStream(filename)));

7) 系统的默认编码,中文一般是 GBK

String encoding=System.getProperty("file.encoding")



对管道进行操作:PipedInputStream(字节输入流),PipedOutStream(字节输出流),PipedReader(字符输入流),PipedWriter(字符输出流)

PipedInputStream的一个实例要和PipedOutputStream的一个实例共同使用,共同完成管道的读取写入操作。主要用于线程操作。

字节/字符数组:ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter是在内存中开辟了一个字节或字符数组。

Buffered缓冲流::BufferedInputStreamBufferedOutputStreamBufferedReader,BufferedWriter,是带缓冲区的处理流,缓冲区的作用的主要目的是:避免每次和硬盘打交道,提高数据访问的效率。


转化流:InputStreamReader/OutputStreamWriter,把字节转化成字符。

数据流:DataInputStreamDataOutputStream

因为平时若是我们输出一个8个字节的long类型或4个字节的float类型,那怎么办呢?可以一个字节一个字节输出,也可以把转换成字符串输出,但是这样转换费时间,若是直接输出该多好啊,因此这个数据流就解决了我们输出数据类型的困难。数据流可以直接输出float类型或long类型,提高了数据读写的效率。

是对”流“功能的扩展,可以更方便的读取 int、long、

字符等类型数据。

DataOutputStream 对基本的输出流功能扩展, 提供了基本数据类型的输出方法, 也就是基本类型

是序列化方法:

writeInt()

writeDouble()

writeUTF()

DataInputStream 是对基本输入流(InputStream)功能的扩展,它提供基本类型的输入方法, 就

是基本类型的反序列化。

DataInputStream 是过滤器,只是功能扩展,丌能直接读取文件。

DataInputStream 提供的方法有

readInt()

readDouble()



打印流:printStreamprintWriter,一般是打印到控制台,可以进行控制打印的地方。

对象流:ObjectInputStreamObjectOutputStream,把封装的对象直接输出,而不是一个个在转换成字符串再输出。

序列化流:SequenceInputStream

有些情况下,当我们需要从多个输入流中向程序读入数据。此时,可以使用合并流,将多个输入流合并成一个SequenceInputStream流对象。

SequenceInputStream会将与之相连接的流集组合成一个输入流并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末 尾为止。 合并流的作用是将多个源合并合一个源。


对象序列化:把对象直接转换成二进制,写入介质中。

使用对象流需要实现Serializable接口,否则会报错。而若用transient关键字修饰成员变量,不写入该成员变量,若是引用类型的成员变量为null,值类型的成员变量为0.


对象的序列化

对象序列化,就是将 Object 转换为 byte 序列,反�Y叫对象的反序列化。

1) 序列化流(ObjectOutputStream), 是过滤流

ObjectOutputStream writeObject(Object) 序列化对象

ObjectInputStream readObject() 对象的反序列化

2) 序列化接口(Serializable)

对象必须实现“序列化接口”才能�行序列化,否则将出现丌能序列化的异常!

Serializable 是一个空的接口,没有任何方法,仅作为序列化的一个标识

3) JavaBean 规范规定,Java 类必须实现 Serializable 接口

Java API 中的类大多是符合 Java Bean 规范的, 基本都实现了 Serializable

4) 对象的序列化和反序列化可以变相实现对象的深层复制

File类

File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。

RandomAccessFile类

RandomAccessFile 类是 Java 提供的功能丰富的文件内容访问类,它提供了众多方法来访问文件

内容,既可以读取文件内容,也可以向文件输出数据,RandomAccessFile 支持“随机访问”方式,可

以访问文件的任意位置。

该对象并不是流体系中的一员,其封装了字节流,同时还封装了一个缓冲区(字符数组),通过内部的指针来操作字符数组中的数据。 该对象特点:

  1. 该对象只能操作文件,所以构造函数接收两种类型的参数:a.字符串文件路径;b.File对象。

  2. 该对象既可以对文件进行读操作,也能进行写操作,在进行对象实例化时可指定操作模式(r,rw)

注意:该对象在实例化时,如果要操作的文件不存在,会自动创建;如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。 可以用于多线程下载或多个线程同时写数据到文件。






字节流:

InputStream是表示字节输入流的所有类的超类。

|---FileInputStream从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader

|---FilterInputStream包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。

|---BufferedInputStream该类实现缓冲的输入流。

|---Stream

|---ObjectInputStream

|---PipedInputStream

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

OutputStream此抽象类是表示输出字节流的所有类的超类。

|---FileOutputStream文件输出流是用于将数据写入FileFileDescriptor的输出流。

|---FilterOutputStream此类是过滤输出流的所有类的超类。

|---BufferedOutputStream该类实现缓冲的输出流。

|---PrintStream

|---DataOutputStream

|---ObjectOutputStream

|---PipedOutputStream



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

字符流:

Reader用于读取字符流的抽象类。子类必须实现的方法只有 read(char[],int, int) close()

|---BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

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

|---InputStreamReader是字节流通向字符流的桥梁:它使用指定的charset读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

|---FileReader用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream上构造一个 InputStreamReader

|---CharArrayReader

|---StringReader

Writer写入字符流的抽象类。子类必须实现的方法仅有 write(char[],int, int)flush() close()

|---BufferedWriter将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

|---OutputStreamWriter是字符流通向字节流的桥梁:可使用指定的charset将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

|---FileWriter用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在FileOutputStream 上构造一个 OutputStreamWriter

|---PrintWriter

|---CharArrayWriter

|---StringWriter

IO包中扩展功能的流对象:基本都是装饰设计模式。

Java.io.outputstream.PrintStream打印流

1:提供了更多的功能,比如打印方法。可以直接打印任意类型的数据。

2:它有一个自动刷新机制,创建该对象,指定参数,对于指定方法可以自动刷新。

3:它使用的本机默认的字符编码.

4:该流的print方法不抛出IOException

PrintStream可以操作目的:1File对象。2:字符串路径。3:字节输出流。

当目的是一个字节输出流时,如果使用的println方法,可以在printStream对象上加入一个true参数。这样对于println方法可以进行自动的刷新,而不是等待缓冲区满了再刷新。最终print方法都将具体的数据转成字符串,而且都对IO异常进行了内部处理。

既然操作的数据都转成了字符串,那么使用PrintWriter更好一些。因为PrintWrite是字符流的子类,可以直接操作字符数据,同时也可以指定具体的编码。

PrintWriter具备了PrintStream的特点同时,还有自身特点:

该对象的目的地有四个:1File对象。2:字符串路径。3:字节输出流。4:字符输出流。

/读取键盘录入将数据转成大写显示在控制台.

BufferedReader bufr = newBufferedReader(new InputStreamReader(System.in));//源:键盘输入

//目的:把数据写到文件中,还想自动刷新。

PrintWriter out= new PrintWriter(newFileWriter("out.txt"),true);//设置true后自动刷新

String line = null;

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

if("over".equals(line))

break;

out.println(line.toUpperCase());//转大写输出

}

//注意:System.inSystem.out这两个标准的输入输出流,在jvm启动时已经存在了。随时可以使用。当jvm结束了,这两个流就结束了。但是,当使用了显示的close方法关闭时,这两个流在提前结束了。

out.close();

bufr.close();



缓冲区是提高效率用的,给谁提高呢?

BufferedWriter是给字符输出流提高效率用的,那就意味着,缓冲区对象建立时,必须要先有流对象。明确要提高具体的流对象的效率。

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

BufferedWriter bufw = new BufferedWriter(fw);//让缓冲区和指定流相关联。

for(int x=0; x<4; x++){

bufw.write(x+"abc");

bufw.newLine(); //写入一个换行符,这个换行符可以依据平台的不同写入不同的换行符。

bufw.flush();//对缓冲区进行刷新,可以让数据到目的地中。

}

bufw.close();//关闭缓冲区,其实就是在关闭具体的流。

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

BufferedReader

FileReader fr = new FileReader("bufdemo.txt");

BufferedReader bufr = newBufferedReader(fr);

String line = null;

while((line=bufr.readLine())!=null){//readLine方法返回的时候是不带换行符的。

System.out.println(line);

}

bufr.close();


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

//记住,只要一读取键盘录入,就用这句话。

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

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));//输出到控制台

String line = null;

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

if("over".equals(line))

break;

bufw.write(line.toUpperCase());//将输入的字符转成大写字符输出

bufw.newLine();

bufw.flush();

}

bufw.close();

bufr.close();


FileReader使用Reader体系,读取一个文本文件中的数据。返回 -1 ,标志读到结尾。

读取数据的第二种方式:第二种方式较为高效,自定义缓冲区。

FileReader fr =new FileReader("demo.txt"); //创建读取流对象和指定文件关联。

//因为要使用read(char[])方法,将读取到字符存入数组。所以要创建一个字符数组,一般数组的长度都是1024的整数倍。

char[] buf = new char[1024];

int len = 0;

while(( len=fr.read(buf)) !=-1) {

System.out.println(newString(buf,0,len));

}

流的操作规律:

1,明确源和目的。

数据源:就是需要读取,可以使用两个体系:InputStreamReader

数据汇:就是需要写入,可以使用两个体系:OutputStreamWriter

2,操作的数据是否是纯文本数据?

如果是:数据源:Reader

数据汇:Writer

如果不是:数据源:InputStream

数据汇:OutputStream

3,虽然确定了一个体系,但是该体系中有太多的对象,到底用哪个呢?

明确操作的数据设备。

数据源对应的设备:硬盘(File),内存(数组),键盘(System.in)

数据汇对应的设备:硬盘(File),内存(数组),控制台(System.out)

4,需要在基本操作上附加其他功能吗?比如缓冲。

如果需要就进行装饰。

转换流特有功能:转换流可以将字节转成字符,原因在于,将获取到的字节通过查编码表获取到指定对应字符。

转换流的最强功能就是基于字节流 + 编码表。没有转换,没有字符流。

如果仅仅使用平台默认码表,就使用FileReaderfr = new FileReader("a.txt"); //因为简化。

凡是操作设备上的文本数据,涉及编码转换,必须使用转换流。


File类:将文件系统中的文件和文件夹封装成了对象。提供了更多的属性和行为可以对这些文件和文件夹进行操作。这些是流对象办不到的,因为流只操作数据。

boolean createNewFile():在指定目录下创建文件,如果该文件已存在,则不创建。而对操作文件的输出流而言,输出流对象已建立,就会创建文件,如果文件已存在,会覆盖。除非续写。


Java.util.Properties一个可以将键值进行持久化存储的对象。Map--Hashtable的子类。

Map

|--Hashtable

|--Properties:用于属性配置文件,键和值都是字符串类型。

特点:1:可以持久化存储数据。2:键值都是字符串。3:一般用于配置文件。


SequenceInputStream:序列流,作用就是将多个读取流合并成一个读取流。实现数据合并

。表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

这样做,可以更方便的操作多个读取流,其实这个序列流内部会有一个有序的集合容器,用于存储多个读取流对象。


RandomAccessFile:

特点:

1:该对象即可读取,又可写入。

2:该对象中的定义了一个大型的byte数组,通过定义指针来操作这个数组。

3:可以通过该对象的getFilePointer()获取指针的位置,通过seek()方法设置指针的位置。

4:该对象操作的源和目的必须是文件。

5:其实该对象内部封装了字节读取流和字节写入流。

注意:实现随机访问,最好是数据有规律。

管道流:管道读取流和管道写入流可以像管道一样对接上,管道读取流就可以读取管道写入流写入的数据

注意:需要加入多线程技术,因为单线程,先执行read,会发生死锁,因为read方法是阻塞式的,没有数据的read方法会让线程等待。

public static voidmain(String[] args) throws IOException{

PipedInputStream pipin = new PipedInputStream();

PipedOutputStream pipout = new PipedOutputStream();

pipin.connect(pipout);

new Thread(new Input(pipin)).start();

new Thread(new Output(pipout)).start();

}

对象的序列化:目的:将一个具体的对象进行持久化,写入到硬盘上。

注意:静态数据不能被序列化,因为静态数据不在堆内存中,是存储在静态方法区中。


如何将非静态的数据不进行序列化?用transient 关键字修饰此变量即可。

Serializable用于启动对象的序列化功能,可以强制让指定类具备序列化功能,该接口中没有成员,这是一个标记接口。这个标记接口用于给序列化类提供UID。这个uid是依据类中的成员的数字签名进行运行获取的。如果不需要自动获取一个uid,可以在类中,手动指定一个名称为serialVersionUID id号。依据编译器的不同,或者对信息的高度敏感性。最好每一个序列化的类都进行手动显示的UID的指定。

DataOutputStreamDataInputStream专门用于操作基本数据类型数据的对象。

DataOutputStream dos = newDataOutputStream(new FileOutputStream("data.txt"));

dos.writeInt(256);

dos.close();


DataInputStream dis = new DataInputStream(newFileInputStream("data.txt"));

int num = dis.readInt();

System.out.println(num);

dis.close();

ByteArrayInputStream:源:内存

ByteArrayOutputStream:目的:内存。

这两个流对象不涉及底层资源调用,操作的都是内存中数组,所以不需要关闭。

直接操作字节数组就可以了,为什么还要把数组封装到流对象中呢?因为数组本身没有方法,只有一个length属性。为了便于数组的操作,将数组进行封装,对外提供方法操作数组中的元素。

对于数组元素操作无非两种操作:设置(写)和获取(读),而这两操作正好对应流的读写操作。这两个对象就是使用了流的读写思想来操作数组。

//创建源:

ByteArrayInputStream bis = newByteArrayInputStream("abcdef".getBytes());

//创建目的:

ByteArrayOutputStream bos = new ByteArrayOutputStream();

int ch = 0;

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

bos.write(ch);

}

System.out.println(bos.toString());



你可能感兴趣的:(二进制,中文,图片,计算机,数据流)