首页 > 代码库 > Java基础——iO(二)

Java基础——iO(二)

接着上一篇,继续做学习笔记。学IO这块,突然找到一点好处,好像以后操作电脑,尤其是电脑里的文件啥的,可以很少的用鼠标了。添加、修改、删除啥的,几行代码就可以搞定了。这只是我一个初学者的一点小心思,IO背后的大用处,相信还有很多很多。继续学习ing....

一、缓冲流和装饰模式

缓冲流(包装类),缓冲区的出现提高了对数据读写的效率,它可以用来对流进行包装,在流的基础上对流的功能进行了增强。和底层系统提供的缓冲区有什么区别?底层直接和目标设备交换数据,包装类中,通过被包装的对象。

BufferedReader : 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

BufferedReader 的构造函数有两个:

---- BufferedReader(Reader in)        

---- BufferedReader(Reader in, int sz) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。

//例子  BufferedWriter 的使用
FileWriter w=new FileWriter("2.txt");
BufferedWriter bw=new BufferedWriter(w);
    bw.write("这是一行内容");
    bw.newLine();  //这是包装类提供的功能
    bw.write("这又是一行内容");
    bw.flush();  //用缓冲流,不要忘了flush()
    bw.close();  //它就相当于关闭 w,这么写了以后,就不用再写 w.close() 了
//例子  BufferedReader 的使用
public static void main(String[] args)throws IOException {
    List<String> nameList= demo2();
    for(String s:nameList)
    {
    System.out.println(s);
    }
}
            
static List<String> demo2() throws IOException {
    List<String> nameList=new ArrayList<String>();
    FileReader r=new FileReader("C:/名单.txt");
    BufferedReader br=new BufferedReader(r);
    String str=null;
    while( (str=br.readLine())!=null ){
    nameList.add(str);
    }
     br.close();
    return nameList;
}

二、装饰设计模式

Decorator模式(别名Wrapper):动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案。当要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有对象的功能,并提供加强功能。那么自定义的该类就称为装饰类。装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。

public class Teste3 {
    public static void main(String[] args) {
    Japan japan=new Japan();
    NiceJapan niceJapan=new NiceJapan(japan);
    niceJapan.speak();    
    }
}
class Japan{
    void speak(){
    System.out.println("我们都是好学生");
    }
}
class NiceJapan{
        NiceJapan(Japan japan){
    this.japan=japan;
    }
    private Japan japan;  //组合
    void speak(){
    System.out.println("清清嗓子");//其他动作
    System.out.println("晃晃脑袋");
    japan.speak();
    System.out.println("磕几个头");
    System.out.println("发几声惨叫");
    }
}

三、字节流概述

在不考虑负数的情况下,每个字节中的数据,都是0-255之间的值(因为一个字节为8位,最大为255)

如果一个文件中的每个字节或每相邻的几个字节的数据都可以表示成某个字符,则可以将这个文件称为文本文件,其实这是二进制的一个特例。

(你可以打开一个记事本,然后把一张图片拉进去,会发现一大堆的乱码,它就是二进制的特例,图片上的信息有的能与码表对上就被显示出来,有的不能就乱了。这是因为,字节流操作的时候,操作单位都是以字节为单位进行的操作的对象不一定有码表对应。

概述:

1.所有字节输入流类都是抽象类InputStream的子类

int read() 从源中读取一个字节的数据,返回字节值

int read(byte b[])从源中试图读取b.length个字节到b中,返回实际读取的字节目

void close()关闭输入流

2.所有字节输出流类都是抽象类OutputStream的子类

void write(int n) 向输出流写入单个字节。

void write(byte b[])向输出流写入一个字节数组

void flush()把缓冲区中内容输出并清空缓冲区(刷新)

void close()关闭输出流

3.例子,使用字节流进行文件的读写

FileOutputStream 用于写入诸如图像数据之类的原始字节的流。要写入字符流,请考虑使用 FileWriter。

FileOutputStream 的write方法的几种重载形式如下:

//void write(byte[] b)  //注意返回类型是void

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

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

//FileInputStream 的read方法的几种重载形式如下

//int read()   从此输入流中读取一个数据字节。 返回读到的字节,到尾返回-1

//int read(byte[] b)  从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中 返回读的字节数,到尾返回-1

//int read(byte[] b, int off, int len)  从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。

//对于字节流来说,每次读到的就是一个字节,如果是英文,正好一个英文对应一个字节,如果中文,就可能对应两个字节

static void demo1() throws IOException{    
    OutputStream out=new FileOutputStream("c:/file1.txt");
    out.write("abcEnlish中国".getBytes());  //字节流不刷新也能写出去
    out.close();
    
        InputStream in=new FileInputStream("c:/file1.txt");
    int ch=0;
    while((ch=in.read())!=-1  ){
    System.out.println((char)ch);  //可以发现,如果是英文,能显示出来,但中文会乱码
        }
    in.close();
                    
} 
//例子,用字节数组进行接收
static void demo1()throws IOException {
    InputStream in=new FileInputStream("c:/名单.txt");
    byte [] buff=new byte[3];  //1024
    int len=0;
    while( (len=in.read(buff)) !=-1 ){
    String str=new String(buff,0,len);
    System.out.println(str);  //有乱码
        }
}
//例子 available 的利用
static void demo2()throws IOException{
    InputStream in=new FileInputStream("c:/名单.txt");
    byte [] buff=new byte[in.available()];   //in.available();当前流中还有多少个字节可读
    in.read(buff);
    System.out.println(new String(buff));
    in.close();
}
//例子.图片的复制
static void demo3()throws IOException  {
    InputStream in=new FileInputStream("C:\\image\\lengtu.jpg");
    byte [] buff=new byte[in.available()];
    in.read(buff);
    
        OutputStream out=new FileOutputStream("E:/tuzi.jpg");
    out.write(buff);
    in.close();
    out.close();
}

补充:

前面,字符流有包装类

BufferedReader,  BufferedWriter

字节流也有包装类

BufferedInputStream, BufferedOutputStream

四、转换流  InputStreamReader , OutputStreamWriter

把字节输入流转为字符输入流:

InputStreamReader    

public class  InputStreamReader extends Reader 

把字节输出流转为字符输出流:

OutputStreamWriter   

public class OutputStreamWriter extends Writer 

1) InputStreamReader

