具有Map接口中的所有方法,参数offset指定从数组中开始读取数据的起始下标位置

buf)——–参数buf指定字节数组类型的数据源,lenght)—–参数buf指定字节数组类型数据源,buf)——–参数buf指定字节数组类型的数据源,lenght)—–参数buf指定字节数组类型数据源,但是在保存和读取数据的时候不建议使用put和get方法,建议使用Properties中特有的方法进行数据的存储,字符串转成字节才能被字节流操作,和字节流缓冲区的区别在于读取流没有readLine()方法,在读写文件需要对内容按行处理,只是读写文件

图片 2

java IO流 之 其他流,javaio流

二、打印流(PrintStream,PrintWriter)

PrintStream是FilterOutputStream的子类。

PrintWriter 是 Writer的子类。

打印流的特点:
 *
  A:只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。打印流只有字节打印流PrintStream 与字符打印流PrintWriter
 *
  B:可以操作任意类型的数据。他们的print()系列方法与println()系列方法可以操作任意类型数据。
 *   C:如果启动了自动刷新,能够自动刷新。但必须调用println()方法

      PrintWriter pw = new PrintWriter(new FileWriter(“pw2.txt”), true);

      PrintStream ps=new PrintStream(new
FileOutputStream(“a.txt”),true);
 *   D:该流是可以直接操作文本文件的。

       public
PrintStream(File file) 
throws
FileNotFoundException。

       public
PrintWriter(File file)
 throws
FileNotFoundException。

1、使用PrintStream实现文件的copy

public static void streamCopy() throws IOException{
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream("a.txt"));
        //public PrintStream(OutputStream out,boolean autoFlush)使用该够造函数 开启自动刷新功能
        PrintStream ps=new PrintStream(new FileOutputStream("Copy.java"),true);
        byte [] bys=new byte[1024];
        int line =0;
        while((line=bis.read(bys))!=-1){
            ps.println(new String(bys,0,line));
        }
        ps.close();
        bis.close();
    }

2、使用 PrintWriter实现文件的copy

public static void copy() throws IOException{
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        // 封装目的地 
        //public PrintWriter(OutputStream out,boolean autoFlush);使用该够造函数 开启自动刷新功能
        PrintWriter pw =new PrintWriter(new FileWriter("Copy.java"), true);
        String line = null;
        while((line=br.readLine())!=null){
            pw.println(line);
        }
        pw.close();
        br.close();
    }

