21、其他输入流与其他输出流

一、其他输入流

1、ByteArrayInputStream
字节数组输入流在内存中创建一个字节数组缓冲区,从输入流读取的数据保存在该字节数组缓冲区中。创建字节数组输入流对象有以下几种方式。
接收字节数组作为参数创建:

ByteArrayInputStream bArray = new ByteArrayInputStream(byte [] a);

另一种创建方式是接收一个字节数组,和两个整形变量 off、len,off表示第一个读取的字节,len表示读取字节的长度。

ByteArrayInputStream bArray = new ByteArrayInputStream(byte []a, int off, int len);

成功创建字节数组输入流对象后,可以参见以下列表中的方法,对流进行读操作或其他操作。
方法:

  • public int read():
    从此输入流中读取下一个数据字节。
  • public int read(byte[] r, int off, int len):
    将最多 len 个数据字节从此输入流读入字节数组。
  • public int available():
    返回可不发生阻塞地从此输入流读取的字节数。
  • public void mark(int read):
    设置流中的当前标记位置。
  • public long skip(long n):
    从此输入流中跳过 n 个输入字节。

实例:
ByteArrayInputStream 和 ByteArrayOutputStream的使用:

import java.io.*;
public class ByteStreamTest {
   public static void main(String args[])throws IOException {
      ByteArrayOutputStream bOutput = new ByteArrayOutputStream(12);
      while( bOutput.size()!= 10 ) {
         // 获取用户输入值
         bOutput.write(System.in.read());
      }

      byte b [] = bOutput.toByteArray();
      System.out.println("Print the content");
      for(int x= 0 ; x < b.length; x++) {
         // 打印字符
         System.out.print((char)b[x]  + "   ");
      }
      System.out.println("   ");

      int c;

      ByteArrayInputStream bInput = new ByteArrayInputStream(b);

      System.out.println("Converting characters to Upper case " );
      for(int y = 0 ; y < 1; y++ ) {
         while(( c= bInput.read())!= -1) {
            System.out.println(Character.toUpperCase((char)c));
         }
         bInput.reset();
      }
   }
}

输出结果:

pcclovezzy
Print the content
p   c   c   l   o   v   e   z   z   y
Converting characters to Upper case
P
C
C
L
O
V
E
Z
Z
Y

2、DataInputStream
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。
下面的构造方法用来创建数据输入流对象。

DataInputStream dis = new DataInputStream(InputStream in);

另一种创建方式是接收一个字节数组,和两个整形变量 off、len,off表示第一个读取的字节,len表示读取字节的长度。
方法:

  • public final int read(byte[] r, int off, int len)throws IOException:
    从所包含的输入流中将 len 个字节读入一个字节数组中。如果len为-1,则返回已读字节数。
  • public final int read(byte [] b)throws IOException:
    从所包含的输入流中读取一定数量的字节,并将它们存储到缓冲区数组 b 中。
  • ①public final Boolean readBooolean()throws IOException;
    ②public final byte readByte()throws IOException;
    ③public final short readShort()throws IOException;
    ④public final Int readInt()throws IOException;

    从输入流中读取字节,返回输入流中两个字节作为对应的基本数据类型返回值。
  • public String readLine() throws IOException:
    从输入流中读取下一文本行。

实例:
下面的例子演示了DataInputStream和DataOutputStream的使用,该例从文本文件test.txt中读取5行,并转换成大写字母,最后保存在另一个文件test1.txt中。
test.tx 文件内容如下:

jiuling1
jiuling2
jiuling3
jiuling4
jiuling5
import java.io.*;
 
public class Test{
   public static void main(String args[])throws IOException{
 
      DataInputStream in = new DataInputStream(new FileInputStream("test.txt"));
      DataOutputStream out = new DataOutputStream(new  FileOutputStream("test1.txt"));
      BufferedReader d  = new BufferedReader(new InputStreamReader(in));
     
      String count;
      while((count = d.readLine()) != null){
          String u = count.toUpperCase();
          System.out.println(u);
          out.writeBytes(u + "  ,");
      }
      d.close();
      out.close();
   }
}

输出结果:

JIULING1
JIULING2
JIULING3
JIULING4
JIULING5

