IO流笔记二

IO包中的其他类

打印流
PrintWriter与PrintStream:可以直接操作输入流和文件。
PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式与其他输出流不同,PrintStream永远不会抛出IOException。
PrintStream打印的所有字符都使用平台的默认字符编码转换为字节。
在需要写入字符而不是写入字节的情况下,应该使用PrintWriter类

PrintStream:
1. 提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式
2. 它不抛IOException

构造函数,接收三种类型的值:
                                                             1. 字符串路径   2. File对象   3. 字节输出流

public static void main(String[] args) throws Exception {
    PrintStream out = new PrintStream("print.txt" );
    //write(int b)方法只写最低8位
    out.write(97); //a
    //print方法将97先变成字符串保持原样将数据打印到目的地
    out.print(97); //97
    out.close();
}

PrintWriter:字符打印流
构造函数参数:
1. 字符串路径
2. File对象
3. 字节输出流
4. 字符输出流

public static void main(String[] args) throws IOException {
    BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter out = new PrintWriter(System.out);
    String line = null;
    while((line = bufr.readLine()) != null){
        if("over" .equals(line))
            break;
            out.println(line.toUpperCase());
            out.flush();
        }
    out.close();
    bufr.close();
}

public static void main(String[] args) throws IOException {
    BufferedReader bufr = new BufferedReader(new
    InputStreamReader(System.in));
    //PrintWriter构造函数的第二个参数设置为true,表示自动刷新
    PrintWriter out = new PrintWriter(new FileWriter("out.txt"),true);
    String line = null;
    while((line = bufr.readLine()) != null){
        if("over" .equals(line))
        break;
        out.println(line.toUpperCase());
    }
    out.close();
    bufr.close();
}

序列流

SequenceInputStream:对多个流进行合并。

public static void main(String[] args) throws Exception {
    Vector<FileInputStream> v = new Vector<FileInputStream>();
    v.add( new FileInputStream("1.txt" ));
    v.add( new FileInputStream("2.txt" ));
    v.add( new FileInputStream("3.txt" ));
    Enumeration<FileInputStream> en = v.elements();
    SequenceInputStream sis = new SequenceInputStream(en);
    FileOutputStream fos = new FileOutputStream("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();
}

将1.txt、2.txt、3.txt文件中的数据合并到4.txt中。使用ArrayList比Vector效率更高。

public static void main(String[] args) throws Exception {
    ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
    for(int x = 1; x <= 3; x++){
        al.add( new FileInputStream(x + ".txt" ));
    }
    final Iterator<FileInputStream> it = al.iterator();
    Enumeration<FileInputStream> en = Collections.enumeration(al);
    /*
    //Collections工具类的enumeration方法核心代码:
    Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){
        public boolean hasMoreElements(){
        return it.hasMoreElements();
        }
        public FileInputStream nextElement(){
            return it.next();
        }
    };*/

    SequenceInputStream sis = new SequenceInputStream(en);
    FileOutputStream fos = new FileOutputStream("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();
}

文件切割器

public static void main(String[] args) throws IOException
    File file = new File("0.mp3" );
    splitFile(file);
    }
public static void splitFile(File file) throws IOException {
    //用读取流关联源文件
    FileInputStream fis = new FileInputStream(file);
    //定义一个1M的缓冲区
    byte[] buf = new byte[SIZE];
    //创建目的
    FileOutputStream fos = null;
    int len = 0;
    int count = 1;
    //切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数,以方便于合并。
    //这个信息为了进行描述,使用键值对的方式,用到了properties对象。
    Properties prop = new Properties();
    File dir = new File("c:\\partFiles" );
    if(!dir.exists())
        dir.mkdirs();
    while((len = fis.read(buf)) != -1){
        fos = new FileOutputStream(new File(dir,(count++) +".part"));
        fos.write(buf,0,len);
        fos.close();
    }
    //将被切割文件的信息保存到prop集合中
    prop.setProperty( "partcount",count + "" );
    prop.setProperty( "filename",file.getName());
    fos = new FileOutputStream(new File(dir,count + ".properties" ));
    //将prop集合中的数据存储到文件中
    prop.store(fos, "save file info");
    fis.close();
    fos.close();
}

文件合并器

public static void main(String[] args) throws IOException {
    File dir = new File("c:\\partFiles" );
    mergeFile(dir);
}
public static void mergeFile(File dir) throws IOException {
    //获取指定目录下的配置文件对象
    File[] files = dir.listFiles( new SuffixFilter(".properties" ));
    if(files.length!=1)
        throw new RuntimeException(dir + ",该目录下没有properties扩展名的文件或者不唯一" );
    //记录配置文件对象
    File confile = files[0];
    //获取该文件中的信息
    Properties prop = new Properties();
    FileInputStream fis = new FileInputStream(confile);
    prop.load(fis);
    String filename = prop.getProperty( "filename");
    int count = Integer.parseInt(prop.getProperty("partcount"));
    //获取该目录下的所有碎片文件
    File[] partFiles = dir.listFiles( new SuffixFilter(".part" ));
    if(partFiles.length != (count - 1)){
        throw new RuntimeException("碎片文件不符合要求,个数不对!应是" + count + "个");
    }
    //将碎片文件和流对象关联并存储到集合中
    ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
    for(int x = 1; x <= partFiles.length; x++){
        al.add( new FileInputStream(partFiles[x-1]));
    }
    final Iterator<FileInputStream> it = al.iterator()
    //将多个流合并成一个序列流
    Enumeration<FileInputStream> en = Collections.enumeration(al);
    SequenceInputStream sis = new SequenceInputStream(en);
    FileOutputStream fos = new FileOutputStream(new  File(dir,filename));
    byte[] buf = new byte[1024*1024];
    int len = 0;
    while((len = sis.read(buf)) != -1){
        fos.write(buf,0,len);
    }
    fos.close();
    sis.close();
}

class SuffixFilter implements FilenameFilter{
    private String suffix;
    public SuffixFilter(String suffix){
        super();
        this.suffix = suffix;
    }
    public boolean accept(File dir,String name){
        return name.endsWith(suffix);
    }
}

操作对象

ObjectInputStream与ObjectOutputStream
P.S.
被操作的对象需要实现Serializable。
类通过实现java.io.Serializable接口以启用序列化功能,Serializable只是一个标记接口

public class ObjectStreamDemo{
    public static void main(String[] args) throws Exception {
        readObj();
    }
    public static void readObj() throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new
        FileInputStream("obj.object" ));
        Person p = (Person)ois.readObject();
        System.out.println(p.getName() + ":" + p.getAge());
        ois.close();
    }
}

