java的io流,同步阻塞式io流

1.io流简介

不论是Reader,Writer,还是InputStream,OutputStream,在创建相应的对象是只是创建了相应的映射,相当于修了一条马路通向两个位置,但是本身并不参与数据的传输,数据的传输是通过数组完成的,这个传输的过程是单向的(nio的buffer是双向的)面向于流的传输(nio面向缓存数据块),对于读的时候不论基于单个字符还是基于数组,当没有可读的元素的时候返回值都是-1,有可读的时候返回的是有效数据的字节或字符长度,返回字符串的时候,在没有的情况下为null,对于一个输入流来说具有skip的方法,跳到我们制定的地方去开始输入,对于写我们可以设置为true在尾部添加,对于覆盖数据我们可以是用RandomAccessFile的seek设定覆盖的位置,对于我们对象流(序列化流)可以将一个文件保存在一个文件中,然后在另一个地方读取(读取的前提条件是相应的序列化类需要已经加载到JVM中),对于BufferedOutputStream等采用装饰模式,也就是在FileOutputStream外面包了一层,对于文件的乱码问题前面有一篇有介绍。

2.file

public class CreateFile {
    // 创建文件
    public static void creatFile(String filePath) throws Exception {
        File file = new File(filePath);
        if (!file.exists()) {
            file.createNewFile();
        } else {
            System.err.println("文件夹以及存在");
        }
    }

    // 创建文件夹
    public static void creatFolder(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        } else {
            System.err.println("文件夹以及存在");
        }
    }

    // 在指定的文件下搜索文件(可以模糊查找)
    public static List<String> FuzzySearch(String filePath, String regex) {
        LinkedList<String> lls = new LinkedList<>();
        regex = ".*" + regex + ".*";
        File file = new File(filePath);
        if (!file.exists()) {
            System.err.println("指定的目录不存在");
            return null;
        }
        if (!file.isDirectory()) {
            System.err.println("指定的不是目录");
            return null;
        }
        getErgodicFiles(regex, lls, file);
        if (lls.size() == 0) {
            System.out.println("没有找到符合的信息");
        }
        return lls;
    }

    // 遍历文件
    public static void getErgodicFiles(String regex, LinkedList<String> lls, File file) {
        if (file.isDirectory()) {
            File[] lfs = file.listFiles();
            for (File f : lfs) {
                if (!f.isDirectory()) {
                    String absolutePath = f.getAbsolutePath();
                    if (absolutePath.matches(regex)) {
                        lls.add(absolutePath);
                    }
                } else {
                    getErgodicFiles(regex, lls, f);
                }
            }
        }
    }

    // 遍历文件
    public static void getErgodicFiles(String fileName, File file) {
        if (file.isDirectory()) {
            File[] lfs = file.listFiles();
            for (File f : lfs) {
                if (!f.isDirectory()) {
                    f.delete();
                } else {
                    getErgodicFiles(fileName, f);
                }
            }
        }
    }

    public static void delete(String fileName) {
        File file = getFile(fileName);
        if (file == null) {
            return;
        }
        if (!file.isDirectory()) {
            file.delete();
            return;
        }
        getErgodicFiles(fileName, file);
        file.delete();
        System.out.println("删除成功");
    }

    // 设置文件只读,但是可以另存为
    public static void setOnlyRead(String fileName) {
        File file = getFile(fileName);
        if (file == null) {
            return;
        }
        file.setReadable(true);
        file.setWritable(false);
    }

    private static File getFile(String fileName) {
        File file = new File(fileName);
        if (!file.exists()) {
            System.err.println("指定的目录或者文件夹不存在不存在");
            return null;
        }
        return file;
    }

    public static void main(String[] args) throws Exception {
        // CreateFile.creatFile("F:/test/file");
        // CreateFile.creatFolder("F:/test/file1.txt");
        // List<String> fuzzySearch = CreateFile.FuzzySearch("F:/test", "file");
        // System.out.println(fuzzySearch);
        // CreateFile.delete("F:/test/file1.txt");
        // CreateFile.setOnlyRead("F:/test/file1/file.txt");
    }
}

3.new FileOutputStream与 new RandomAccessFile的区别

一个存在则新建,一个存在则覆盖覆盖,默认的seek是从0开始的,RandomAccessFile对同一文件可进行读写

4.更改某一个文件中的值然后保存

public static void main(String[] args) {
        try {
            InputStream resourceAsStream4 = PopertiesDemo1.class.getClassLoader()
                    .getResourceAsStream("cn/collection/demo/config.properties");
            Properties properties = new Properties();
            properties.load(resourceAsStream4);
            System.out.println(properties.getProperty("name"));
            properties.setProperty("name", "李四");
            System.out.println(properties.getProperty("name"));
            FileWriter fileWriter = new FileWriter("config1");
            // "aa" 描述信息
            properties.store(fileWriter, "aa");
            fileWriter.close();
        } catch (Exception e) {
            System.out.println("没有找到文件");
        }
    }