/**

1.2、字节流

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

图片 1

总结:字节流不需要刷新,和字节流缓冲区的区别在于读取流没有readLine()方法,写入流没有newLine()方法。

InputStream 类似于Reader,但是它是操作字节流数据的。OutputStream 类似于
Writer,但是它是操作字节流数据的。

  FileOutputStream

二、打印流(PrintStream,PrintWriter)

PrintStream是FilterOutputStream的子类。

PrintWriter 是 Writer的子类。

打印流的特点:
 *
  A:只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。打印流只有字节打印流PrintStream 与字符打印流PrintWriter
 *
  B:可以操作任意类型的数据。他们的print()系列方法与println()系列方法可以操作任意类型数据。
 *   C:如果启动了自动刷新,能够自动刷新。但必须调用println()方法

      PrintWriter pw = new PrintWriter(new FileWriter(“pw2.txt”), true);

      PrintStream ps=new PrintStream(new
FileOutputStream(“a.txt”),true);
 *   D:该流是可以直接操作文本文件的。

       public PrintStream(File file)  throws FileNotFoundException。

       public PrintWriter(File file)  throws FileNotFoundException。

1、使用PrintStream实现文件的copy

public static void streamCopy() throws IOException{
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream("a.txt"));
        //public PrintStream(OutputStream out,boolean autoFlush)使用该够造函数 开启自动刷新功能
        PrintStream ps=new PrintStream(new FileOutputStream("Copy.java"),true);
        byte [] bys=new byte[1024];
        int line =0;
        while((line=bis.read(bys))!=-1){
            ps.println(new String(bys,0,line));
        }
        ps.close();
        bis.close();
    }

2、使用 PrintWriter实现文件的copy

public static void copy() throws IOException{
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        // 封装目的地 
        //public PrintWriter(OutputStream out,boolean autoFlush);使用该够造函数 开启自动刷新功能
        PrintWriter pw =new PrintWriter(new FileWriter("Copy.java"), true);
        String line = null;
        while((line=br.readLine())!=null){
            pw.println(line);
        }
        pw.close();
        br.close();
    }

一、内存操作流(ByteArrayInputStream、ByteArrayOutputStream)

 (一)、   public class ByteArrayInputStream extends
InputStream;

     ByteArrayInputSteam:该类是InputStream的子类,它从内存中的字节数组中读取数据,因此它的数据源是一个字节数组。这个类的构造方法包括: 
     ByteArrayInputStream(byte[]
buf)——–参数buf指定字节数组类型的数据源。 
     ByteArrayInputStream(byte[] buf, int offset, int
lenght)—–参数buf指定字节数组类型数据源,参数offset指定从数组中开始读取数据的起始下标位置,lenght指定从数组中读取的字节数。 
    
ByteArrayInputStream类本身采用了适配器设计模式,它把字节数组类型转换为输入流类型,使得程序能够对字节数组进行读操作。 

public static void byteArrTest() throws IOException{
        ByteArrayInputStream bis=new ByteArrayInputStream("abcd".getBytes());
        int len=0;
        while((len=bis.read())!=-1){
            System.out.println((char)len+"<=>"+len);
        }
        bis.close();
    }

(二)、public class ByteArrayOutputStream extends OutputStream。

ByteArrayOutputStream:此类实现了一个输出流,其中的数据被写入一个 byte
数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray()
toString() 获取数据。关闭 ByteArrayOutputStream
无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException

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

    public static void byteArrOut() throws IOException{
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        bos.write(97);
        bos.write(new byte[]{98,99,100});
        //public byte[] toByteArray()创建一个新分配的 byte 数组。其大小是此输出流的当前大小,并且缓冲区的有效内容已复制到该数组中。 
        byte [] bys=bos.toByteArray();
        for(byte b:bys){
            System.out.println(b+"<==>"+(char)b);
        }
    }

2、public String
toString()使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。新
String 的长度是字符集的函数,因此可能不等于缓冲区的大小。

public static void byteArrOut2() throws IOException{
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        bos.write(97);
        bos.write(new byte[]{98,99,100});
        //public String toString()使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。新 String 的长度是字符集的函数,因此可能不等于缓冲区的大小。 
        String str=bos.toString();
        System.out.println(str);//abcd
    }

(三)、ByteArrayInputStream、ByteArrayOutputStream一起使用

public static void byteArrOut() throws IOException{
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        bos.write(97);
        bos.write(new byte[]{98,99,100});
        byte [] bys=bos.toByteArray();
        ByteArrayInputStream bis=new ByteArrayInputStream(bys);
        int len=0;
        while((len=bis.read())!=-1){
            System.out.print((char)len);//abcd
        }
    }

常用方法:

3、IO流操作规律

public class TestByteArrayInputStream1 {

一、内存操作流(ByteArrayInputStream、ByteArrayOutputStream)

 (一)、   public class ByteArrayInputStream extends InputStream;

    
ByteArrayInputSteam:该类是InputStream的子类,它从内存中的字节数组中读取数据,因此它的数据源是一个字节数组。这个类的构造方法包括: 
     ByteArrayInputStream(byte[]
buf)——–参数buf指定字节数组类型的数据源。 
     ByteArrayInputStream(byte[] buf, int offset, int
lenght)—–参数buf指定字节数组类型数据源,参数offset指定从数组中开始读取数据的起始下标位置,lenght指定从数组中读取的字节数。 
    
ByteArrayInputStream类本身采用了适配器设计模式,它把字节数组类型转换为输入流类型,使得程序能够对字节数组进行读操作。 

public static void byteArrTest() throws IOException{
        ByteArrayInputStream bis=new ByteArrayInputStream("abcd".getBytes());
        int len=0;
        while((len=bis.read())!=-1){
            System.out.println((char)len+"<=>"+len);
        }
        bis.close();
    }

(二)、public class ByteArrayOutputStream extends OutputStream。

ByteArrayOutputStream:此类实现了一个输出流,其中的数据被写入一个 byte
数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray()
toString() 获取数据。关闭 ByteArrayOutputStream
无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException

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

    public static void byteArrOut() throws IOException{
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        bos.write(97);
        bos.write(new byte[]{98,99,100});
        //public byte[] toByteArray()创建一个新分配的 byte 数组。其大小是此输出流的当前大小,并且缓冲区的有效内容已复制到该数组中。 
        byte [] bys=bos.toByteArray();
        for(byte b:bys){
            System.out.println(b+"<==>"+(char)b);
        }
    }

2、public String
toString()使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。新
String 的长度是字符集的函数,因此可能不等于缓冲区的大小。

public static void byteArrOut2() throws IOException{
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        bos.write(97);
        bos.write(new byte[]{98,99,100});
        //public String toString()使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。新 String 的长度是字符集的函数,因此可能不等于缓冲区的大小。 
        String str=bos.toString();
        System.out.println(str);//abcd
    }

(三)、ByteArrayInputStream、ByteArrayOutputStream一起使用

public static void byteArrOut() throws IOException{
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        bos.write(97);
        bos.write(new byte[]{98,99,100});
        byte [] bys=bos.toByteArray();
        ByteArrayInputStream bis=new ByteArrayInputStream(bys);
        int len=0;
        while((len=bis.read())!=-1){
            System.out.print((char)len);//abcd
        }
    }

三、标准输入输出流(public final class System) 

System类中的三个成员变量

        //“标准”输入流。此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。 
        public final static InputStream in = null;
        //“标准”输出流。此流已打开并准备接受输出数据。通常,此流对应于显示器输出或者由主机环境或用户指定的另一个输出目标。 
        public final static PrintStream out = null;
        //“标准”错误输出流。此流已打开并准备接受输出数据。 通常,此流对应于显示器输出或者由主机环境或用户指定的另一个输出目标
        public final static PrintStream err = null;

由System.out变量我们可以:

       // 有这里的讲解我们就知道了,这个输出语句其本质是IO流操作,把数据输出到控制台。
        System.out.println("helloworld");
        // 获取标准输出流对象
        PrintStream ps = System.out;
        ps.println("helloworld");

 System.in 标准输入流。是从键盘获取数据的。

获取键盘输入数据的方式:

1、Scanner(JDK5以后的)

Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
int x = sc.nextInt()

2、System.in
System.in返回的类型是InputStream,而它是一个字节流,如果我们以此获取键盘输入的数据每次获取一个字节,输入的数据是我们看不懂的编码数据。所以我们把该流转换为字符流。

private static void systemInTest() throws IOException {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String str=br.readLine();
        System.out.println(str);
    }

* 序列值,用于标记类的唯一性

b) FileOutputStream

FileOutputStream fos = new FileOutputStream("stream.txt");
fos.write("abcde".getBytes());

        input.read(out);

三、标准输入输出流(public final class System) 

System类中的三个成员变量

        //“标准”输入流。此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。 
        public final static InputStream in = null;
        //“标准”输出流。此流已打开并准备接受输出数据。通常,此流对应于显示器输出或者由主机环境或用户指定的另一个输出目标。 
        public final static PrintStream out = null;
        //“标准”错误输出流。此流已打开并准备接受输出数据。 通常,此流对应于显示器输出或者由主机环境或用户指定的另一个输出目标
        public final static PrintStream err = null;

由System.out变量我们可以:

       // 有这里的讲解我们就知道了,这个输出语句其本质是IO流操作,把数据输出到控制台。
        System.out.println("helloworld");
        // 获取标准输出流对象
        PrintStream ps = System.out;
        ps.println("helloworld");

 

IO流 之 其他流,javaio流
一、内存操作流(ByteArrayInputStream、ByteArrayOutputStream) (一)、
public class ByteArrayInputStream extends InputStream; ByteA…

 六、随机访问流(RandomAccessFile)

     public class RandomAccessFile  extends Object  implements
DataOutput, DataInput,
Closeable。该类RandomAccessFile类不属于流,是Object类的子类。  但它融合了InputStream和OutputStream的功能。 支持对文件的随机访问读取和写入。

  够造函数:public
RandomAccessFile(String name, String mode)throws
FileNotFoundException;

    
第一个参数是文件路径,第二个参数是操作文件的模式。模式有四种("r""rw""rws"

"rwd"),我们最常用的一种叫”rw”,这种方式表示我既可以写数据,也可以读取数据

private static void read() throws IOException {
        // 创建随机访问流对象
        RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");

        int i = raf.readInt();
        System.out.println(i);
        // 该文件指针可以通过 getFilePointer方法读取,并通过 seek 方法设置。
        System.out.println("当前文件的指针位置是:" + raf.getFilePointer());

        char ch = raf.readChar();
        System.out.println(ch);
        System.out.println("当前文件的指针位置是:" + raf.getFilePointer());

        String s = raf.readUTF();
        System.out.println(s);
        System.out.println("当前文件的指针位置是:" + raf.getFilePointer());

        // 我不想重头开始了,我就要读取a,怎么办呢?
        raf.seek(4);
        ch = raf.readChar();
        System.out.println(ch);
    }

    private static void write() throws IOException {
        // 创建随机访问流对象
        RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");

        // 怎么玩呢?
        raf.writeInt(100);
        raf.writeChar('a');
        raf.writeUTF("中国");

        raf.close();
    }

 

*/