如果修改Person类中属性的修饰符为public,就会报如下异常

writeObject方法不能写入类及其所有超类型的瞬态和静态字段的值。

RandomAccessFile

随机访问文件,自身具备读写的方法。
通过skipBytes(int x),seek(int x)等方法来达到随机访问。
特点:
1. 该对象即能读,又能写
2. 该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素
3. 可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置。
4. 其实该对象就是将字节输入流和输出流进行了封装。
5. 该对象的源或者目的只能是文件。通过构造函数就可以看出。

RandomAccessFile不是io体系中的子类。

public static void main(String[] args) throws IOException {
    writeFile();
}
//使用RandomAccessFile对象写入一些人员信息,比如姓名和年龄
public static void writeFile() throws IOException {
    //如果文件不存在,则创建,如果文件存在,不创建
    RandomAccessFile raf = new RandomAccessFile("ranacc.txt" ,"rw" );
    raf.write( "张三".getBytes());
    //使用write方法之写入最后一个字节
    raf.write(97);
    //使用writeInt方法写入四个字节(int类型)
    raf.writeInt(97);
    raf.write( "小强".getBytes());
    raf.writeInt(99);
    raf.close();
}

public static void main(String[] args) throws IOException {
    readFile();
}
public static void readFile() throws IOException {
    RandomAccessFile raf = new RandomAccessFile("ranacc.txt" ,"r" );
    //通过seek设置指针的位置
    raf.seek(9); //随机的读取,只要指定指针的位置即可
    byte[] buf = new byte[4];
    raf.read(buf);
    String name = new String(buf);
    System.out.println( "name=" + name);
    int age = raf.readInt();
    System.out.println( "age=" + age);
    System.out.println( "pos:" + raf.getFilePointer());
    raf.close();
}

public static void main(String[] args) throws IOException {
    randomWrite();
}
public static void randomWrite() throws IOException {
    RandomAccessFile raf = new RandomAccessFile("ranacc.txt" ,"rw" );
    //往指定位置写入数据
    raf.seek(3*8);
    raf.write( "哈哈".getBytes());
    raf.writeInt(102);
    raf.close();
}

管道流

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

public static void main(String[] args) throws Exception {
    PipedInputStream input = new PipedInputStream();
    PipedOutputStream output = new PipedOutputStream();
    input.connect(output);
    new Thread(new Input(input)).start();
    new Thread(new Output(output)).start();
}

class Input implements Runnable{
    private PipedInputStream in;
    Input(PipedInputStream in){
        this.in = in;
    }
    public void run(){
        try{
            byte[] buf = new byte[1024];
            int len = in.read(buf);
            String s = new String(buf,0,len);
            System.out.println( "s=" + s);
            in.close();
        } catch(Exception e){
            e.printStackTrace();
        }
    }
}

class Output implements Runnable{
    private PipedOutputStream out;
    Output(PipedOutputStream out){
        this.out = out;
    }
    public void run(){
        try{
            out.write( "hi,管道来了!" .getBytes());
            out.close();
        } catch(Exception e){
            e.printStackTrace();
        }
    }
}

操作基本数据类型

DataInputStream与DataOutputStream

public static void writeData() throws IOException {
    DataOutputStream dos = new DataOutputStream(new
    FileOutputStream("data.txt" ));
    dos.writeUTF( "您好");
    dos.close();
}

public static void readData() throws IOException {
    DataInputStream dis = new DataInputStream(new
    FileInputStream("data.txt" ));
    String str = dis.readUTF();
    System.out.println(str);
    dis.close();
}

操作字节数组

ByteArrayInputStream与ByteArrayOutputStream

关闭字节数组输出输出流无效,因为它们没有调用底层资源,所有的操作都是在内存中完成的

public static void main(String[] args) throws IOException {
    ByteArrayInputStream bis = new ByteArrayInputStream("abcdef.getBytes());
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    int ch = 0;
    while((ch = bis.read()) != -1){
        bos.write(ch);
    }
    System.out.println(bos.toString());
}

常见的编码表
ASCII:美国标准信息交换码,用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表,用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
Unicode:国际标准码,融合了多种文字。
所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值