5.对象流

实现Externalizable接口,Externalizable继承了Serializable 接口,Externalizable中有两个方法需要重写writeExternal及readExternal,在writeObject和readObject时会调用相应的方法。

transient关键字表示瞬态的,在保存的是是后不会被保存进对象流,假如我么依旧添加,那么可以使用如下方法

public class Person implements Serializable {
    private String adress;
    // transient 关键字 表示瞬态 假如需要保存这个那么需要单独的去保存
    private transient int age;
    private static String name;
    private transient static int id;

    public String getAdress() {
        return adress;
    }

    public void setAdress(String adress) {
        this.adress = adress;
    }

    public static int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Person() {
        super();
    }

    public Person(int age, String adress, int id, String name) {
        super();
        this.age = age;
        this.adress = adress;
        this.id = id;
        this.name = name;
    }

    public static String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    // 一定要为私有才可以被调用
    private void writeObject(ObjectOutputStream stream) throws IOException {
        // 将非静态的非瞬态的保存在对象流中
        stream.defaultWriteObject();
        stream.writeObject(age);
        stream.close();
    }

    // 一定要为私有才可以被调用
    private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException {
stream.defaultReadObject(); age = (int) (stream.readObject()); stream.close(); } @Override public String toString() { return "Person [age=" + age + ", adress=" + adress + ",name=" + name + ",]"; } }

6.分段读取文件,每次只保存一部分(网络版的在爬虫中)

public class SegmentedReadFile extends Thread {
        private volatile boolean flag = false;
        @Override
        public void run() {
                try {
                        Scanner scanner = new Scanner(System.in);
                        String nextLine = scanner.nextLine();
                        if (nextLine.equals("true")) {
                                this.flag = true;
                        }
                } catch (Exception e) {
                }
        }

        public boolean test(String src, String target) throws IOException {
                File file = new File(src);
                File file2 = new File(target);
                // 这里以单个文件为例
                if (file.isDirectory()) {
                        System.out.println("该路径是文件夹不是文件");
                        return false;
                }
                if (!file.isFile()) {
                        System.out.println("该文件路径不存在");
                        return false;
                }
                if (!file2.isFile()) {
                        try {
                                file2.createNewFile();
                        } catch (IOException e) {
                                return false;
                        }
                }
                FileInputStream fileInputStream=null;
                BufferedInputStream bufferedInputStream=null;
                FileOutputStream fileOutputStream=null;
                BufferedOutputStream bufferedOutputStream=null;
                if (file2.isFile()) {
                        long lg1 = file.length();
                        int segment = 24000000;
                        fileInputStream = new FileInputStream(file);
                        bufferedInputStream = new BufferedInputStream(fileInputStream);
                        fileOutputStream = new FileOutputStream(file2, true);
                        bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                        byte[] bys = new byte[1024];
                        
                        if (file.length() - file2.length() >= segment) {
                                long lg = file2.length();
                                bufferedInputStream.skip(lg);
                                for (int i = 0; i <= segment / 1024; i++) {
                                        if (flag) {
                                                break;
                                        }
bufferedInputStream.read(bys); if (i < segment / 1024 ) { bufferedOutputStream.write(bys, 0, 1024); } else { bufferedOutputStream.write(bys, 0, segment%1024); } } } else if(file.length() - file2.length()>0){ long lg = file2.length(); bufferedInputStream.skip(lg); long lastSize=file.length() - file2.length(); for (int i = 0; i <= lastSize / 1024; i++) { if (flag) { break; } int read = bufferedInputStream.read(bys); if (read != -1) { bufferedOutputStream.write(bys, 0, read); } } }else{ System.out.println("传输完成"); } } bufferedInputStream.close(); bufferedOutputStream.close(); System.gc(); System.runFinalization(); return true; } public static void main(String[] args) throws IOException { SegmentedReadFile segmentedReadFile = new SegmentedReadFile(); segmentedReadFile.setDaemon(true); segmentedReadFile.start(); boolean test = segmentedReadFile.test("G:/360安全浏览器下载安装包/tim_pc.exe", "G:/360安全浏览器下载安装包/tim_pc1.exe"); if (!test) { System.out.println("传输失败"); } } }

7.重定向输出记录错误日志文件