二、其他输出流

1、ByteArrayOutputStream
字节数组输出流在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组缓冲区中。创建字节数组输出流对象有以下几种方式。
下面的构造方法创建一个32字节(默认大小)的缓冲区。

OutputStream bOut = new ByteArrayOutputStream();

另一个构造方法创建一个大小为 a 字节的缓冲区。

OutputStream bOut = new ByteArrayOutputStream(int a)

成功创建字节数组输出流对象后,可以参见以下列表中的方法,对流进行写操作或其他操作。
方法:

  • public void reset():
    将此字节数组输出流的 count 字段重置为零,从而丢弃输出流中目前已累积的所有数据输出。
  • public byte[] toByteArray():
    创建一个新分配的字节数组。数组的大小和当前输出流的大小,内容是当前输出流的拷贝。
  • public String toString():
    将缓冲区的内容转换为字符串,根据平台的默认字符编码将字节转换成字符。
  • public void write(int w):
    将指定的字节写入此字节数组输出流。
  • public void write(byte []b, int off, int len):
    将指定字节数组中从偏移量 off 开始的 len 个字节写入此字节数组输出流。
  • public void writeTo(OutputStream outSt):
    将此字节数组输出流的全部内容写入到指定的输出流参数中。

实例:
ByteArrayInputStream 和 ByteArrayOutputStream 的使用:

import java.io.*;
public class ByteStreamTest {
   public static void main(String args[])throws IOException {
      ByteArrayOutputStream bOutput = new ByteArrayOutputStream(12);
      while( bOutput.size()!= 10 ) {
         // 获取用户输入
         bOutput.write(System.in.read()); 
      }
      byte b [] = bOutput.toByteArray();
      System.out.println("Print the content");
      for(int x= 0 ; x < b.length; x++) {
         // 打印字符
         System.out.print((char)b[x]  + "   "); 
      }
      System.out.println("   ");
      int c;
      ByteArrayInputStream bInput = new ByteArrayInputStream(b);
      System.out.println("Converting characters to Upper case " );
      for(int y = 0 ; y < 1; y++ ) {
         while(( c= bInput.read())!= -1) {
            System.out.println(Character.toUpperCase((char)c));
         }
         bInput.reset(); 
      }
   }
}

输出结果:

pcclovezzy
Print the content
p   c   c   l   o   v   e   z   z   y
Converting characters to Upper case
P
C
C
L
O
V
E
Z
Z
Y

2、DataOutputStream
数据输出流允许应用程序以与机器无关方式将Java基本数据类型写到底层输出流。
下面的构造方法用来创建数据输出流对象。

DataOutputStream out = new DataOutputStream(OutputStream  out);

创建对象成功后,可以参照以下列表给出的方法,对流进行写操作或者其他操作。
方法:

  • public final void write(byte[] w, int off, int len)throws IOException:
    将指定字节数组中从偏移量 off 开始的 len 个字节写入此字节数组输出流。
  • public final int write(byte [] b)throws IOException:
    将指定的字节写入此字节数组输出流。
  • ①public final void writeBooolean()throws IOException;
    ②public final void writeByte()throws IOException;
    ③public final void writeShort()throws IOException;
    ④public final void writeInt()throws IOException;

    这些方法将指定的基本数据类型以字节的方式写入到输出流。
  • public void flush()throws IOException:
    刷新此输出流并强制写出所有缓冲的输出字节。
  • public final void writeBytes(String s) throws IOException:
    将字符串以字节序列写入到底层的输出流,字符串中每个字符都按顺序写入,并丢弃其高八位。

实例:
下面的例子演示了DataInputStream和DataOutputStream的使用,该例从文本文件test.txt中读取5行,并转换成大写字母,最后保存在另一个文件test1.txt中。
test.tx 文件内容如下:

jiuling1
jiuling2
jiuling3
jiuling4
jiuling5
import java.io.*;
public class Test{
   public static void main(String args[])throws IOException{
      DataInputStream in = new DataInputStream(new FileInputStream("test.txt"));
      DataOutputStream out = new DataOutputStream(new  FileOutputStream("test1.txt"));
      BufferedReader d  = new BufferedReader(new InputStreamReader(in));
      String count;
      while((count = d.readLine()) != null){
          String u = count.toUpperCase();
          System.out.println(u);
          out.writeBytes(u + "  ,");
      }
      d.close();
      out.close();
   }
}