i) 操作字符数据

CharArrayReader 与 CharArrayWriter

    public static void main(String[] args) throws IOException {

 五、序列化流(ObjectOutputStream)与反序列化流(ObjectInputStream)

1、public class ObjectOutputStream 
extends OutputStream implements ObjectOutput,
ObjectStreamConstants

ObjectOutputStream:把对象按照流一样的方式存入文本文件或者在网络中传输,通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

示例:先构建一个person对象且实现Serializable接口(该接口是标记接口)

public class Person implements Serializable {
    private static final long serialVersionUID = 6722268977065149350L;
    private String name;
    private int age;
    public Person() {
        super();
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
   get() ...
  set()...
}

private static void writer() throws IOException {
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("oos.txt"));
        Person person=new Person("张三",12);
        //public final void writeObject(Object obj)throws IOException
        //将指定的对象写入 ObjectOutputStream。对象的类、类的签名,以及类及其所有超类型的非瞬态和非静态字段的值都将被写入。
        //可以使用 writeObject 和 readObject 方法重写类的默认序列化
        oos.writeObject(person);
        oos.flush();
        oos.close();
    }

oos.txt的内容:
图片 2

 2、反序列化:public class
ObjectInputStream extends InputStream implements ObjectInput,
ObjectStreamConstants。

 ObjectInputStream:把文本文件中的流对象数据或者网络中的流对象数据还原成对象,ObjectInputStream
用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。

    private static void reader() throws IOException, ClassNotFoundException{
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("oos.txt"));
        //public final Object readObject( throws IOException, ClassNotFoundException
        //从 ObjectInputStream 读取对象。对象的类、类的签名和类及所有其超类型的非瞬态和非静态字段的值都将被读取。
        Object obj=ois.readObject();
        System.out.println(obj);
        ois.close();
    }

