`
xiaoer_1982
  • 浏览: 1882196 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

《Java面向对象编程》学习笔记16—Java I/O系统

阅读更多

1.基本概念和基本情况:

a.流:一组有序的数据序列。

b.字节流:数据流中最小的数据单元是字节。

c.字符流:数据流中最小的数据单元是字符。

d.java.io.InputStream和java.io.OutputStream分别表示字节输入流和字节输出流。都是抽象类,不能被实例化。所有的字节操作流都是这两个类的直接或间接子类。read()读取的是一个8位字节,write()写入的是一个8位字节。

e.java.io.Reader和java.io.Writer分别表示字符输入流和字符输出流。都是抽象类,不能被实例化。所有的字符操作流都是这两个类的直接或间接子类。

2.字节输入流:

image_thumb2

1)字节数组输入流:ByteArrayInputStream类

从内存中的字节数组中读取数据,其数据源是一个字节数组。该类本身采用了适配器设计模式,将字节数组类型转化为输入流,完成对数组的读操作,读到的每一个字节类型的元素都会自动转换为int。

使用如下:

import java.io.ByteArrayInputStream;
import java.io.IOException;

public class Test {
public static void main(String[] args){
byte buff[]= new byte[]{2,15,67,-1,-9,9};
ByteArrayInputStream inputStream = new ByteArrayInputStream(buff,1,4);
int data = inputStream.read();
while (data!=-1) {
System.out.println(data + " ");
data = inputStream.read();
}
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

这里的值会在前边补0而导致变化,但是请注意在byte类型赋值给int类型时,取值不会变。

2)文件输入流:FileInputStream类

从文件中读取数据流。注意系统的默认编码格式。

3)字符串输入流:StringBufferInputStream类。(已被StringReader类代替而废弃)

从一个字符串中读取。本身采用了适配器设计模式。

4)管道输入流PipedInputStream类

通常用于线程间通信,A执行管道输入流的read方法,暂时没有数据的时候这个线程就会被阻塞,只有当线程B向管道输入流写了新的数据后A才会执行。

5)顺序输入流:SequenceInputStream类

用于将几个输入流串联在一起,合并为一个输入流。当类通过这个类来读取数据时,它会依次(以输入流加入为序) 从所有被串联的输入流中读取数据。关闭输入流不需要先依次关闭各个子输入流。

6)过滤输入流:FilterInputStream类

这是装饰器,它本身继承了InputStream类,还可以用来修饰其他的输入流类。其构造方法为protected访问级别,因此外部程序不能创建这个类本身的实例。

关于装饰器模式,在这摘录一个网友(江苏 无锡 缪小东 )的文字,我把一些调侃的话删掉了,留其本质内容:

“三明治”的例子:三明治必不可少的是两块面包片,然后可以在夹层里加上蔬菜、沙拉、咸肉等等,外面可以涂上奶油之类的。假如现在你要为一个三明治小店构造一个程序,其中要设计各种三明治的对象。可能你已经创建了一个简单的Sandwich对象,现在要产生带蔬菜的就是继承原有的Sandwich添加一个蔬菜的成员变量,看起来很“正点”的做法,以后我还要带咸肉的、带奶油的、带蔬菜的又分为带青菜的、带芹菜的、生菜的……还是一个一个继承是吧!假如我们还需要即带蔬菜又带其它肉类,设置我们还要求这些添加成分的任意组合,那你就慢慢继承吧!下面我们就使用装饰器模式来设计这个库吧!下图是我们的设计图:

下面是以上各个类的意义:

1. Ingredient(成分):所有类的父类,包括它们共有的方法,一般为抽象类且方法都有默认的实现,也可以为接口。它有Bread和Decorator两个子类。这种实际不存在的,系统需要的抽象类仅仅表示一个概念,图中用红色表示。

2. Bread(面包):就是我们三明治中必须的两片面包。它是系统中最基本的元素,也是被装饰的元素,和IO中的媒质流(原始流)一个意义。在装饰器模式中属于一类角色,所以其颜色为紫色。

3. Decorator(装饰器):所有其它成分的父类,这些成分可以是猪肉、羊肉、青菜、芹菜。这也是一个实际不存在的类,仅仅表示一个概念,即具有装饰功能的所有对象的父类。图中用蓝色表示。

4. Pork(猪肉):具体的一个成分,不过它作为装饰成分和面包搭配。

5. Mutton(羊肉):同上。

6. Celery(芹菜):同上。

7. Greengrocery(青菜):同上。

总结一下装饰器模式中的四种角色:1.被装饰对象(Bread);2.装饰对象(四种);3.装饰器(Decorator);4.公共接口或抽象类(Ingredient)。其中1和2是系统或者实际存在的,3和4是实现装饰功能需要的抽象类。

写段代码体会其威力吧!(程序很简单,但是实现的方法中可以假如如何你需要的方法,意境慢慢体会吧!)

//Ingredient.java

public abstract class Ingredient {

public abstract String getDescription();

public abstract double getCost();

public void printDescription(){

System.out.println(" Name "+ this.getDescription());

System.out.println(" Price RMB "+ this.getCost());

}

}

所有成分的父类,抽象类有一个描述自己的方法和一个得到价格的方法,以及一个打印自身描述和价格的方法(该方法与上面两个方法构成模板方法哦!)

//Bread.java

public class Bread extends Ingredient {

private String description ;

public Bread(String desc){

this.description=desc ;

}

public String getDescription(){

return description ;

}

public double getCost(){

return 2.48 ;

}

}

面包类,因为它是一个具体的成分,因此实现父类的所有的抽象方法。描述可以通过构造器传入,也可以通过set方法传入。同样价格也是一样的,我就很简单地返回了。

//Decorator.java

public abstract class Decorator extends Ingredient {

Ingredient ingredient ;

public Decorator(Ingredient igd){

this.ingredient = igd;

}

public abstract String getDescription();

public abstract double getCost();

}

装饰器对象,所有具体装饰器对象父类。它最经典的特征就是:1.必须有一个它自己的父类为自己的成员变量;2.必须继承公共父类。 这是因为装饰器也是一种成分,只不过是那些具体具有装饰功能的成分的公共抽象罢了。在我们的例子中就是有一个Ingredient作为其成员变量。Decorator继承了Ingredient类。

//Pork.java

public class Pork extends Decorator{

public Pork(Ingredient igd){

super(igd);

}

public String getDescription(){

String base = ingredient.getDescription();

return base +"\n"+"Decrocated with Pork !";

}

public double getCost(){

double basePrice = ingredient.getCost();

double porkPrice = 1.8;

return basePrice + porkPrice ;

}

}

具体的猪肉成分,同时也是一个具体的装饰器,因此它继承了Decorator类 。猪肉装饰器装饰可以所有的其他对象,因此通过构造器传入一个Ingredient的实例,程序中调用了父类的构造方法,主要父类实现了这样的逻辑关系。同样因为方法是具体的成分,所以getDescription得到了实现,不过由于它是具有装饰功能的成分,因此它的描述包含了被装饰成分的描述和自身的描述。价格也是一样的。价格放回的格式被装饰成分与猪肉成分的种价格哦!

从上面两个方法中我们可以看出,猪肉装饰器的功能得到了增强,它不仅仅有自己的描述和价格,还包含被装饰成分的描述和价格。主要是因为被装饰成分是它的成员变量,因此可以任意调用它们的方法,同时可以增加自己的额外的共同,这样就增强了原来成分的功能。

//Mutton.java

public class Mutton extends Decorator{

public Mutton(Ingredient igd){

super(igd);

}

public String getDescription(){

String base = ingredient.getDescription();

return base +"\n"+"Decrocated with Mutton !";

}

public double getCost(){

double basePrice = ingredient.getCost();

double muttonPrice = 2.3;

return basePrice + muttonPrice ;

}

}

羊肉的包装器。

//Celery.java

public class Celery extends Decorator{

public Celery(Ingredient igd){

super(igd);

}

public String getDescription(){

String base = ingredient.getDescription();

return base +"\n"+"Decrocated with Celery !";

}

public double getCost(){

double basePrice = ingredient.getCost();

double celeryPrice =0.6;

return basePrice + celeryPrice ;

}

}

芹菜的包装器。

//GreenGrocery.java

public class GreenGrocery extends Decorator{

public GreenGrocery (Ingredient igd){

super(igd);

}

public String getDescription(){

String base = ingredient.getDescription();

return base +"\n"+"Decrocated with GreenGrocery !";

}

public double getCost(){

double basePrice = ingredient.getCost();

double greenGroceryPrice = 0.4;

return basePrice + greenGroceryPrice ;

}

}

青菜的包装器。

下面我们就领略装饰器模式的神奇了!我们有一个测试类,其中建立夹羊肉的三明治、全蔬菜的三明治、全荤的三明治。
public class DecoratorTest{

public static void main(String[] args){

Ingredient compound = new Mutton(new Celery(new Bread("Master24's Bread")));

compound.printDescription();

compound = new Celery(new GreenGrocery(new Bread("Bread with milk")));

compound.printDescription();

compound = new Mutton(new Pork(new Bread("Bread with cheese")));

compound.printDescription();

}

}

以上就是一个简单的装饰器类。

a.DataInputStream类

实现了DataInput接口,用于读取基本类型数据。如int,long,float,double,boolean。其中的readUTF()方法还能读取UTF-8编码的字符串。其应该与DataOutputStream配套使用。也就是说,用DataInputStream读取由DataOutputStream写出的数据,才能保证获得正确的数据。

b.LineNumberInputStream类:已被废弃

c.BufferedInputStream类

覆盖了被装饰的输入流的读数据行为,利用buffer来提供效率。一般在读取数据文件或者键盘输入时都使用其进行装饰。

d.PushbackInputStream类

很少用到。

3.字节输出流

image_thumb4

1)字节数组输出流:ByteArrayOutputStream类

向内存中的字节数组写数据,使用toByteArray方法获得字节数组。

2)文件输出流:FileOutputStream类

向文件中写数据。注意默认下使用则是覆盖文件,必须使用FileOutputStream(String name,boolean append),在后边设置为true则是在追加。

3)过滤输出流:FilterOutputStream类

和过滤输入流的特性一样。

a)DataOutputStream类:

用于向输出流写基本数据类型。

b)BufferedOutputStream类:

缓冲区提高效率。在超过缓冲区时会将缓冲区的内的数据写入输出流,若没有超过则不会自动写入,否则使用flush()方法刷新,或者关闭输出流。

c)PrintStream类:

采用本地OS默认的字符编码输出格式化数据。每一个Print()方法都与一个println()方法对应。使用checkError()方法判断写数据是否成功。它也带有缓冲区,不过用户可以自己设置刷新规则(见其构造函数的一个重载)。

4.字符输入流

image_thumb8

注意BufferedReader不是FilterReader的子类。

1)字符数组输入流:CharArrayReader类

从内存中的字符数组中读取字符。

2)字符串输入流:StringReader类

数据源是字符串。

3)InputStreamReader类:

image_thumb10

主要是解决Unicode字符编码和用户指定编码的变换问题。为了提高效率则可以使用BufferedReader来修饰。它有个子类是FileReader类,但是其只能按照本地平台的字符编码来读取数据,用户不能指定编码类型。

4)BufferedReader类:

带有缓冲区的字符输入流。

5.字符输出流

image_thumb12

1)字符数组输出流:CharArrayWriter类

将内存中的字符中写入字符数组。

2)BufferedWriter类:带有缓冲。

3)OutputStreamWriter类:

为了提高效率则可以使用BufferedWriter来修饰。它有个子类是FileWriter类,但是其只能按照本地平台的字符编码来写入数据,用户不能指定编码类型。

4)PrintWriter类:能输出格式化的数据。在输出字符数据的场合,应该优先考虑用PrintWriter。

6.标准IO

三个标准输入输出流:

System.in:InputStream类,代表标准输入流,默认为键盘。常用套路是InputStreamReader适配器把System.in转换为Reader类型,再用BufferedReader装饰它。

System.out:PrintStream类,代表标准输出流,默认为控制台。通常转化为PrintWriter类型。

System.err:PrintStream类,代表标准错误输出流,默认为控制台。

重定向使用System类中的,setIN(),setOut(),setErr()方法。

7.随机访问文件类:RandomAccessFile

可以从任意位置对文件进行读写。实现了DataInput和DataOutput接口,可以读写格式化的数据。

8.新IO库的部分介绍

java.nio包中,目的在于提高IO操作效率。缓冲器Buffer类:减少了实际物理读写次数,减少动态分配和回收内存区域的次数。这个类可以使得程序直接控制和运用缓冲区。抽象类,有8个具体的缓冲区类,都有能返回自身实例的静态工厂方法。

image_thumb15

缓冲区的几个属性(也提供了改变这三个属性的方法):

容量:缓冲区的大小。

极限:缓冲区的当前终点。这个点即为实际的数据区的终点。

位置:缓冲区的下一个读写单元。

image_thumb14

Channel是用来连接缓冲区与数据源的。通道在创建时被打开,一旦关闭就不能再打开了。

有两个常用方法:一个是flip(),确保后续操作只针对在缓冲区中的当前数据,而clear()方法则把缓冲区的极限设为容量值,为后续向缓冲区填入更多的数据做准备。

2)字符编码Charset类

其中的每个实例都代表特定的字符编码类型。

3)FileChannel读写文件

放一个例子吧,从书上摘的:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;

public class Test{
public static void main(String[] args) throws IOException{
final int SIZE = 1024;
/*向文件中写数据*/
FileChannel fcChannel = new FileOutputStream("c:\\test.txt").getChannel();
fcChannel.write(ByteBuffer.wrap("你好,".getBytes()));//静态方法wrap为包装为一个ByteBuffer对象
fcChannel.close();
/*向文件末尾添加数据*/
fcChannel = new RandomAccessFile("c:\\test.txt","rw").getChannel();
fcChannel.position(fcChannel.size());//定位到文件尾
fcChannel.write(ByteBuffer.wrap("世界!".getBytes()));
fcChannel.close();
/*读数据*/
fcChannel = new FileInputStream("c:\\test.txt").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(SIZE);//创建ByteBuffer对象
fcChannel.read(buffer);//将文件中的数据读入缓冲区中
buffer.flip();//将极限设为当前位置值,再把position设为0,这使得接下来的cs.decode(buff)方法仅仅操作刚刚写入缓冲区的数据。
Charset cs = Charset.defaultCharset();//获得本地OS的字符编码
System.out.println(cs.decode(buffer));//转换为Unicode字符编码
fcChannel.close();
}
}

分享到:
评论

相关推荐

    Java面向对象编程学习笔记.pdf

    "Java面向对象编程学习笔记.pdf" Java面向对象编程学习笔记是Java程序设计语言中面向对象编程(Object-Oriented Programming,OOP)的一份学习笔记。面向对象编程是一种软件设计方法,它强调使用对象和类来模拟现实...

    JAVA的面向对象编程学习笔记

    JAVA的面向对象编程学习笔记

    JAVA的面向对象编程笔记(经典)

    Java面向对象编程笔记 本文主要介绍了Java面向对象编程的基本概念和原则,包括对象、类、继承、多态、封装、抽象等概念的定义和解释,并通过实例讲解了面向对象编程的思想和方法。 一、什么是对象? 在面向对象...

    JAVA面向对象编程(孙卫琴)学习笔记

    综上所述,这些文件覆盖了Java面向对象编程的基本元素,从入门到深入,对于系统学习和理解Java面向对象编程有着极大的帮助。无论是初学者还是有经验的开发者,都可以从中找到提升自身技能的宝贵资料。

    Java I/O学习笔记: 磁盘操作 字节操作 字符操作 对象操作 网络操作 NIO & AIO Java I/O

    Java I/O学习笔记: 磁盘操作 字节操作 字符操作 对象操作 网络操作 NIO & AIO Java I/O Java是一种面向对象的编程语言,由Sun Microsystems于1995年推出。它是一种跨平台的语言,意味着可以在不同的操作系统上运行...

    JAVA面向对象编程学习笔记.pdf

    JAVA面向对象编程,是程序设计方法学的一种,强调通过对象来设计程序和组织数据。面向对象编程(OOP)的思想模型是现实世界的抽象,其核心概念包括类(Class)、对象(Object)、继承(Inheritance)、封装...

    WI TWO 淘宝分享Java面向对象编程(孙卫琴)_学习笔记

    Java面向对象编程是Java开发中的核心概念,由孙卫琴老师讲解的这门课程深入...以上只是部分Java面向对象编程的关键知识点,实际学习中,还需要结合实例深入理解和实践,以便更好地掌握这些概念并在实际开发中灵活应用。

    accp6.0_使用Java面向对象编程_笔记.doc

    ### 使用Java面向对象编程知识点...通过以上知识点的学习,我们能够更好地理解和运用Java面向对象编程的基本概念和技术。面向对象编程是一种强大的编程范式,它不仅简化了程序设计,还提高了代码的可维护性和可扩展性。

    Java面象对象编程学习笔记(孙卫琴版)doc+pdf

    Java面向对象编程是Java开发的核心概念,它基于面向对象编程思想,使得代码更易于理解和维护。孙卫琴老师的《Java面向对象编程》是一本深受初学者欢迎的教材,旨在帮助读者掌握这一关键技术。 首先,我们要了解面向...

    Java面向对象程序设计笔记

    Java面向对象编程的特性包括继承、多态和封装。继承允许子类继承父类的属性和方法,增强代码的扩展性;super关键字用于在子类中引用父类的成员;this关键字则用于在当前对象中引用自身成员。子类对象的构造和初始化...

    JAVA的面向对象编程Java学习笔记(必看经典).doc

    面向对象编程是Java的核心特性,它与传统的面向过程编程有所不同。面向过程编程中,基本单元是函数,而面向对象编程的焦点在于“对象”。对象包含了属性(数据)和方法(行为),它们共同描述了一个实体的特征和功能...

    JAVA面向对象基础总结笔记

    ### JAVA面向对象基础总结 #### 一、面向对象的基本概念 面向对象编程(Object-Oriented Programming, OOP)是一种程序设计范式,它将数据和处理这些数据的方法组织在一起,形成一个整体——对象(Object)。Java...

    java面向对象和第一章整理笔记

    Java面向对象编程是Java语言的核心特性,它基于面向对象编程(OOP)理论,使得代码更易于理解、维护和重用。本章整理的笔记主要涵盖了以下几个关键知识点: 1. **Java简介**: Java是一种跨平台的、开源的、高性能...

    Java基础 学习笔记 Markdownr版

    1. 面向对象(OOP):Java的核心是面向对象编程,它将数据和操作数据的方法封装在一起,形成类。面向对象的三大特性——封装、继承和多态,在06面向对象(上)、07面向对象(中)和08面向对象(下)中进行了详细介绍...

    JAVA个人学习笔记

    JAVA学习笔记是面向对象编程语言的学习笔记,涵盖了JAVA的基本概念、面向对象编程思想、类和对象的概念、实例变量和局部变量的区别、方法的定义和调用、类型转换、精度问题、移位问题、switch语句的使用等内容。...

    java面向对象编程--课堂笔记

    在Java编程中,面向对象编程(Object-Oriented Programming, OOP)是一种核心的设计思想,它与面向过程编程有着本质的区别。面向对象编程基于"万物皆对象"的理念,将数据和操作数据的方法封装在一起,形成独立的对象...

    Java 学习笔记Java学习笔记

    2. 类与对象:面向对象编程(OOP)是Java的核心。类是对象的模板,包含了数据(字段)和行为(方法)。对象是类的实例,通过构造函数创建。封装、继承和多态是OOP的三大特性,Java通过访问修饰符(public、private、...

    Java学习笔记-面向对象-001-面向对象概括

    面向对象编程(Object-Oriented Programming,简称OOP)是一种重要的编程范式,它基于对象的概念,通过将数据和操作数据的方法封装在一起,提供了一种更高效、灵活且可维护的编程方式。Java语言作为一门纯面向对象的...

    《java学习》-java学习笔记.zip

    Java是一种广泛使用的面向对象的编程语言,以其跨平台、健壮性和安全性著称。这份《java学习》笔记包含了多个核心主题,旨在帮助初学者和有经验的开发者深入理解和掌握Java技术。 1. **正则表达式(正则.md)**: ...

    Java编程思想学习笔记

    在讨论Java编程思想学习笔记时,首先需要了解的是Java语言的平台无关性,而这一特性正是通过Java虚拟机(JVM)得以实现的。JVM作为Java程序设计的关键组成部分,对于Java开发人员来说是必须掌握的基础知识。在该学习...

Global site tag (gtag.js) - Google Analytics