它有四个构造函数:

InputStreamReader(InputStream in)

InputStreamReader(InputStream in, Charset cs)

InputStreamReader(InputStream in, CharsetDecoder dec)  //CharsetDecoder 解码器

InputStreamReader(InputStream in, String charsetName) 

2) OutputStreamWriter 

它有四个构造函数:

OutputStreamWriter(OutputStream out) //创建使用默认字符编码的 OutputStreamWriter。

OutputStreamWriter(OutputStream out, CharsetEncoder enc) // 创建使用给定字符集的 OutputStreamWriter。

OutputStreamWriter(OutputStream out, String charsetName) // 创建使用给定字符集编码器的 OutputStreamWriter。

OutputStreamWriter(OutputStream out, String charsetName) // 创建使用指定字符集的 OutputStreamWriter。

//例子,用缓冲流包装转换流,转换流转换字节流
InputStream in=new FileInputStream("c:/1.txt");
    InputStreamReader inputReader=new InputStreamReader(in);
    BufferedReader br=new BufferedReader(inputReader);
        String str=null;
    while((str=br.readLine())!=null){
    System.out.println(str);
}
//例子 从键盘读入数据,转成大写打印出来
public static void main(String[] args) throws IOException {
    BufferedReader br=new BufferedReader( new InputStreamReader(System.in));
    String msg=null;
    while((msg=br.readLine())!=null){
        System.out.println(msg.toUpperCase());
        }
}

五、 ByteArrayInputStream 与ByteArrayOutputStream

它是用来以IO流的方式,完成对字节数组内容的读写,支持类似内存虚拟文件或内存映象文件的功能。

关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何IOException。

//ByteArrayInputStream(byte[] buff) 

//ByteArrayInputStream(byte[] buff,int offset,int length)

//ByteArrayOutStream () //没有传参,则默认创建一个32字节的缓冲区,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray()和toString()获取数据。

//ByteArrayOutStream(int size) 根据指定大小创建缓冲区

//ByteArrayOutStream 的  byte[] toByteArray() 创建一个新分配的 byte 数组。其大小是此输出流的当前大小,并且缓冲区的有效内容已复制到该数组中

 

//例子,使用 ByteArrayOutputStream 
ByteArrayOutputStream byteOut=new ByteArrayOutputStream();
    byteOut.write("这是放在虚拟内存中的数据".getBytes());
                
    byte[] byteArray=byteOut.toByteArray();
    String str=new String(byteArray);
    System.out.println(str);    
//加强 
从输入流中,读取字符,然后把字符变成大写,写入到输出流中
public static void main(String[] args) throws IOException {
    /* 示例1 用 ByteArrayInputStream 和 ByteArrayOutputStream
    ByteArrayInputStream in=new ByteArrayInputStream("abcdef".getBytes());
    ByteArrayOutputStream out=new ByteArrayOutputStream();
    transform(in,out);
                    
    byte  [] contents=out.toByteArray();
    String str=new String(contents);
    System.out.println(str); */
                    
    // 示例2 用键盘输入输出流 
       transform(System.in,System.out); 
                    
    // 示例3 用文件输入输出流
    InputStream in =new FileInputStream("c:/1.txt");
    OutputStream out =new FileOutputStream("e:/big.txt");
                     
    transform(in,out);
                    
}
                
                
static void transform(InputStream in,OutputStream out) throws IOException{
    int ch=0;
    while((ch=in.read())!=-1){
        out.write(Character.toUpperCase(ch));
    }
}

 

Java基础——iO(二)