输出结果:Person [name=张三, age=12]
注意:1、我们在实际开发中,可能还需要使用以前写过的数据,即如果我们更改了person类的内容而oos.txt
没有重新生成,则会出现异常类型id值不一致异常,我们可以在person类中提供一个标识来控制这个问题加入一个属性private
static final long serialVersionUID = 6722268977065149350L;

       
2、如果某个人属性我们不想被序列化可以为该属性添加一个关键字transient,类如:private
transient int age;

}

b) 合并流

SequenceInputStream对多个流进行合并,没有对应输出流的操作,也就是说只有字节输入流。多个源对应一个目的。也就是多个流合并成一个流。 
构造函数:

SequenceInputStream(Enumeration<? extends InputStream> e)
//通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
SequenceInputStream(InputStream s1, InputStream s2)
//通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。

Vector
有特有的枚举迭代器,通过elements()方法返回此向量的组件的枚举。让Enumeration和SequenceInputStream建立关联。

Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("d:\\1.txt"));
v.add(new FileInputStream("d:\\2.txt"));
v.add(new FileInputStream("d:\\3.txt"));
Enumeration<FileInputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("d:\\4.txt");
byte[] buf = new byte[1024];
int len = 0;
while ((len=sis.read(buf))!=-1) {
    fos.write(buf,0,len);
}
fos.close();
sis.close();

File file = new File(“”);

四、合并流 SequenceInputStream   

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

   够造函数一、 public
SequenceInputStream(InputStream s1,  InputStream s2) 

通过记住这两个参数来初始化新创建的
SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取
s2),以提供从此 SequenceInputStream 读取的字节。

     参数:
s1 – 要读取的第一个输入流。

s2 – 要读取的第二个输入流。

 //将 a.txt+b.txt=c.txt(将a、b文件中的内容合并到c中)
    private static void gzOne() throws IOException {
        InputStream s1 = new FileInputStream("a.txt");
        InputStream s2 = new FileInputStream("b.txt");
        SequenceInputStream sis = new SequenceInputStream(s1, s2);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("c.txt"));
        // 如何写读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = sis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }
        bos.close();
        sis.close();
    }

 够造函数二、public
SequenceInputStream(Enumeration<? extends
InputStream> e)

    
通过记住参数来初始化新创建的
SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的
Enumeration 型参数。将按顺序读取由该枚举生成的输入流,以提供从此
SequenceInputStream
读取的字节。在用尽枚举中的每个输入流之后,将通过调用该流的 close
方法将其关闭。

参数:e – 输入流的一个枚举。

 private static void multiInput() throws IOException {
        // 需求:把下面的三个文件的内容复制到d.txt中
        // Enumeration是Vector中的一个方法的返回值类型。
        // Enumeration<E> elements()
        Vector<InputStream> v = new Vector<InputStream>();
        InputStream s1 = new FileInputStream("a.txt");
        InputStream s2 = new FileInputStream("b.txt");
        InputStream s3 = new FileInputStream("c.txt");
        v.add(s1);
        v.add(s2);
        v.add(s3);
        Enumeration<InputStream> en = v.elements();
        SequenceInputStream sis = new SequenceInputStream(en);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d.txt"));
        // 如何写读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = sis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }
        bos.close();
        sis.close();
    }

不需要调用close()方法

g) 操作基本数据类型

DataInputStream 与 DataOutputStream,凡是流操作基本数据类型就用这个。 
构造函数:

  • DataInputStream(InputStream in):传进去一个输入流进行操作。
  • DataOutputStream(OutputStream out):传进去一个输出流进行操作。

方法:常用的操作基本类型方法的规律[write基本类型]和[read基本类型]例:readInt(),writeDouble()。

其中readUTF()方法必须要对应的writeUTF()方法。使用别的方法会出现异常。(字节数不同)

a) 写数据的方法:

public void write() throws Exception {
    String path = this.getClass().getClassLoader().getResource("test.txt").toURI().getPath();
    OutputStream os = new FileOutputStream(path);
    DataOutputStream dos = new DataOutputStream(os);
    dos.writeDouble(Math.random());
    dos.writeBoolean(true);
    dos.writeInt(1000);
    dos.writeInt(2000);
    dos.flush();
    os.close();
    dos.close();
}

b) 读取数据的方法:

public void write() throws Exception {
    String path = this.getClass().getClassLoader().getResource("test.txt").toURI().getPath();
    OutputStream os = new FileOutputStream(path);
    DataOutputStream dos = new DataOutputStream(os);
    dos.writeDouble(Math.random());
    dos.writeBoolean(true);
    dos.writeInt(1000);
    dos.writeInt(2000);
    dos.flush();
    os.close();
    dos.close();
}

输出结果:

1.3042321165175584E-76
true
943011632
842479160

throw new FileNotFoundException();

//创建一个内存输出流,可以通过它向内置的字节数组中写字节

j) 操作字符串

StringReader 与 StringWriter

来源: 

 

