Java基础知识IO流(其他类)

IO包中的其他类

  • 打印流 PrintWriter与PrintStream
  • 序列流 SequenceInputStream
  • 切割文件
  • 操作对象 ObjectInputStream与ObjectOutputStream
  • 管道流 PipedInputStream和PipedOutputStream
  • RandomAccessFile类 (随机访问文件)
  • 操作基本数据类型 DataInputStream和DataOutputStream类
  • 操作数组的流

    ByteArrayInputStream/ByteArrayOutputStream/CharArrayReader/CharArrayWriter/StringReader/StringWriter

打印流

该流提供了打印方法,可以将各种数据类型的数据原样打印。

PrintStream字节打印流

构造时可以直接操作文件file,能够直接操作file的类都很重要。

构造函数可以接收的参数类型:

1,file对象。File

2,字符串路径。String

3,字节输出流。OutputStream

构造方法摘要

PrintStream(File file)

创建具有指定文件且不带自动行刷新的新打印流。

PrintStream(File file, String csn)

创建具有指定文件名称和字符集且不带自动行刷新的新打印流。

PrintStream(OutputStream out)

创建新的打印流。

PrintStream(OutputStream out, boolean autoFlush)

创建新的打印流。

autoFlush - boolean 变量;如果为 true,则每当写入 byte 数组、调用其中一个 println 方法或写入换行符或字节 (‘\n’) 时都会刷新输出缓冲区

PrintStream(OutputStream out, boolean autoFlush, String encoding)

创建新的打印流。

PrintStream(String fileName)

创建具有指定文件名称且不带自动行刷新的新打印流。

PrintStream(String fileName, String csn)

创建具有指定文件名称和字符集且不带自动行刷新的新打印流。

PrintWriter

构造函数可以接收的参数类型:

1,file对象。File

2,字符串路径。String

3,字节输出流。OutputStream

4,字符输出流,Writer。

构造方法摘要

PrintWriter(File file)

使用指定文件创建不具有自动行刷新的新 PrintWriter。

PrintWriter(File file, String csn)

创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。

PrintWriter(OutputStream out)

根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。

PrintWriter(OutputStream out, boolean autoFlush)

通过现有的 OutputStream 创建新的 PrintWriter。

autoFlush - boolean 变量;如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区

PrintWriter(String fileName)

创建具有指定文件名称且不带自动行刷新的新 PrintWriter。

PrintWriter(String fileName, String csn)

创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。

PrintWriter(Writer out)

创建不带自动行刷新的新 PrintWriter。

PrintWriter(Writer out, boolean autoFlush)

创建新 PrintWriter。

import java.io.*;

class  PrintStreamDemo
{
    public static void main(String[] args) throws IOException
    {
        BufferedReader bufr =
            new BufferedReader(new InputStreamReader(System.in));

        PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);

        String line = null;

        while((line=bufr.readLine())!=null)
        {
            if("over".equals(line))
                break;
            //直接换行且刷新缓存区
            out.println(line.toUpperCase());
            //out.flush();
        }

        out.close();
        bufr.close();

    }
}

SequenceInputStream类

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

构造方法摘要

