zxzxzx0119的博客

Java,算法

IO总结之处理乱码,编码,简单装饰,文件分割

目录

  • 处理乱码,编码(转换流)
  • 简单装饰
  • 关闭流的工具类
  • 随机流和文件分割与合并SequenceInputStream
  • IO的一个小总结

处理乱码,编码(转换流)

不同的编码方式,要使用相应的编码方式读取,要注意读取长度不够的时候也会乱码

import java.io.UnsupportedEncodingException;
/**
 * 处理乱码问题以及编码问题
 * @author 郑鑫
 */
public class TestConvertDemo {
    public static void main(String[] args){
        try {
            test1();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        test2();
    }
    /**
     * 编码和解码处理乱码
     * @throws UnsupportedEncodingException
     */
    public static void test1() throws UnsupportedEncodingException {
        // byte --> 解码
        String str = "中国"; // gbk编码
        // byte --> 编码
        byte[] data = new byte[1024];
        data = str.getBytes();
        System.out.println(new String(data));

        data = str.getBytes("utf-8"); // utf8编码
        System.out.println(new String(data)); // 编码不同出现乱码

        byte[] data2 = new byte[100];
        data2 = "中国".getBytes("utf-8"); // 使用utf-8编码
        str = new String(data2, "utf-8"); // 使用utf-8解码
        System.out.println(str);
    }

    /**
     * 长度不足的也会乱码
     */
    public static void test2() {
        String str = "中国";
        byte[] data = str.getBytes();
        System.out.println(new String(data,0,3)); //长度不足 也会乱码
    }
}

再看一个和IO有关的

  • InputStreamReader,OutputStreamReader可以处理乱码,而缓冲流只能处理字符流
  • 注意读取的文件convert.txt我是用UTF8编码格式来存的
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
/**
 * 处理乱码
 * 输出流 : OutputStreamWriter  编码
 * 输入流 : InputStreamReader  解码
 * @author 郑鑫
 */
public class TestConvertDemo2 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(  // 字符  解码读取
                new InputStreamReader(    //这个是处理解码的流,处理字节流,缓冲流只能处理字符流
                    new FileInputStream(
                        new File("D:/eclipsework/zx/test/convert.txt")),"UTF-8") //注意这里c.txt我是用UTF-8的字符集保存的
                );

//      Reader br = new InputStreamReader(    //这个是处理解码的流,处理字节流,缓冲流只能处理字符流
//                  new FileInputStream(
//                      new File("D:/eclipsework/zx/test/convert.txt")),"UTF-8");

        Writer wr = new OutputStreamWriter(new FileOutputStream(new File("D:/eclipsework/zx/test/d.txt")),"UTF-8");//指定存的编码方式
        String str = null;
        while(null != (str = br.readLine())) {
            wr.write(str);  //字节转换编码
            System.out.println(str);
        }
        wr.flush();
        br.close();
    }
}

这里写图片描述


简单装饰

注意类与类之间的关系

  • 扩音器,io : 装饰设计模式
  • 玩的就是类与类之间的关系
  • 依赖 : 形参,局部变量
  • 关联 : 属性
    聚合 : 整体与部分 : 不一致的生命周期 : 人与手
    组合 : 整体与部分 : 一致的生命周期 : 人于大脑
  • 继承 : 父子关系
  • 实现 : 接口与实现类的关系
/**
 * 扩音器
 * io :  装饰设计模式
 * 玩的就是类与类之间的关系
 * 1.依赖 : 形参,局部变量
 * 2.关联 : 属性
 *      聚合 :  整体与部分 : 不一致的生命周期 : 人与手
 *      组合 :  整体与部分 : 一致的生命周期 : 人于大脑
 * 3.继承 : 父子关系
 * 4.实现 : 接口与实现类的关系
 * @author 郑鑫
 *
 */
public class AmpApp {
    public static void main(String[] args) {
        Voices v = new Voices();
        v.say();
        //对Voices的一个装饰
        Amplifier f = new Amplifier(v);
        f.say();
    }
}