判断文件是否存在,是否是一个普通文件

//在这里因为操作的是内存,所以不需要释放存放

a) 打印流

凡是和文件相关的流对象,都是重要的。(打印流这个对象非常重要!)

PrintWriter 与
PrintStream:可以直接操作输出流和文件。该流提供了打印方法,可以将各种数据类型的数据都原样打印。 
字节打印流:PrintStream 
构造函数可以接收的参数类型。

  • file对象(File file)
  • 字符串路径(String path)
  • 字节输出流(OutputStream)

字符打印流:PrintWriter(不管字符还是字节流,它都能打印) 
构造函数可以接收的参数类型。

  • file对象(File file)
  • 字符串路径(String path)
  • 字节输出流(OutputStream)
  • 字符输出流(Writer)
  • PrintWriter(OutputStream out, boolean Flush)://如果为 true,则
    println、printf 或 format 方法将刷新输出缓冲区。
  • PrintWriter(File file, String
    csn)://还能操作文件对象的同时指定字符集。不带自动刷新!

总结:既能操作字符流,也能操作字节流,其中println()能自动换行,构造函数的布尔值可以选择是否自动刷新。 
注意:PrintWriter中自动刷新只是针对流而言,如果是文件则没有这个功能。但是,我们可以将文件封装到流里面,这样也能自动刷新了! 
PrintWriter out = new PrintWriter(new FileWriter(“a.txt”),true);

public static void printTest(){
    BufferedReader bufr;
    PrintWriter out;
    try {
        //键盘录入
        bufr = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out,true);
        String line = null;
        while((line = bufr.readLine())!=null){
            if(line.equals("over"))
                break;
            out.println(line.toUpperCase());
        }
        bufr.close();
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

        buf[2] = 102;

public static void main(String[] args)throws IOException,
ClassNotFoundException {

h) 操作字节数组

ByteArrayInputStream 与 ByteArrayOutputStream

  • 由于该流并未调用底层资源,所以关闭该流是无效的。也不会报IOException异常。
  • 缓冲区会随着数据的不断写入而自动增长。
  • 可使用toByteArray()和toString()获取数据,不用flush()。

构造函数: 
ByteArrayInputStream
:在构造的时候,需要接受数据源,而数据源是一个字节数组。

  • ByteArrayInputStream(byte[] buf)://创建一个
    ByteArrayInputStream,使用 buf 作为其缓冲区数组。
  • ByteArrayInputStream(byte[]
    buf, int offset, int length)://创建
    ByteArrayInputStream,使用 buf 作为其缓冲区数组。

ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装可变长度的数组(目的)

  • ByteArrayOutputStream()://创建一个新的 byte 数组输出流。
  • ByteArrayOutputStream(int size)://创建一个新的 byte
    数组输出流,它具有指定大小的缓冲区容量(以字节为单位)。

void writeTo(OutputStream out)://将此 byte
数组输出流的全部内容写入到指定的输出流参数中,这与使用 out.write(buf, 0,
count)调用该输出流的write方法效果一样。 
注:这个方法很特殊,是数组流中唯一一个会报异常的方法。

public class ByteArrayTester {  
    public static void main(String[] args) throws IOException {  
        byte[] buff = new byte[] { 2, 15, 67, -1, -9, 9 };  
        ByteArrayInputStream in = new ByteArrayInputStream(buff, 1, 4);  
        int data = in.read();  
        while (data != -1) {  
            System.out.println(data + " ");  
            data = in.read();  
        }  
        // ByteArrayInputSystem 的close()方法实际上不执行任何操作 
        in.close(); 
    }  
}  

以上字节数组输入流从字节数组buff的下标为1的元素开始读,一共读取4个元素。对于读到的每一个字节类型的元素,都会转换为int类型。

  字符流:

//准备从这个字节数组中读字节

1.3、其他常用流

  字符流 = 字节流  + 解码

b) 明确数据源和目的地

  • 数据源:

    纯文本:Reader(字符流)
    非纯文本:InputStream(字节流)

  • 数据目的地

    纯文本:Writer(字符流)
    非纯文本:OutputStream(字节流)

}

System.out.println(key+”………..”+value);

a) FileInputStream

int available()://返回写入内容的个数,包含'/r'和'/n'。老师用此方法定义一个刚刚好的字节数组 
FileInputStream fis = new FileInputStream("buf.txt");
byte[] by = new byte[fis.available()]//定义一个大小刚好的数组,这个方法对内存需求过大,慎用。 
//这样就可以避免通过while循环来判断文件内容是否被取完。

注意:字符串转成字节才能被字节流操作,字符串.getBytes();

// 该类包括两个构造方法

}

c) 明确具体设备:

  • 数据源是从哪个设备来的(源设备)

    (1)是硬盘就加FileXXX。
    (2)是键盘用System.in(是一个InputStream对象)。
    (3)是内存就用数组流。 ByteArrayInputStream
    (4)是网络用Socket流。

  • 目的是哪个设备:(目的设备)

    (1)是硬盘就加FileXXX。

    (2)是控制台用System.out(是一个OutoutStream对象)

    (3)是内存就用数组流。 ByteArrayOutputStream

    (4)是网络用Socket流。

 详情参见笔记:IO数据源和数据汇.jpg