SequenceInputStream(Enumeration

import java.io.*;
import java.util.*;

class  PrintStreamDemo
{
    public static void main(String[] args) throws IOException
    {
        Vector<FileInputStream> fiss=new Vector<FileInputStream>();
        fiss.add(new FileInputStream("1.txt"));
        fiss.add(new FileInputStream("2.txt"));
        fiss.add(new FileInputStream("3.txt"));

        Enumeration<FileInputStream> elements=fiss.elements();
        SequenceInputStream sis=new SequenceInputStream(elements);

        FileOutputStream fos=new FileOutputStream("4.txt");
        byte[] arr=new byte[1024];
        int length=0;
        while((length=sis.read(arr))!=-1)
        {
            fos.write(arr);
        }

        sis.close();
        fos.close();
    }
}

切割文件

将一个文件按照一定大小切割成几个文件。也就是一个InputStream对应多个OutputStream。

import java.io.*;

class SplitDemo
{
    public static void main(String[] args) throws IOException
    {
        FileInputStream fis=new FileInputStream("4.txt");
        byte[] arr=new byte[1024];
        int len=0;
        int count=1;
        while((len=fis.read(arr))!=-1)
        {

            FileOutputStream fos=new FileOutputStream((count++)+".txt");
            fos.write(arr,0,len);
            fos.close();

        }

         fis.close();

    }
}

操作对象

ObjectInputStream和ObjectOutputStream是可以直接操作对象的流。

意义:将堆内存的对象存储到硬盘上,对象封装的数据也随之存储到硬盘上,方便程序运行完之后再次得知对象的数据。将对象存放在硬盘上是对象的持久化存储。

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。

构造方法:

ObjectOutputStream(OutputStream out)

创建写入指定 OutputStream 的 ObjectOutputStream。

关键方法:

void writeObject(Object obj)

将指定的对象写入 ObjectOutputStream。

序列化是什么意思?

一个类想要序列化,需要实现Serializable接口。Serializable接口没有方法,没有方法的接口属于标记接口,实现该接口的类表示具备被序列化的资格。相当于猪肉只有盖了合格戳才能具备在市场上卖的资格。

序列化的原理是什么?

实际上,Serializable接口给实现它的类加了一个serialVersionUID,类在被序列化时希望有个Id标识,给编译器使用。假如一个序列化的类创建了一个对象,该对象被持久化保存带硬盘上了,然后这个类进行了修改,重新编译之后序列号发生变化,此时编译器取回硬盘上的对象时,由于序列号不同,断定为不同的类的对象。

UID实际上根据类中的成员变量算出来的,如果多次修改之后,成员变量不变,那么序列号不变。

UID可以自定义,不让java自动生成。

只能将堆内的对象序列化,不能将静态变量序列化。如果对非静态的成员也不想序列化的话,可以在变量前加上关键字 transient

import java.io.*;
class Person implements Serializable
{
    //自己确定类的UID
    public static final long serialVersionUID = 42L;

    private String name;
    transient int age;
    static String country = "cn";
    Person(String name,int age,String country)
    {
        this.name = name;
        this.age = age;
        this.country = country;
    }
    public String toString()
    {
        return name+":"+age+":"+country;
    }
}
import java.io.*;

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);
        ois.close();
    }

    public static void writeObj()throws IOException
    {
        ObjectOutputStream oos =
            new ObjectOutputStream(new FileOutputStream("obj.txt"));

        oos.writeObject(new Person("lisi0",399,"kr"));

        oos.close();
    }
}

管道流

通常输入流和输出流之间没有直接的关系,若想有关系需要一个数组作为一个中转站。而管道流可以将输入流和输出流对接到一起。问题是,输入流和输出流哪个先执行呢?

PipedInputStream

管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。(一个线程的话,假如没有数据时,PipedInputStream就开始读数据,那么进入等待,造成堵塞)

集合中涉及到IO流的是Properties,在IO流中涉及到多线程的是管道流

管道输入流和管道输出流如何连接到一起呢? 构造方法!或connect()方法。

PipedInputStream(PipedOutputStream src)

创建 PipedInputStream,使其连接到管道输出流 src。

示例:

import java.io.*;

class PipedStreamDemo
{
    public static void main(String[] args) throws IOException
    {
        PipedInputStream in=new PipedInputStream();
        PipedOutputStream out=new PipedOutputStream();
        in.connect(out);

        new Thread(new Read(in)).start();
        new Thread(new Write(out)).start();
    }
}

class Read implements Runnable
{
    private PipedInputStream in;
    Read(PipedInputStream in)
    {
        this.in=in;
    }
    public void run()
    {
        try
        {

            byte[] arr=new byte[1024];
            System.out.println("读之前");
            int len=in.read(arr);
            System.out.println("读之后");
            System.out.println( new String(arr,0,len));
        }
        catch (IOException e)
        {
            throw new RuntimeException("读失败");
        }
        finally
        {
            try
            {
                if(in!=null)
                    in.close();
            }
            catch (IOException e)
            {
                throw new RuntimeException("读失败");
            }
        }
    }

}

class Write implements Runnable
{
    private PipedOutputStream out;
    Write(PipedOutputStream out)
    {
        this.out=out;
    }
    public void run()
    {
        try
        {
            System.out.println("写之前");
            out.write("hahaha".getBytes());
            System.out.println("写之后");

        }
        catch (IOException e)
        {
            throw new RuntimeException("写失败");
        }
        finally
        {
            try
            {
                if(out!=null)
                    out.close();
            }
            catch (IOException e)
            {
               throw new RuntimeException("写失败");
            }
        }

    }

}

RandomAccessFile类

此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。

构造方法摘要

RandomAccessFile(File file, String mode)

创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。

RandomAccessFile(String name, String mode)

创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。

该类不是算是IO体系中子类。

而是直接继承自Object。

但是它是IO包中成员。因为它具备读和写功能。

内部封装了一个数组,而且通过指针对数组的元素进行操作。

可以通过getFilePointer获取指针位置,

同时可以通过seek改变指针的位置。

其实完成读写的原理就是内部封装了字节输入流和输出流。

通过构造函数可以看出,该类只能操作文件

而且操作文件还有模式:只读r,,读写rw等。

如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。

如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。