//模仿普通人说话的声音
class Voices {
    private int voice = 10;
    public Voices() {}
    public Voices(int voice) {
        super();
        this.voice = voice;
    }
    public int getVoice() {
        return voice;
    }
    public void setVoice(int voice) {
        this.voice = voice;
    }

    public void say() {
        System.out.println(voice);
    }
}

//扩大人的说话的声音(装饰)
class Amplifier {
    private Voices voice;
    public Amplifier() {}
    public Amplifier(Voices voice) {
        super();
        this.voice = voice;
    }
    public void say() {
        System.out.println(voice.getVoice()*1000);
    }
}

这里写图片描述


关闭流的工具类

设计关闭流的工具类

import java.io.Closeable;
import java.io.IOException;

public class FileUtil {
    /**
     * 关闭流的方法
     * 注意可变参数的使用 : 只能位于形参的最后一个位置,使用方法类似数组
     */
    public static void close(Closeable ... io) {  //实现Closeable的方法
        for(Closeable temp : io) {
            if(null != temp)
                try {
                    temp.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * 使用泛型
     * @param io
     */
    public static <T extends Closeable>void closeAll(T ... io) {
        for(Closeable temp : io) {
            if(null != temp) {
                try {
                    temp.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

随机流和文件分割与合并SequenceInputStream

首先看一下RandomAccessFile流的用法,主要是其中的seek(index)方法,从某个位置开始读取。

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import Test.IO.Util.FileUtil;

/**
 *文件分割之前的知识点
 * @author 郑鑫
 */
public class TestRandAccessFile {
    public static void main(String[] args) throws IOException {
        RandomAccessFile rnd = new RandomAccessFile(new File("D:/eclipsework/zx/test/print.txt"),"r");
        rnd.seek(3);  //从某个位置开始读

        byte[] flush = new byte[1024];
        int len = 0;
        while(-1 != (len = rnd.read(flush))) {
            if(len >= 200) {
                System.out.println(new String(flush,0,200));
            }else  {
                System.out.println(new String(flush,0,len));
            }
        }
        FileUtil.closeAll(rnd);
    }
}

再来看文件分割,意思就是传入一个源文件src.txt,将这个文件分割成几块,并放到指定的destPath中的某个目录中,分割成的每个文件都有一个名字,文件分割用到了RandomAccessFile。
文件合并函数mergeFile将分割的几个文件合并到一个文件中,文件合并可以直接追加到文件尾,也可以将之前的那些流合并到SequenceInputStream中,然后再一起写到指定的文件中。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * 文件的分割
 * 1)快数
 * 2)每块的大小
 * 3)每块的名称
 * 分割
 * a)第几块,每块的起点,实际大小
 * b)文件分割
 * @author 郑鑫
 *
 */
public class SplitFile {
    private String filePath;//文件的路径
    private String fileName;  //文件的名字
    private long len; //整个文件的长度
    private int size; //快数
    private long blockSize;  //每块的大小
    private String destPath;  //分割后的存放目录
    private List<String>blockPath;

    public SplitFile() {
        this.blockPath = new ArrayList<String>();
    }   
    public SplitFile(long blockSize) {
        this();
        this.blockSize = blockSize;
    }

    public SplitFile(String path,long blockSize,String destPath) { 
        this(blockSize);
        this.destPath = destPath;
        this.filePath = path;
        init();
    }

    /**
     * 初始化操作
     */
    public void init() {
        File src = null;
        if(null == filePath || !((src = new File(filePath)).exists())) {
            return ;
        }
        if(src.isDirectory())return ;

        //文件名
        this.fileName = src.getName();
        this.len = src.length();

        //修正实际的块的大小
        if( blockSize > len ) {
            this.blockSize = len;
        }

        size = (int) Math.ceil(1.0*len/this.blockSize); //取大于这个数的
        //确定文件的路径
        initFileName();
    }

    public void initFileName() { //每一块的路径和destPath关联
        for(int i = 0; i < size; i++) {
            this.blockPath.add(destPath + "/" + i + this.fileName);
        }
    }
    /**
     * @param destPath 文件的分割的存放目录
     */
    public void split() {
        long beginPos = 0;
        long actualBlockSize = blockSize;
        for(int i = 0; i < size; i++) {
            if(i == size - 1) {
                actualBlockSize = len - beginPos;
            }
            splitDetail(i,beginPos,actualBlockSize);
            beginPos += actualBlockSize;
        }

    }

    /**
     * @param idx  第几块
     * @param beginPos  每一块的开始位置
     * @param actualBlockSize  每一块的实际大小
     */
    public void splitDetail(int idx,long beginPos,long actualBlockSize) {  //实际的整数(最后一块不一定有这么多)
        File src = new File(this.filePath);
        File dest = new File(this.blockPath.get(idx));  //这个是目的地的文件名//在初始化的时候设置为destpath+fileName+part+i了
        RandomAccessFile raf = null;
        BufferedOutputStream bos = null;
        try {
             raf = new RandomAccessFile(src, "r");//只读模式
             bos = new BufferedOutputStream(new FileOutputStream(dest));
             raf.seek(beginPos);
             byte[] flush = new byte[1024];
             int alen = 0;
             while(-1 != (alen = raf.read(flush))) {
                 if(actualBlockSize > len) {                     
                     bos.write(flush,0,alen); 
                     actualBlockSize -= alen;
                 }else {
                     bos.write(flush,0,(int)actualBlockSize); //注意要转换一下成为int
                     break;
                 }
             }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {   //关闭流
            if(null != bos) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(null != raf) {
                try {
                    raf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //将刚刚分解的那些文件合并到destPath
    public void mergeFile(String destPath) {
        File dest = new File(destPath);
        BufferedOutputStream bos = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(dest,true)); //等下就是追加的类型
            for(int i = 0; i < blockPath.size(); i++) {             
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(blockPath.get(i))));
                byte[] flush = new byte[1024];
                int alen = 0;
                while(-1 != (alen = bis.read(flush))) {
                    bos.write(flush,0,alen);
                }
                bos.flush();
                bis.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 先合成一个流
     * SequenceOutputStream
     * @param args
     */
    public void mergeFile2(String destPath) {
        File dest = new File(destPath);
        Vector<InputStream> ve = new Vector<InputStream>();
        BufferedOutputStream bos = null;
        SequenceInputStream sis = null;
        try {
            for(int i = 0; i < blockPath.size(); i++) {             
                ve.add( new BufferedInputStream(new FileInputStream(new File(blockPath.get(i)))) );
            }
            sis = new SequenceInputStream(ve.elements()); //把这些流合并成一个流
            bos = new BufferedOutputStream(new FileOutputStream(dest,true)); //等下就是追加的类型
                byte[] flush = new byte[1024];
                int alen = 0;
                while(-1 != (alen = sis.read(flush))) {
                    bos.write(flush,0,alen);
                }
                bos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                sis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SplitFile sp = new SplitFile("D:/eclipsework/zx/test/split.txt",20,"D:/eclipsework/zx/test/Split");//每一块的大小,后面那个目录参数是为了等下mergeFile
        //System.out.println(sp.size);
        //sp.split();
        //sp.mergeFile("D:/eclipsework/zx/test/Merge/merge.txt");
        sp.mergeFile2("D:/eclipsework/zx/test/Merge/merge1.txt");
    }
}

相关配图效果
这里写图片描述
这里写图片描述
分割后各个文件中内容
这里写图片描述
把分割的文件合并
这里写图片描述

IO的一个小总结

这里写图片描述

阅读更多
文章标签: io
个人分类: JavaIO
上一篇IO总结之ByteArray,DataOutput,Object(序列化),PrintStream
下一篇剑指Offer第六天(31~36)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