int length = -1; //用于保存读取到的字符个数

Student stu =(Student)ois.readObject();

d) 是否需要额外功能:

  • 需要高效,既是否需要使用缓冲区。是就加上Buffred。
  • 需要转换,即是否需要转换流。InputStreamReade和OutputStreamWriter。

//readerTest2(); 

}

a) BufferedInputStream

概念:和 BufferedReader 是一样的。都是装饰模式,对功能增强的缓冲区。 
//它的内部其实就是提供了一个数组。对数据进行临时存储。 
区别:和 BufferedReader 的区别在于没有readLine()方法。

//
该类重写了InputStream中的所有方法,因此我们可以调用其父类同名的方法进行读写操作。

baos.write(66);

1、FileInputStream 和 FileOutputStream

        buf[0] = 100;

//从磁盘上读取对象的数据并生成对象

e) 拓展

  • 当涉及到编码表的转换时,需要用到转换流。

long end = System.currentTimeMillis();

throw
newRuntimeException(“适用用次数已经超过5次上限,请续费!…….”);

c) InputStreamReader 和 OutputStreamWriter(转换流)

InputStreamReader 和 OutputStreamWriter :他们都属于字符流体系中。

它们都是将字节流数据转换成字符流数据进行操作。

注意:由于字节流的缓冲区没有readLine和newLine方法,我们通常会将字节流通过转换流转换成字符流,再通过字符流的缓冲区进行增强操作。

//读取流程
InputStream in = System.in;
InputStreamReader isr = new InputStreamReader(in);
BufferedReader bufr = new BufferedReader(isr);
//这个时候就可以使用字符流的readLine方法了, 这个方法效率高。
//简写格式
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

//输出流程
OutputStream out = System.out;
OutputStreamWriter osw = new OutputStreamWriter(out);
BufferedWriter bufw = new BufferedWriter(osw);
//这个时候就可以使用字符流的newLine方法了,这个方法跨平台。
//简写格式
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

package com.qfedu.c_reader;

对象流读写的对象必须要可序列化,必须实现Serializable接口,这个接口无抽象方法。

b) BufferedOutputStream

概念:和 BufferedWriter 是一样的。都是装饰模式,对功能增强的缓冲区。 
区别:和BufferWriter的区别在于没有newLine()方法。

        // 初始化字节数组

PrintWriter(Stringpath,String
csn)在以第一个参数为路径的文件上建立打印流,字符集由第二个参数指定

f) 随机流

RandomAccessFile 
|–DataInput 
|–DataOutput

  • 随机访问文件,自身具备读写方法。
  • 通过skipBytes(int x),seek(int x)来达到随机访问。

概述:

  • 该类不算是IO体系的子类。(内部封装了流)而是直接继承Object类。
  • 但是它是IO包中的成员,因为它具备读和写的功能。
  • 内部封装了一个数组,而且通过指针对数组中的元素进行操作。
  • 可以通过getFilePointer获取指针位置。同时可以通过seek改变指针的位置。
  • 其实完成读写的原理就是内部封装了字节输入流和字节输出流。

构造方法:

  • andomAccessFile(File file, String mode)//参数是文件和模式。
  • RandomAccessFile(String name, String mode)//参数是指定文件名和模式。

常用模式: 
“r”
不会创建文件,会去读取一个已经存在的文件,如果文件不存在则会出现异常。 
“rw” 操作的文件不存在,会自动创建,如果存在则不会覆盖。 
注:而且该对象的构造函数要操作的文件不存在,会自动创建,如果存在则不会覆盖。

public class TestRandomAccessFile {
    public static void main(String[] args) throws IOException {
        // 写入基本类型double数据
        RandomAccessFile rf = new RandomAccessFile("rtest.dat", "rw");
        for (int i = 0; i < 10; i++) {
            rf.writeDouble(i * 1.414);
        }
        rf.close();

        // 直接将文件指针移到第5个double数据后面,然后覆盖第6个数据
        rf = new RandomAccessFile("rtest.dat", "rw");
        rf.seek(5 * 8);    
        rf.writeDouble(47.0001);    
        rf.close();
        rf = new RandomAccessFile("rtest.dat", "r");
        for (int i = 0; i < 10; i++) {
            System.out.println("Value " + i + ": " + rf.readDouble());
        }
        rf.close();
    }
}

具体参考:

  FileInputStream

byte[]array=baos.toByteArray();   //获取字节数组

e) 管道流

PipedInputStream 和
PipedOutputStream输入和输出可以直接进行连接,通过结合线程使用。

管道流,用于线程间的通信。一个线程的PipedInputStream对象从另外一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。
管道流和读写流的区别

  • 普通的读写流,是通过读取流,将数据存进一个数组,再对数组进行操作。
  • 管道流则不同,它是让读写操作进行对接,类似于对接成一个管道。
  • 由于管道流不能分别是读还是写的操作,所以不能用单线程。
  • 根据以上特点,管道流是通过两个线程对读写进行分开操作。

