Java IO 流(一)

字节流和字符流

字节流InputStream/OutputStream ,只能操作byte
字符流Reader/Writer

节点流和过滤流

节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。
过滤流:使用节点流作为输入或输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。FliterInputStream、FliterOutputStream

 

FileoutputStream(File f)

字节流本身是只能操作byte的。
对于这一个类,如果文件不存在会自动创建
write()方法默认会将文件进行覆盖
可以使用构造方法FileoutputStream(File f,boolean append),这样就可以指定要不要使用追加模式

FileinputStream(File f)

方法 - available() 获得可以读取的字节数

字符流

一般一个字符为两个字节,可以直接操作字符串
会用到缓冲区
FileWriter/FileReader
默认依然是覆盖,要追加只要和FileoutputStream类似加boolean标志就好了 Filereader读取到char/char[]

字节流和字符流的不同

字节流是直接与文件操作,不会用到缓冲区 字符流数据先放在缓冲区,然后再从缓冲区写到文件,要记得fiush()或者close()

字节-字符的转换流

  1. InputStreamReader
    将一个输入字节流转为字符流,是Reader的子类
  2. OutputStreamWriter
    将一个输出字节流转为字符流,是Writer的子类

FileWriter是OutputStreamWriter的子类 FileReader是OutputStreamReader的子类

内存操作流