特点:

1.通过seek(int n )方法改变指针的位置。读写指定位置。

2.skipBytes(int n)跳过n个字节,只能往前跳,不能往回跳。

3.可以直接读取和写入基本数据类型。如writeInt(int v),readInt()等。

4. 不用按顺序读写,可以在任意位置进行读写和修改,可以存在空格。这样有什么好处呢? 可以将文件的内容分段,用多个线程分别负责每个段的操作,这就是下载软件的原理,这样会提高效率。

示例:

import java.io.*;
class RandomAccessFileDemo
{
    public static void main(String[] args) throws IOException
    {
        write();
        read();
    }
    public static void write()throws IOException
    {
        RandomAccessFile raf=new RandomAccessFile("rafDemo.txt","rw");
        raf.write("马闪闪".getBytes());
        raf.writeInt(25);

        raf.seek(11);
        raf.write("赵根源".getBytes());
        raf.writeInt(24);

        raf.close();
    }
    public static void read() throws IOException
    {
        RandomAccessFile raf=new RandomAccessFile("rafDemo.txt","rw");
        byte[] buf=new byte[6];
        int len=raf.read(buf);
        System.out.println(new String(buf,0,len));
        System.out.println(raf.readInt());

        raf.skipBytes(1);
        byte[] buf2=new byte[6];
        int len2=raf.read(buf2);
        System.out.println(new String(buf2,0,len2));
        System.out.println(raf.readInt());

        raf.seek(0);
        byte[] buf3=new byte[6];
        int len3=raf.read(buf3);
        System.out.println(new String(buf3,0,len3));
        System.out.println(raf.readInt());
        raf.close();
    }
}

操作基本数据类型 DataInputStream和DataOutputStream类

DataOutputStream

数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。

writeUTF(String str): 以与机器无关方式使用 UTF-8 修改版编码将一个字符串写入基础输出流。

DataInputStream

数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。

import java.io.*;

class DataStreamDemo
{
    public static void main(String[] args)  throws IOException
    {
        write();
        read();
    }

    public static void write() throws IOException
    {
        DataOutputStream dos=new DataOutputStream(new FileOutputStream("dosDemo.txt") );
        dos.writeInt(255);
        dos.writeBoolean(true);
        dos.writeDouble(8998.655);
        dos.close();
    }
    public static void read() throws IOException
    {
        DataInputStream dis=new DataInputStream(new FileInputStream("dosDemo.txt") );
        int a=dis.readInt();
        boolean b=dis.readBoolean();
        double c=dis.readDouble();
        System.out.println(String.valueOf(a)+String.valueOf(b)+String.valueOf(c));
        dis.close();
    }

}

操作数组的流

ByteArrayInputStream和ByteArrayOutoutStream

用于操作字节数组的流对象。我们知道InputStream和OutputStream都可以对字节数组进行操作,这二者有什么区别呢?

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

ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。这就是数据目的地。

因为这两个流对象都操作的数组,并没有使用系统资源。

所以,不用进行close关闭,也不会产生IOException异常。

只有一个方法会有IOException,那就是writeTo(OutputStream out)方法。

在流操作规律讲解时:

源设备有,

键盘 System.in,硬盘 FileStream,内存 ArrayStream

目的设备有:

控制台 System.out,硬盘FileStream,内存 ArrayStream。

操作数组的流就是用流的读写思想来操作数据。

CharArrayReader和CharArrayWriter以及StringReader和StringWriter都是同样的道理。

示例:

import java.io.*;

class ArrayStreamDemo
{
    public static void main(String[] args) throws IOException
    {
        byteArrayStreamTest();
        CharArrayTest();
        StringTest();
    }

    public static void byteArrayStreamTest()
    {
        ByteArrayInputStream bis=new ByteArrayInputStream("abcdefghijklmnopqrstuvwxyz".getBytes());
        ByteArrayOutputStream bos=new ByteArrayOutputStream();

        int b=0;
        while((b=bis.read())!=-1)
        {
            bos.write(b);
        }

        System.out.println(bos.toString());
    }

    public static void CharArrayTest() throws IOException
    {
        CharArrayReader car=new CharArrayReader("wo shi yi ge da huai dan".toCharArray());
        CharArrayWriter caw=new CharArrayWriter();

        int b=0;
        while((b=car.read())!=-1)
        {
            caw.write(b);
        }

        System.out.println(caw.toString());
    }

    public static void StringTest() throws IOException
    {
        StringReader sr=new StringReader("ha ha ha ha ha");
        StringWriter sw=new StringWriter();

        int b=0;
        while((b=sr.read())!=-1)
        {
            sw.write(b);
        }

        System.out.println(sw);
    }
}