小知识:集合中涉及到IO流的是Properties,IO流涉及到多线程的是管道流。 
两种连接方式:

  • 创建构造函数的时候,将对应的流传进去即可.
  • 如果是空构造函数,则通过connect(流)方法连接。

模拟流水线生产产品的同时,进行消费:

a) 生产产品的类

// 生产产品
public class Producer extends Thread {
    private PipedOutputStream pos;
    public Producer(PipedOutputStream pos) {
        this.pos = pos;
    }

    @Override
    public void run() {
        super.run();
        try {
            pos.write("Hello".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

b) 生产同时进行消费

// 消费者
public class Consumer extends Thread {
    private PipedInputStream pis;

    public Consumer(PipedInputStream pis) {
        this.pis = pis;
    }

    @Override
    public void run() {
        super.run();
        byte[] b = new byte[100]; // 将数据保存在byte数组中
        try {
            int len = pis.read(b); // 从数组中得到实际大小。
            System.out.println(new String(b, 0, len));
            pis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

c) 测试,此时生产的产品会在第一时间消费掉,所以管道流可以用来进程通信。

public class PipedStreamTest {
    public static void main(String[] args) {
        PipedOutputStream pos = new PipedOutputStream();
        PipedInputStream pis = new PipedInputStream();
        try {
            pos.connect(pis);// 连接管道
            new Producer(pos).start();// 启动线程
            new Consumer(pis).start();// 启动线程
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//

System.out.println(“程序正常运行…….”);

2、 BuferedInputStream 和 BufferedOutputStream

// ByteArrayInputStream(byte[] buf,int offset,int length );

baos.write(buf,0,n);   //没有读完就将有效字节写到内存输出流

c) 分割流

//分割文件
public static void splitFile() throws IOException{
    FileInputStream fis = new FileInputStream("d:\\1.jpg");
    FileOutputStream fos = null;
    byte[] buf = new byte[1024*1024];
    int len = 0;
    //定义一个变量来让文件名变化
    int count = 1;
    //每次创建一个新流,所以每次都要关闭。
    while((len=fis.read(buf))!=-1){
        fos = new FileOutputStream("d:\\split\\"+(count++)+".part");
        fos.write(buf,0,len);
        fos.close();
    }
    fis.close();
}
//合并文件
public static void merge() throws IOException{
    ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
    for(int x=1;x<=3;x++){
        al.add(new FileInputStream("d:\\split\\"+x+".part"));
    }
        //由于ArrayList没有枚举,但是迭代器有枚举,匿名内部类访问局部变量必须final修饰。
    final Iterator<FileInputStream> it = al.iterator();
    Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){
    public boolean hasMoreElements(){
            return it.hasNext();
    }
    public FileInputStream nextElement(){
        return it.next();
    }
        };
    SequenceInputStream sis = new SequenceInputStream(en);
    FileOutputStream fos = new FileOutputStream("d:\\split\\0.jpg");
    byte[] buf = new byte[1024];
    int len = 0;
    while((len=sis.read(buf))!=-1){
        fos.write(buf,0,len);
    }
    fos.close();
    sis.close();                                        
}

  IO input Output

//把内存中的内容拷贝到文件,重复进行

a) 体系:明确数据的来源和数据将要到达的目的地。

  • 字节输入流:(InputStream)
  • 字节输出流:(OutputStream)
  • 字符输入流:(Reader)
  • 字符输出流:(Writer)

        byte[] out = new byte[3];

fos.close();

d) 对象序列化

ObjectInputStream和ObjectOutputStream可以将对象进行持久化存储和读取。

  • 被操作的对象需要实现 Serializable以启用其序列化功能。
  • Serializable是没有方法的接口(标记接口)。
  • ObjectInputStream和ObjectOutputStream必须成对使用。
  • 被序列化的类中静态成员是不能被序列化的,只有堆内存中的成员才能被序列化。
  • 不想对非静态变量进行序列化,可以使用transient修饰符修饰。(保证在值在堆内存存在,而不存在文件中)

自定义序列号UID: 
UID其实是根据类中的成员算出来的,当我们修改了被序列化的类的源代码的时候,会产生一个新的class文件, 
这样我们就不能再通过操作对象的流进行读取了,为了保证UID的一致性,我们可以自定义序列化UID号。

static final long serialVersionUID = 42L;//自定义序列化UID号。返回任意类型。

常用方法:

(1)Object readObject():从 ObjectInputStream 读取对象。
(2)void writeObject(Object obj):将指定的对象写入 ObjectOutputStream。

了解:当存储多个对象时,我们可以多次用readObject按存储先后顺序将其读出来。

class Person implements Serializable{
    String name;
    int age;
    Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    public String toString(){
        return name + ":" + age;
    }
}
class ObjectStreamDemo{
    public static void main(String[] args) throws Exception{
        //writeObj();
        readObj();
    }
    //读取文件
    public static void readObj() throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
        Person p = (Person)ois.readObject();
        System.out.println(p);
    }
    //持久化存储,写文件
    public static void writeObj() throws IOException{
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
        oos.writeObject(new Person("lisi",39));
        oos.close();
    }
}

  ——| FileReader 读取文件的输入字符流

println()打印并且换行,在autoFlush为true时,会自动刷缓存

// 2. 建立FileReder 输入字符流管道

ObjectOutputStream oos = newObjectOutputStream(fos);

        ByteArrayInputStream input = new ByteArrayInputStream(buf);

* 官方建议使用setProperty()方法添加键值对

//3.建立缓冲区,利用缓冲区读取数据, 创建字符数组作为缓冲区

}

long start = System.currentTimeMillis();

try {

  字节流:

//要保证文件存在

     
在读写文件需要对内容按行处理,比如比较特定字符,处理某一行数据的时候一般会选择字符流。只是读写文件,和文件内容无关的,一般选择字节流。

bais.read(cubf);

        System.out.println(new String(out));

FileInputStream fis = new FileInputStream(“data.txt”);

System.out.println(“耗时:” + (end – start));

//当数组输出流被创建的时候内部会自动创建一个数组

}

//读取数据

     
以stream结尾都是字节流,以reader和writer结尾都是字符流,两者的区别就是读写的时候一个是按字节读写,一个是按字符。在实际使用时差不多。

继承自Hashtable类,所以是一个Map集合,具有Map接口中的所有方法,但是在保存和读取数据的时候不建议使用put和get方法,因为有可能会出现异常,建议使用Properties中特有的方法进行数据的存储

        buf[1] = 101;

System.out.println((char)b);

}

System.out.println(prop2);