public class Redirect1 {
   public static void main(String[] args) throws FileNotFoundException {
     String str="hello world";
     PrintStream printStream = new PrintStream("y.txt");
//可以不关闭,自动会刷新缓存 printStream.print(str); }

8.字节字符转换流

public static void main(String[] args) throws IOException {
         //方式一
         FileInputStream fileInputStream = new  FileInputStream("1.txt");
         //不乱码的前提是知道编码,或者是unicode码的\\u方式写的
         InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"utf-8");
         BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
         //java内存中是使用unicode码保存的
         String readLine = bufferedReader.readLine();
         System.out.println(readLine);
         if(bufferedReader!=null){
             bufferedReader.close();
         }
         if(inputStreamReader!=null){
             inputStreamReader.close();
         }
         if(fileInputStream!=null){
             fileInputStream.close();
         }
         FileOutputStream fileOutputStream = new FileOutputStream("3.txt");
         OutputStreamWriter outputStreamWriter = new  OutputStreamWriter(fileOutputStream,"gbk");
         BufferedWriter bufferedWriter = new  BufferedWriter(outputStreamWriter);
         bufferedWriter.write(readLine);
         if(bufferedWriter!=null){
             bufferedWriter.close();
         }
         if(outputStreamWriter!=null){
             outputStreamWriter.close();
         }
         if(fileOutputStream!=null){
             fileOutputStream.close();
         }
         FileInputStream fileInputStream1 = new  FileInputStream("3.txt");
         //按指定解码然后按unicode保存
         InputStreamReader inputStreamReader1 = new InputStreamReader(fileInputStream1,"gbk");
         BufferedReader bufferedReader1 = new BufferedReader(inputStreamReader1);
         String readLine1 = bufferedReader1.readLine();
        //将unicode码有转换成了工作空间相应的编码
         System.out.println(readLine1);
         if(bufferedReader1!=null){
             bufferedReader1.close();
         }
         if(inputStreamReader1!=null){
             inputStreamReader1.close();
         }
         if(fileInputStream1!=null){
             fileInputStream1.close();
         }
         //方式二
         ByteArrayOutputStream byteArrayOutputStream = new  ByteArrayOutputStream();
         byteArrayOutputStream.write(readLine1.getBytes());
        //因为我的工作空间是utf-8的
         String string = byteArrayOutputStream.toString("utf-8");
         byteArrayOutputStream.close();
         System.out.println(string);
         FileInputStream fileInputStream2 = new  FileInputStream("3.txt");
         ByteArrayOutputStream byteArrayOutputStream2 = new  ByteArrayOutputStream();
         byte [] bs =new byte [1024];
         int len =0;
         while((len=fileInputStream2.read(bs))!=-1){
             byteArrayOutputStream2.write(bs, 0, len);
         }
         //不会乱码
         String string2 = byteArrayOutputStream2.toString("gbk");
         fileInputStream2.close();
         byteArrayOutputStream2.close();
         System.out.println(string2);
         //readLine.getBytes(charset)
        //Charset.forName("UTF-8").encode(str)
   }

9.其他一些流

SequenceInputStream 合并多个流文件 SequenceInputStream(Enumeration<? extends InputStream> e)

PrintWriter 与 PrintStream 差不多

PipedWriter 是向与其它线程共用的管道中写入数据

CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据

DataOutputStream 保存相应的数据,按保存的顺序读取

ZipOutputStream 压缩流 批量压缩(文件夹)可以使用这个方法putNextEntry(ZipEntry e),ZipEntry(String name)使用指定名称创建新的 ZIP 条目。

ZipInputStream 解压流

public class ZipInputStreamDemo2 {
    public static void main(String[] args) throws IOException {
        File file = new File("d:" + File.separator + "zipFile.zip");
        File outFile = null;
        ZipFile zipFile = new ZipFile(file);
        ZipInputStream zipInput = new ZipInputStream(new FileInputStream(file));
        ZipEntry entry = null;
        InputStream input = null;
        OutputStream output = null;
        while ((entry = zipInput.getNextEntry()) != null) {
            System.out.println("解压缩" + entry.getName() + "文件");
            outFile = new File("d:" + File.separator + entry.getName());
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdir();
            }
            if (!outFile.exists()) {
                outFile.createNewFile();
            }
            input = zipFile.getInputStream(entry);
            output = new FileOutputStream(outFile);
            int temp = 0;
            while ((temp = input.read()) != -1) {
                output.write(temp);
            }
            input.close();
            output.close();
        }
    }

}
//多个文件进行压缩
public class ZipOutputStreamDemo2 { public static void main(String[] args) throws IOException { // 要被压缩的文件夹 File file = new File("d:" + File.separator + "temp"); File zipFile = new File("d:" + File.separator + "zipFile.zip"); InputStream input = null; ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile)); zipOut.setComment("hello"); if (file.isDirectory()) { File[] files = file.listFiles(); for (int i = 0; i < files.length; ++i) { input = new FileInputStream(files[i]); zipOut.putNextEntry(new ZipEntry(file.getName() + File.separator + files[i].getName())); int temp = 0; while ((temp = input.read()) != -1) { zipOut.write(temp); } input.close(); } } } }