时间: 2024-08-08 23:30:28

Java基础知识IO流(其他类)的相关文章

Java基础知识IO流(练习)

练习: 要求:有五个学生,每个学生有3门课的成绩, 从键盘输入以上数据(包括姓名,三门课成绩), 输入的格式:如:zhagnsan,30,40,60计算出总成绩, 并把学生的信息和计算出的总分数高低顺序存放在磁盘文件"stud.txt"中. 1,描述学生对象. 2,定义一个可操作学生对象的工具类. 思想: 1,通过获取键盘录入一行数据,并将该行中的信息取出封装成学生对象. 2,因为学生有很多,那么就需要存储,使用到集合.因为要对学生的总分排序. 所以可以使用TreeSet. 3,将集合

java基础知识回顾之javaIO类--管道流PipedOutputStream和PipedIutputStream

管道流(线程通信流):管道流的主要作用是可以进行两个线程间的通讯,分为管道输出流(PipedOutputStream).管道输入流(PipedInputStream),如果想要进行管道输出,则必须要把输出流连在输入流之上.如图所示: 1.管道输入流应该连接到管道输出流 ,输入流和输出流可以直接连接       2.使用多线程操作,结合线程进行操作.通常由某个线程从管道输入流中(PipedInputStream)对象读取.          并由其他线程将其写入到相应的端到输出流中.不能使用单线程

java基础知识回顾之javaIO类--内存操作流ByteArrayInputStream和ByteArrayOutputSteam(操作字节数组)

直接看代码: package cn.itcast.io.p6.bytestream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class ByteArrayStreamDemo { /** * @param args * @throws IOException * 特点 * 1.内存操作流 * 2.不操作底层资源,不调

java基础知识回顾之javaIO类--RandomAccessFile类

java.io 类 RandomAccessFile java.lang.Object java.io.RandomAccessFile1.该类不是IO流中的子类.2.该类既能读又能写.3.该对象内部分装了一个字节数组,通过指针可以操作数组中的元素.4.其实该对象就是将字节输入流和输出流进行了封装.5.该对象只能对文件操作,目的和源只能是文件对象.通过看构造方法可以看得出来.RandomAccessFile(File file, String mode) RandomAccessFile(Str

java基础知识回顾之javaIO类--File类应用:获取指定目录下面的指定扩展名的文件,将文件的绝对路径写入到目的文件当中

/** * File文件综合应用 * 需求:获取指定目录下面,指定扩展名的文件,将文件的绝对路径写到文本文件当中. *  * 思路:1.需要深度遍历.--递归 * 2.遍历的过程中过滤指定扩展名的文件--过滤器FileNameFilter,将文件存入容器中 * 3.将容器中的内容遍历,写入到指定文件中 * */ 代码:  FilenameFilter 过滤器: package com.lp.ecjtu.File.filter; import java.io.File; import java.i

java基础知识回顾之javaIO类--File类应用:递归深度遍历文件

代码如下: package com.lp.ecjtu.File.FileDeepList; import java.io.File; public class FileDeepList { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub File dir = new File("E:"+File.separator+"demodir

java基础知识回顾之javaIO类--File类应用:过滤器接口FilenameFilter和FileFilter

FilenameFilter和FileFilter都是用来过滤文件,例如过滤,以.jpg或者.java结尾的文件,通过看他们的源码:通过使用File类中String[] list(FilenameFilter filter)或者public File[] listFiles(FileFilter filter)方法,把FilenameFilter或者FileFilter接口对象作为参数传入,通过实现接口里面的 boolean accept(File dir, String name) 或者boo

java基础知识回顾之javaIO类--File类

File类是对文件系统中文件以及目录(文件夹)进行封装的对象,可以通过面向对象的思想来操作文件和目录(文件夹).File类保存文件或目录的各种元素的信息,包括文件名,文件长度,最后修改日期,是否可读,获取当前文件的路径名,判断指定文件是否存在,获得当前文件的列表,创建.删除文件目录等方法. /**     * 构造方法:File f = new File("file.txt");//file.txt 相对路径     *       File f1 = new File("c

java基础篇IO流的规律

前两篇降了IO流中的字节流和字符流复制的例子,今天来总结一下IO流的规律 掌握好IO流的规律,再开发中会很好用 下面来总结一下: 1,明确源和目的 源:输入流 InputStream 和Reader 目的:输出流 OutputStream 和Writer 2,操作的数据是否是纯文本. 是:使用字符流 不是:使用字节流 3,当体系明确后,在明确要使用哪个具体的对象,通过设备来进行区分 源设备: 内存,硬盘,键盘 目的设备: 内存,硬盘,控制台 这里的源就是你想进行的操作,比如说你想从c盘复制一个文