  1. 建立FileReader读取通道

  2. 读取数据

  3. 关闭资源

byte[] buf = new byte[1024];

import java.io.FileNotFoundException;

baos.write(67);

  —| Reader 输入字符流的基类/超类  抽象类

getProperty(String
key):通过键获取值《
getProperty(Stringkey)

package input;

if(fis != null){

}

FileInputStream fis = newFileInputStream(“objdemo.object”);

public static void main(String[] args) throws IOException {

DataInputStream(InputStreamis)构造方法参数为它所装饰的字节输入流,添加了读基本数据类型的功能

FileReader fr = new FileReader(file);

ByteArrayInputStreambais = new ByteArrayInputStream(array);

    }

注意事项:

// 判断文件是否存在,是否是一个普通文件

for(int i=1;i<=100;i++){

// 输入字节流InputStream的实现

构造方法:

public static void readerTest2() throws IOException {

System.out.println(raf.read());

// 字节数组作为输入源——ByteArrayInputStream

实例:写一个程序,要求用户只能打开5次,在第6次打开的时候就抛出异常提示“打开失败”

}

byte[] array =baos.toByteArray();

        byte[] buf = new byte[3];

ByteArrayOutputStream()创建一个内存输出流,无参数,可以往内置的字节数组中写字节

import java.io.ByteArrayInputStream;

}

}

//               prop.put(“textsize”,18);

        input.close();

}

// 1. 找到文件:

int count=Integer.parseInt(prop.getProperty(“count”,”0″));

char[] buffer = new char[1024];

pw.println(“1000phone”);//打印1000phone到文件中并换行

import java.io.IOException;

System.out.println(dis.readFloat());

System.out.println(new String(buffer, 0, length));

newObjectInputStream(new FileInputStream(“g:/obj”));

/*

import java.io.File;

dos.writeInt(66);

*/

}

  1. 找到文件

Set     keyset = prop2.stringPropertyNames();

//
下面是如何通过一个字节数组创建字节输入流的过程,并从输入流中读取数据输出到操作台。

*
思路:记录用户打开程序的次数,每次打开的时候都记一次,将次数保存在配置文件中,

        // 创建输入流

File file = newFile(“prop_ex.properties”);

public class Demo1 {

writeXXX(xxx i)

while ((length = fr.read(buffer)) != -1) {

//

store():将数据通过输出流写到指定文件中

使用方式:

ByteArrayInputStream

  InputStream

//内部自动进行了反序列化

//        
只能读取指定的字节数,不能读取的数据过多,有可能会超过内存的限制

getProperty(Stringkey,StringdefaultValue)》如果键不存在返回默认值

// ByteArrayInputStream(byte[] buf);

import java.io.FileReader;

*
但是Properties类中的数据要求应该都是String类型,使用put方法返回可能会出问题

import java.io.IOException;

pw.println(“Android”);//打印android到文件中并换行

  字符流读取数据,输入字符流

Properties prop2 = newProperties();

//4. 关闭资源

int n=0;

//

oos.close();

        // 从输入流中读取数据

/*ps.print(true);

fr.close();

//字节数组输出流

if (!file.exists() || !file.isFile()) {

ByteArrayInputStream bais =new ByteArrayInputStream(buf);

        // 关闭输入流

byte[] buf = new byte[4];

  OutputStream

对象流读写,写的和读的类型一定要一致。

check();

FileOutputStream fos = newFileOutputStream(“data.txt”);

}

this.name = name;

ois.close();

//每次从文件读4个字节方法缓冲中,有效字节数赋给n,和-1比较判断是否读完

}

System.out.println(dis.readInt());

public Student(String name, Stringgender, int age) {

FileInputStream fis =null;

对象流

//               prop.save(out, comments);

/*