输出结果:

JIULING1
JIULING2
JIULING3
JIULING4
JIULING5

22、其他文件和IO

1、File Class(类)
Java文件类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。
File对象代表磁盘中实际存在的文件和目录。通过以下构造方法创建一个File对象。
通过给定的父抽象路径名和子路径名字符串创建一个新的File实例。

File(File parent, String child);

通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例。

File(String pathname) ;

根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。

File(String parent, String child) ;

通过将给定的 file: URI 转换成一个抽象路径名来创建一个新的 File 实例。

File(URI uri) ;

创建File对象成功后,可以使用以下列表中的方法操作文件。
方法:

  • public String getName():
    返回由此抽象路径名表示的文件或目录的名称。
  • public String getParent():
    返回此抽象路径名的父路径名的路径名字符串,如果此路径名没有指定父目录,则返回 null。
  • public File getParentFile():
    返回此抽象路径名的父路径名的抽象路径名,如果此路径名没有指定父目录,则返回 null。
  • public String getPath():
    将此抽象路径名转换为一个路径名字符串。
  • public boolean isAbsolute():
    测试此抽象路径名是否为绝对路径名。
  • public String getAbsolutePath():
    返回抽象路径名的绝对路径名字符串。
  • public boolean canRead():
    测试应用程序是否可以读取此抽象路径名表示的文件。
  • public boolean canWrite():
    测试应用程序是否可以修改此抽象路径名表示的文件。
  • public boolean exists():
    测试此抽象路径名表示的文件或目录是否存在。
  • public boolean isDirectory():
    测试此抽象路径名表示的文件是否是一个目录。
  • public boolean isFile():
    测试此抽象路径名表示的文件是否是一个标准文件。
  • public long lastModified():
    返回此抽象路径名表示的文件最后一次被修改的时间。
  • public long length():
    返回由此抽象路径名表示的文件的长度。
  • public boolean createNewFile() throws IOException:
    当且仅当不存在具有此抽象路径名指定的名称的文件时,原子地创建由此抽象路径名指定的一个新的空文件。
  • public boolean delete():
    删除此抽象路径名表示的文件或目录。
  • public void deleteOnExit():
    在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。
  • public String[] list():
    返回由此抽象路径名所表示的目录中的文件和目录的名称所组成字符串数组。
  • public String[] list(FilenameFilter filter):
    返回由包含在目录中的文件和目录的名称所组成的字符串数组,这一目录是通过满足指定过滤器的抽象路径名来表示的。
  • public File[] listFiles():
    返回一个抽象路径名数组,这些路径名表示此抽象路径名所表示目录中的文件。
  • public File[] listFiles(FileFilter filter):
    返回表示此抽象路径名所表示目录中的文件和目录的抽象路径名数组,这些路径名满足特定过滤器。
  • public boolean mkdir():
    创建此抽象路径名指定的目录。
  • public boolean mkdirs():
    创建此抽象路径名指定的目录,包括创建必需但不存在的父目录。
  • public boolean renameTo(File dest):
    重新命名此抽象路径名表示的文件。
  • public boolean setLastModified(long time):
    设置由此抽象路径名所指定的文件或目录的最后一次修改时间。
  • public boolean setReadOnly():
    标记此抽象路径名指定的文件或目录,以便只可对其进行读操作。
  • public static File createTempFile(String prefix, String suffix, File directory) throws IOException:
    在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。
  • public static File createTempFile(String prefix, String suffix) throws IOException:
    在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。
  • public int compareTo(File pathname):
    按字母顺序比较两个抽象路径名。
  • public int compareTo(Object o):
    按字母顺序比较抽象路径名与给定对象。
  • public boolean equals(Object obj):
    测试此抽象路径名与给定对象是否相等。
  • public String toString():
    返回此抽象路径名的路径名字符串。

实例:
File对象的使用:

import java.io.File;
public class DirList {
    public static void main(String args[]) {
        String dirname = "/java";
        File f1 = new File(dirname);
        if (f1.isDirectory()) {
            System.out.println("Directory of " + dirname);
            String s[] = f1.list();
            for (int i = 0; i < s.length; i++) {
                File f = new File(dirname + "/" + s[i]);
                if (f.isDirectory()) {
                    System.out.println(s[i] + " is a directory");
                } else {
                    System.out.println(s[i] + " is a file");
                }
            }
        } else {
            System.out.println(dirname + " is not a directory");
        }
    }
}

输出结果:

Directory of /java
bin is a directory
lib is a directory
demo is a directory
test.txt is a file
README is a file
index.html is a file
include is a directory

2、FileReader Class(类)
FileReader类从InputStreamReader类继承而来。该类按字符读取流中数据。可以通过以下几种构造方法创建需要的对象。

在给定从中读取数据的 File 的情况下创建一个新 FileReader。

FileReader(File file);

在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。

FileReader(FileDescriptor fd);

在给定从中读取数据的文件名的情况下创建一个新 FileReader。

FileReader(String fileName);

创建FIleReader对象成功后,可以参照以下列表里的方法操作文件。
方法:

  • public int read() throws IOException:
    读取单个字符,返回一个int型变量代表读取到的字符
  • public int read(char [] c, int offset, int len):
    读取字符到c数组,返回读取到字符的个数

实例:

import java.io.*;
public class FileRead {
    public static void main(String args[]) throws IOException {
        File file = new File("Hello1.txt");
        // 创建文件
        file.createNewFile();
        // creates a FileWriter Object
        FileWriter writer = new FileWriter(file);
        // 向文件写入内容
        writer.write("This\n is\n an\n example\n");
        writer.flush();
        writer.close();
        // 创建 FileReader 对象
        FileReader fr = new FileReader(file);
        char[] a = new char[50];
        fr.read(a); // 读取数组中的内容
        for (char c : a)
            System.out.print(c); // 一个一个打印字符
        fr.close();
    }
}

输出结果:

This
is
an
example

3、FileWriter Class(类)
FileWriter 类从 OutputStreamWriter 类继承而来。该类按字符向流中写入数据。可以通过以下几种构造方法创建需要的对象。

在给出 File 对象的情况下构造一个 FileWriter 对象。

FileWriter(File file);

在给出 File 对象的情况下构造一个 FileWriter 对象。

FileWriter(File file, boolean append);

参数:

  • file:要写入数据的 File 对象。
  • append:如果 append 参数为 true,则将字节写入文件末尾处,相当于追加信息。如果 append 参数为 false, 则写入文件开始处。

构造与某个文件描述符相关联的 FileWriter 对象。

FileWriter(FileDescriptor fd);

在给出文件名的情况下构造 FileWriter 对象,它具有指示是否挂起写入数据的 boolean 值。

FileWriter(String fileName, boolean append);

创建FileWriter对象成功后,可以参照以下列表里的方法操作文件。
方法:

  • public void write(int c) throws IOException:
    写入单个字符c。
  • public void write(char [] c, int offset, int len):
    写入字符数组中开始为offset长度为len的某一部分。
  • public void write(String s, int offset, int len):
    写入字符串中开始为offset长度为len的某一部分。

实例:

import java.io.*;
 
public class FileRead {
    public static void main(String args[]) throws IOException {
        File file = new File("Hello1.txt");
        // 创建文件
        file.createNewFile();
        // creates a FileWriter Object
        FileWriter writer = new FileWriter(file);
        // 向文件写入内容
        writer.write("This\n is\n an\n example\n");
        writer.flush();
        writer.close();
        // 创建 FileReader 对象
        FileReader fr = new FileReader(file);
        char[] a = new char[50];
        fr.read(a); // 从数组中读取内容
        for (char c : a)
            System.out.print(c); // 一个个打印字符
        fr.close();
    }
}

输出结果:

This
is
an
example

总结:

      这篇主要是紧接着上一篇内容所补充的,当然Java的IO流是基于BIO的,当线程过多的时候就会一直处于阻塞状态,在Java当中为解决阻塞状态还提出了一些其他的IO操作,被称为NIO,这块感兴趣的小伙伴可以关注一下,本篇主要还是以IO流为主,在后续会给大家讲解!