ByteArrayInputStream(byte[])
将byte中是数据写入内存中
ByteArrayOutputStream()
实际的意思就是说,通过输入流将数据写入到内存里面,然后通过输出流把内存里面的东西取出来!

    private static void tesByteArrayInputStream() {
    // 创建ByteArrayInputStream字节流,内容是ArrayLetters数组
    ByteArrayInputStream bais = new ByteArrayInputStream(ArrayLetters);

    // 从字节流中读取5个字节
    for (int i=0; i<LEN; i++) {
        // 若能继续读取下一个字节,则读取下一个字节
        if (bais.available() >= 0) {
            // 读取“字节流的下一个字节”
            int tmp = bais.read();
            System.out.printf("%d : 0x%s
", i, Integer.toHexString(tmp));
        }
    }

    // 若“该字节流”不支持标记功能,则直接退出
    if (!bais.markSupported()) {
        System.out.println("make not supported!");
        return ;
    }

    // 标记“字节流中下一个被读取的位置”。即--标记“0x66”,因为因为前面已经读取了5个字节,所以下一个被读取的位置是第6个字节”
    // (01), ByteArrayInputStream类的mark(0)函数中的“参数0”是没有实际意义的。
    // (02), mark()与reset()是配套的,reset()会将“字节流中下一个被读取的位置”重置为“mark()中所保存的位置”
    bais.mark(0);

    // 跳过5个字节。跳过5个字节后,字节流中下一个被读取的值应该是“0x6B”。
    bais.skip(5);

    // 从字节流中读取5个数据。即读取“0x6B, 0x6C, 0x6D, 0x6E, 0x6F”
    byte[] buf = new byte[LEN];
    bais.read(buf, 0, LEN);
    // 将buf转换为String字符串。“0x6B, 0x6C, 0x6D, 0x6E, 0x6F”对应字符是“klmno”
    String str1 = new String(buf);
    System.out.printf("str1=%s
", str1);

    // 重置“字节流”:即,将“字节流中下一个被读取的位置”重置到“mark()所标记的位置”,即0x66。
    bais.reset();
    // 从“重置后的字节流”中读取5个字节到buf中。即读取“0x66, 0x67, 0x68, 0x69, 0x6A”
    bais.read(buf, 0, LEN);
    // 将buf转换为String字符串。“0x66, 0x67, 0x68, 0x69, 0x6A”对应字符是“fghij”
    String str2 = new String(buf);
    System.out.printf("str2=%s
", str2);
}

}

管道流

管道流就是实现两个进程之间的通信

PipeOutputStream PipeInputStream 使用的时候要使用connect()把输入输出流连接起来,Connect是PipeOutputStream的方法,用来连接一个PipeInputStream

打印流

PrintStream

定义了很多的print和pringtln方法,可以打印任意数据类型
System.out就是定位在输出设备的PrintStream

构造方法,指定输出的位置
PrintSTream(OutputStream out)

这样打印输出更加方便了,PrintStream就是OutputStream的子类,可以方便的进行输出,这样的设计称之为装饰设计模式

PrintWriter与上面的类似

格式化输出

类似于C语言的格式化输出 %d,%s,%f,%c

ps.printf("姓名%s,年龄:%d",a,b);

System.in以及BufferedReader(字符流)

是一个InputStream

    BufferedReader buf=null;
    buf=new BufferedReader(new InputStreamReader(System.in));
    String str=null;
    try {
        while ((str=buf.readLine())!=null){
            System.out.println(str);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

输入输出重定向

System.setOut(new PrintStream(new FileOutputStream("D:/a.txt")));

实际上in、out、err就是System的三个常量,可以通过set方法改变,然后就完成了重定向的作用。

Scanner

在java.util包中,可以实现BufferedReader的全部功能,是一个工具类

  • 默认的分隔符是空格,可以自行设置
  • 非常强大,可以接受多种类型的数据,但是对于日期类型没有支持,可以使用Scanner.hasNext(Pattern)/next(Pattern)匹配来取出数据
  • 可以接受File,做一系列文件操作

    Scanner scanner=new Scanner(System.in);
    scanner.useDelimiter("
    ");//修改分割符
    int a=0;
    float f=0f;
    String date=null;
    
    if(scanner.hasNextInt()){
        a=scanner.nextInt();
    }
    if(scanner.hasNextFloat()){
        f=scanner.nextFloat();
    }
    if(scanner.hasNext("\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}")){
        date=scanner.next("\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}");
    }
    System.out.println(a+" "+f+" "+date);
    try {
        Date date1=new SimpleDateFormat("yy-MM-dd hh:mm:ss").parse(date);
        System.out.println(date1);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    

合并流

压缩流

支持三种格式的压缩,zip/jar/Gzip,这里以zip为例另外两种都是一样的
ZipEntry,就是压缩文件目录下的每一个文件

  • ZipOutputStream(OutputStream)
    • PutNextEntry(ZipEntry ?)

可以将文件、文件夹进行压缩

ZipFile类

专门表示压缩文件的类

回退流

字符编码

获得本机编码
System.getProperity("file.encoding")

常见的编码格式

  • iso8859-1单字节编码,只能表示英文
  • GBK国标,表示汉字
  • unicode 16进制两个字节的编码,最标准的,但是不兼容iso-8859-1
  • utf 变长的编码,一个字符长度1--6不等,可以表示所有语言的字符、

关于io流的结构

输入流

  • InputStream
    • ByteArrayInputStream(byte[])
    • FileInputStream(File)
    • PipedInputStream
    • SequenceInputStream(InputStream,InputStream)
    • FilterInputStream
      • BufferedInputStream(InputStream)
      • PushbackInputStream
      • DataInputStream
        • ObjectInputStream

输出流

  • OutputStream
    • ByteArrayOutputStream
    • FileOutputStream
    • PipedOutputStream
    • FilterOutputStream
      • BufferedOutputStream
      • PrintWriter
      • DataOutputStream
        • ObjectOutputStream

常见的方法

                        InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法.Inputstream类中的常用方法:

                      1   public abstract int read( ):读取一个byte的数据,返回值是高位补0的int类型值。

                      2   public int read(byte b[ ]):读取b.length个字节的数据放到b数组中。返回值是读取的字节数。该方法实际上是调用下一个方法实现的

                      3   public int read(byte b[ ], int off, int len):从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中。

                      4   public int available( ):返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用,

                      5   public long skip(long n):忽略输入流中的n个字节,返回值是实际忽略的字节数, 跳过一些字节来读取

                      6   public int close( ) :我们在使用完后,必须对我们打开的流进行关闭. 

                    OutputStream提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。

                      1. public void write(byte b[ ]):将参数b中的字节写到输出流。

                      2. public void write(byte b[ ], int off, int len) :将参数b的从偏移量off开始的len个字节写到输出流。

                      3. public abstract void write(int b) :先将int转换为byte类型,把低字节写入到输出流中。

                      4. public void flush( ) : 将数据缓冲区中数据全部输出,并清空缓冲区。

                      5. public void close( ) : 关闭输出流并释放与流相关的系统资源。

java的流类提供了结构化方法,如,底层流和高层过滤流。
而高层流不是从输入设备读取,而是从其他流读取。同样高层输出流也不是写入输出设备,而是写入其他流。
使用"分层对象(layered objects)",为单个对象动态地,透明地添加功能的做法,被称为Decorator
Pattern。Decorator模式要求所有包覆在原始对象之外的对象,都必须具有与之完全相同的接口。这使得
decorator的用法变得非常的透明--无论对象是否被decorate过,传给它的消息总是相同的。这也是Java I/O
类库要有"filter(过滤器)"类的原因:抽象的"filter"类是所有decorator的基类

  • DataInputStream 包含了一整套读取primitive数据的接口
  • BufferedInputStream,为InputStream增加了一个缓冲区,缓冲区的大小是8k
  • PushbackInputStream 有一个"弹压单字节"的缓冲区,可以把最后读到的那个字节再压回去
  • DataOutputStream 包括写入primitive数据的全套接口。
  • PrintStream(inpurstream,boolean autoflush) 打印流
  • BufferedOutputStream 有缓冲区
原文地址:https://www.cnblogs.com/Coder-Pig/p/6599120.html