Java笔记-10 IO流

输入输出流

  • 外部系统的输入输出操作

  • 字节流:以字节为单位获取数据,命名上以Stream结尾的流一般是字节流,如FileInputStream、FileOutputStream。

  • 字符流:以字符为单位获取数据,命名上以Reader/Writer结尾的流一般是字符流,如FileReader、FileWriter。

序号 分类 功能
1. InputStream/OutputStream 字节流 抽象类。
2. Reader/Writer 字符流 抽象类
3. FileInputStream/FileOutputStream 节点流 以字节为单位直接操作“文件”。
4. ByteArrayInputStream/ByteArrayOutputStream 节点流 以字节为单位直接操作“字节数组对象”。
5. ObjectInputStream/ObjectOutputStream 处理流 以字节为单位直接操作“对象”。
6. DataInputStream/DataOutputStream 处理流 以字节为单位直接操作“基本数据类型与字符串类型”。
7. FileReader/FileWriter 节点流 以字符为单位直接操作“文本文件”(注意:只能读写文本文件)。
8. BufferedReader/BufferedWriter 处理流 将Reader/Writer对象进行包装,增加缓存功能,提高读写效率。
9. BufferedInputStream/BufferedOutputStream 处理流 将InputStream/OutputStream对象进行包装,增加缓存功能,提高 读写效率。
10. InputStreamReader/OutputStreamWriter 处理流 将字节流对象转化成字符流对象。
11. PrintStream 处理流 将OutputStream进行包装,可以方便地输出字符,更加灵活v

File的关于文件的操作

import java.io.File;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        //分隔符
        System.out.println(File.separator); // 文件夹的分隔符字符串的\
        System.out.println(File.separatorChar); // char的\
        System.out.println(File.pathSeparator); //;
        String userDir = System.getProperty("user.dir"); //相对路径的路径
        System.out.println(userDir);

        File f = new java.io.File("src/images/ball.png");
        //基本信息
        System.out.println(f.exists());
        System.out.println(f.getName()); // ball.png
        System.out.println(f.getPath()); // src\images\ball.png
        System.out.println(f.getAbsolutePath());// D:\data\idea\testjava\src\images\ball.png
        System.out.println(f.getParent()); //父路径 src\images,如果没有则为null
        System.out.println(f.getParentFile());//父路径的File对象
        //状态
        System.out.println(f.isDirectory());
        System.out.println(f.isFile());
        System.out.println(f.isAbsolute());
        System.out.println(f.isHidden());
        //信息
        if(f.isFile()){
            //目录的length是0,没有存在的文件长度也是0
            System.out.println("文件长度:"+f.length()+" B");
        }
        //创建文件,路径默认是项目下的路径
        File nf = new File("aa.txt");
        boolean isCreateSuccess = nf.createNewFile();
        System.out.println(isCreateSuccess);
        //删除文件
        boolean isDeleteSuccess = nf.delete();
        System.out.println(isDeleteSuccess);
    }
}

File关于文件夹的操作

import java.io.File;

/**
 * File目录的相关操作,
 * 遍历打印文件
 */
public class TestFileFolder {
    public static void main(String[] args) {

        File[] roots = File.listRoots(); //盘符的File对象数组
        for(File f:roots) {
            System.out.println(f);
        }
        //创建目录,需要前一层目录存在
        File file = new File("abc");
        file.mkdir();
        //多层创建,可以创建多层目录
        new File("ddd/eee/fff").mkdirs();
        new File("abc").deleteOnExit();
        //列出下一级
        File f1 = new File(".");
        String[] fsting = f1.list(); //只列出名称
        System.out.println(fsting);
        File[] fs = f1.listFiles();//列出File对象
        for(File f:fs){
            System.out.println(f+":"+f.isDirectory());
            //System.out.println(f.getAbsolutePath());
        }
        System.out.println("--------------");
        leng = 0;
        getFiles(new File("D:\\fvc"),0);
        System.out.println(leng);

    }
    static long leng = 0;
    //递归打印所有文件,顺便获取文件夹所有文件的大小
    public static void getFiles(File file,int deep){
        for(int i = 0;i<deep;i++){
            System.out.print("-");
        }
        if(file.isDirectory()){
            File[] fs = file.listFiles();
            for(File f:fs){
                getFiles(f,deep+1);
            }
        }else {
            System.out.println(file.getAbsolutePath());
            leng+=file.length();
        }
    }
}

字符集,字符串与字节数组的转换

import java.io.UnsupportedEncodingException;

public class TestEncode {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String msg = "编程java";
        //转换为字节数组
        byte[] bytes = msg.getBytes();
        System.out.println(bytes);
        printByte(bytes);

        byte[] bytesgbk = msg.getBytes("GBK");
        printByte(bytesgbk);

        byte[] bytesutf16 = msg.getBytes("UTF-16LE");
        printByte(bytesutf16);

        //字节数组转换为字符串
        msg = new String(bytes,0,bytes.length,"utf8");
        System.out.println(msg);

        msg = new String(bytesgbk,0,bytesgbk.length,"GBK");
        System.out.println(msg);

        msg = new String(bytesutf16,0,bytesutf16.length,"UTF-16LE");
        System.out.println(msg);
    }
    static void printByte(byte[] bytes){
        /**
         * 将字节数组打印成一行
         */
        StringBuilder sb = new StringBuilder("[");
        for(byte b:bytes){
            sb.append(b+",");
        }
        sb.setCharAt(sb.length()-1,']');
        System.out.println(sb);
    }
}

四大抽象类

  • InputStream/OutputStream和Reader/writer类是所有IO流类的抽象父类,前两个是字节的输入输出流,后面两个是字符的输入输出流。读和输入常用read和close方法,写和输出常用write,flush,close方法。

文件字节流

FileInputStream

  • 按字节读取文件
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class TestIO {
    public static void main(String[] args) throws IOException {
        //FileInpuStream可以传入File或字符串路径,word里存abc三个字母
        InputStream fis = new FileInputStream("testdata/word.txt");

        System.out.println((char)fis.read()); //第一个字母a
        System.out.println((char)fis.read()); //第二个字母b
        System.out.println((char)fis.read()); //第三个字母c
        System.out.println(fis.read()); //第4个返回-1,不是数据了
        //关闭
        fis.close();


        //使用while来读,一直到最后,一次读取一个字符
        InputStream fis1 = new FileInputStream("testdata/word.txt");
        int temp;
        while((temp=fis1.read()) != -1){
            System.out.println((char)temp);
        }
        fis1.close();

        //一次读取多个字符,一般按K读取,例如flush个数为1024*10,表示10k
        InputStream fis2 = new FileInputStream("testdata/word.txt");
        byte[] flush = new byte[3]; //用于接收读取的内容
        int len = -1; //接收长度
        while((len = fis2.read(flush)) != -1){
            //参数为byte[]类型时,读取的内容到字节数组中,返回读取的个数
            System.out.println(len);
            String s = new String(flush,0,len,"utf8");
            System.out.println(s);
        }
        fis2.close();
    }
}

FileOutputStream

  • 按字节写出文件,FileWriter是按字符写出
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * FileOutputStream
 */
public class TestFileOutputStream {
    public static void main(String[] args) throws IOException {
        //如果文件不存在则自动创建,true表示追加模式
        //默认false,新文件
        OutputStream os = new FileOutputStream("testdata/out.txt",true);
        String s = "学编程多赚钱\r\n";
        byte[] data = s.getBytes();
        //write需要传入字节数组,off,length,不加的话自动调用这个方法
        os.write(data,0,data.length);
        os.write("万能的java".getBytes());
        os.flush();
        os.close();
    }
}

文件的复制

  • FileInputStream和FileOutpputStream复制文件
import java.io.*;

/**
 * 使用FileInputStream和FileOutpputStream复制文件
 */
public class TestCopyFile {
    public static void main(String[] args) throws IOException {
        String inFile = "src/images/desk.jpg";
        String outFile = "testdata/desk.jpg";
        File f = new File(outFile);
        if(f.exists()){
            System.out.println("目标文件已存在,即将退出");
            System.exit(0);
        }else {
            System.out.println("开始复制");
        }
        InputStream src = new FileInputStream(inFile);
        OutputStream dst = new FileOutputStream(f);

        byte[] buff = new byte[1024*10]; //用于接收读取的内容
        int len = -1; //接收长度
        while((len = src.read(buff)) != -1){
            //接受来的数据直接传入到输出
            dst.write(buff);
            dst.flush();
        }
        dst.close();
        src.close();
        if(f.exists()){
            System.out.println("复制成功");
        }
    }
}

文件字符流

  • FileReader与FileWriter,直接操作文本文件的字符

FileReader

  • 将字符读入一个字符数组中,char[],再将字符数组转换为字符串,指定字符数组的偏移和长度
import java.io.FileReader;
import java.io.IOException;

/**
 * 文件字符流,读文本文件
 */

public class TestFileReader {
    public static void main(String[] args) throws IOException {
        String inFile = "testdata/word.txt";
        FileReader fr = new FileReader(inFile);
        char[] data = new char[3];
        int len=-1 ;
        while ((len = fr.read(data)) != -1){
            //读入的字符转换为字符串,需要指定长度
            String str = new String(data,0,len);
            System.out.println(str);
        }
        if(fr != null){
            fr.close();
        }
    }
}

FileWriter

  • 写出字符数组,或字符串
import java.io.FileWriter;
import java.io.IOException;

public class TestFileWriter {
    public static void main(String[] args) throws IOException {
        String dst = "testdata/filewriter.txt";
        //true表示追加模式
        FileWriter fw = new FileWriter(dst,true);
        String str = "哈哈哈大数据云计算java物联网\r\n";
        char[] chars = str.toCharArray();
        //write的参数可以是字符串或字符数组,三个参数再加上偏移和长度
        fw.write(str);
        fw.write(chars,3,4);
        //流模式写入
        fw.append("hadoop").append("spark").append("java").append("scala");
        fw.flush();
        fw.close();
    }

字节数组流

  • 源头是内存中的数据,java虚拟机直接访问内存,gc机制回收,不需要关闭,由于内存的限制数据不要太大
  • ByteArrayInputStream,ByteArrayOutputStream

ByteArrayInputStream

  • 读与FileInputStream相同,只不过输入源不同
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

public class TestByteArrayInputStream {
    public static void main(String[] args) throws IOException {
        byte[] s = "abcdefghijklmn".getBytes();
        InputStream fis2 = new ByteArrayInputStream(s);
        byte[] flush = new byte[3]; //用于接收读取的内容
        int len = -1; //接收长度
        while((len = fis2.read(flush)) != -1){
            //参数为byte[]类型时,读取的内容到字节数组中,返回读取的个数
            String str = new String(flush,0,len,"utf8");
            System.out.println(str);
        }
        //close是个空方法,可以不用close
        fis2.close();
    }
}

ByteArrayOutputStream

  • 不需要指定源
  • 数据到内存中
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class TestByteArrayOutputStream {
    public static void main(String[] args) throws IOException {
        byte[] dest= null;
        ByteArrayOutputStream fis = new ByteArrayOutputStream();
        byte[] flush = new byte[3]; //用于接收读取的内容
        int len = -1; //接收长度
        String msg = "abcdefg";
        byte[] data = msg.getBytes();
        //将data写入到字节数组输出流
        fis.write(data,0,data.length);
        fis.flush();
        //数据保存到了内存中,使用toByteArray取数据
        dest=fis.toByteArray();
        String ss = new String(dest);
        System.out.println(ss);
        System.out.println(fis.toString());
    }
}

均使用Buffered开头的读写

缓冲字节流 BufferedInputStream和BufferedOutputStream

  • Java缓冲流本身并不具有IO流的读取与写入功能,只是在别的流(节点流或其他处理流)上加上缓冲功能提高效率,就像是把别的流包装起来一样,因此缓冲流是一种处理流
  • 缓冲流是先将数据缓存起来,然后当缓存区存满后或者手动刷新时再一次性的读取到程序或写入目的地,使用缓冲流就能够更高效的读写信息。
  • BufferedInputStream和BufferedOutputStream这两个流是缓冲字节流,通过内部缓存数组来提高操作流的效率。
  • 使用时将 FileInputStream或FileOutputStream的对象传入,其他读写方法不变
        BufferedInputStream src = new BufferedInputStream(new FileInputStream(inFile));
        BufferedOutputStream dst = new BufferedOutputStream(new FileOutputStream(f));

缓冲字符流

  • BufferedReader/BufferedWriter增加了缓存机制,大大提高了读写文本文件的效率,同时,增加了更方便的按行读取的方法:readLine(); 处理文本时,我们一般可以使用缓冲字符流

BufferedReader

  • 增加了readLine()方法,一次读取一行,其他的read的方法也能适用
  • 创建BufferReader对象需要传入FileReader对象,跟上面的FileInputStream一样
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * 缓冲字符流BufferedReader
 */
public class TestBufferedBufferStream {
    public static void main(String[] args) throws IOException {
        String inFile = "testdata/word.txt";
        FileReader fr = new FileReader(inFile);
        //创建BufferReader对象需要传入FileReader对象
        BufferedReader reader = new BufferedReader(fr);
        String line = null;
        //直接使用readline方法,读取的结果给line,读不到则为null
        while ((line = reader.readLine()) != null){
            System.out.println(line);
        }
        reader.close();
    }
}

BufferedWriter

  • 写入纯文本文件,newLine方法只写出一个换行
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class TestBufferedWriter {
    public static void main(String[] args) throws IOException {
        String dst = "testdata/wordout.txt";
        FileWriter dstf = new FileWriter(dst);
        BufferedWriter writer = new BufferedWriter(dstf);
        writer.write("大数据");
        writer.newLine();  //newLine方法添加换行符
        writer.write("云计算");
        writer.newLine();
        
        writer.flush();
        writer.close();
    }
}

转换流

  • 字节流和字符流相互装换
  • InputStreamReader将字节流转化成字符流
  • OutputStreamWriter将字符流转化为字节流

InputStreamReader

import java.io.*;

/**
 * 字符流与字节流的转换
 *
 */
public class TestInputStreamReader {
    public static void main(String[] args) throws IOException {
        //System.in是个字节流,r是字符流
        InputStreamReader r = new InputStreamReader(System.in);
        //System.out是字符流
        OutputStreamWriter w = new OutputStreamWriter(System.out);
        //加上缓冲
        BufferedReader reader = new BufferedReader(r);
        BufferedWriter writer = new BufferedWriter(w);

        String msg = "";
        while (!msg.equals("exit")){
            msg = reader.readLine();
            writer.write(msg);
            writer.newLine();
            writer.flush();
        }
        System.out.println("");

    }
}

OutputStreeamWriter

  • 网络数据流保存到文件
import java.io.*;
import java.net.URL;

/**
 * 字符流与字节流的转换
 *
 */
public class TestInputStreamReader2 {
    public static void main(String[] args) throws IOException {
        System.out.println("-----");
        getNormalBuffer(); //BufferedReader
    }
   
    public static void getNormalBuffer() throws IOException {
        /**
         * 使用InputStreamReader,指定字符集
         */
        //网络字节流输入
        //InputStream is = new URL("http://www.baidu.com").openStream();
        InputStreamReader is = new InputStreamReader(new URL("http://www.baidu.com").openStream(),"UTF-8");
        BufferedReader reader = new BufferedReader(is);
        //输出字节流
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(
                        new FileOutputStream("testdata/baidu.html"),"UTF-8")) ;
        String line = "";
        while ((line=reader.readLine()) != null){
            //将读到的数据打印
            System.out.println(line);
            //将数据保存到文件
            writer.write(line);
            writer.newLine();
            writer.flush();
        }
        writer.close();

    }
}

数据流 DataInputStream / DataOutputStream

  • 数据流将“基本数据类型与字符串类型”作为数据源,从而允许程序以与机器无关的方式从底层输入输出流中操作Java基本数据类型与字符串类型
  • 示例1,BufferedOutputStream作为源
import java.io.*;

/**
 * 基本数据类型和字符串的流
 * 先写出DataOuputStream
 * 再读入DataInputStream
 */
public class TestDataInputStream {
    public static void main(String[] args) throws IOException {
        //写出
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream ds = new DataOutputStream(new BufferedOutputStream(baos));
        //操作数据类型和数据
        ds.writeUTF("哈哈哈"); //字符串
        ds.writeByte(123);
        ds.writeShort(22);
        ds.writeInt(100);
        ds.writeLong(1234L);
        ds.writeChar('a');
        ds.writeFloat(12f);
        ds.writeDouble(2.34);
        ds.writeBoolean(true);
        //写出的时候一定不能忘记
        ds.flush();
        byte[] datas = baos.toByteArray();

        //读取
        DataInputStream dis = new DataInputStream(
                new BufferedInputStream(new ByteArrayInputStream(datas)));
        //顺序与写入顺序一致
        String msg = dis.readUTF(); //哈哈哈
        byte b = dis.readByte();//123
        System.out.println(msg);
        System.out.println(b);
    }
}
  • 示例2:文件源,写入到文件再从文件读取
import java.io.*;

public class TestDataStream {
    public static void main(String[] args) throws IOException {
        /**\
         * 写入文件,只能用编程方法再次读取,如果打开的话是乱码
         */
        FileOutputStream fos = new FileOutputStream("testdata/data.txt");
        FileInputStream  fis = new FileInputStream("testdata/data.txt");
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(fos));
        DataInputStream dis = new DataInputStream(new BufferedInputStream(fis));

        //将如下数据写入到文件中
        dos.writeChar('a');
        dos.writeInt(10);
        dos.writeDouble(Math.random());
        dos.writeBoolean(true);
        dos.writeUTF("北京尚学堂");
        //手动刷新缓冲区:将流中数据写入到文件中
        dos.flush();
        //直接读取数据:读取的顺序要与写入的顺序一致,否则不能正确读取数据。
        System.out.println("char: " + dis.readChar());
        System.out.println("int: " + dis.readInt());
        System.out.println("double: " + dis.readDouble());
        System.out.println("boolean: " + dis.readBoolean());
        System.out.println("String: " + dis.readUTF());
        
        dos = null;
        dis = null;
        fos = null;
        fis = null;

    }
}

对象流 ObjectInputStream / ObjectOutputStream

  • 使用与DataInputStream类似
  • ObjectInputStream/ObjectOutputStream是以“对象”为数据源,但是必须将传输的对象进行序列化与反序列化操作。
  • 输出流为将对象写出到文件或数据库,内存中,输入流为将文件等还原为对象
  • 不是所有的对象都能序列化,需要继承java.io.Serializable接口
  • 不序列化的字段用transient关键字修饰
  • 示例1:对象的保存与读写,使用ByteArrayOutputStream / ByteArrayInputStream
import java.io.*;

/**
 * 基本数据类型和字符串的流
 * 先写出DataOuputStream
 * 再读入DataInputStream
 */
public class TestObjectInputStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //将对象写出
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream ds = new ObjectOutputStream(
                new BufferedOutputStream(baos));
        //操作数据类型和对象
        ds.writeUTF("哈哈哈"); //字符串
        ds.writeInt(100);
        ds.writeDouble(2.34);
        ds.writeBoolean(true);
        ds.writeObject("明月");//字符串是对象,且实现了Serializable接口
        ds.writeObject(Integer.valueOf(10));
        ds.writeObject(new Person(45,"大刀关胜")); //写入自定义对象
        //写出的时候一定不能忘记
        ds.flush();
        byte[] datas = baos.toByteArray();

        //还原对象
        ObjectInputStream dis = new ObjectInputStream(
                new BufferedInputStream(new ByteArrayInputStream(datas)));
        //顺序与写入顺序一致
        String msg = dis.readUTF(); //哈哈哈
        int i = dis.readInt();//100
        double d = dis.readDouble();
        boolean b = dis.readBoolean();
        String s = (String)dis.readObject();
        int in = (Integer)dis.readObject();

        System.out.println(msg);
        System.out.println(s);
        System.out.println(in);

        Object op = dis.readObject();
        if(op instanceof Person){
            Person p = (Person)op;
            System.out.println(p);
        }
    }
}

class Person implements Serializable{
    /**
     * Person继承了Serializable接口,能够进行序列化
     * age用transient关键字修饰,不会序列化age的数据,值为默认值
     */
    private transient int age;
    private String name;
    public Person(){}
    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return String.format("name: %s ----- age: %s",name,age);
    }
}
  • 示例2:对象保存到文件中,再读取FileOutputStream/FileInputStream
import java.io.*;

/**
 * 基本数据类型和字符串的流
 * 先写出DataOuputStream
 * 再读入DataInputStream
 */
public class TestObjectInputStreamFile {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //保存对象的路径
        String path = "testdata/object.obj";
        writeObjectToFile(path);
        readObjectFromFile(path);
    }
    
    public static void writeObjectToFile(String path) throws IOException {
        /**
         * 将对象保存到文件
         */
        ObjectOutputStream ds = new ObjectOutputStream(
                new BufferedOutputStream(new FileOutputStream(path)));
        //操作数据类型和对象
        ds.writeObject("江畔何人初见月,江月何年初照人");//字符串是对象,且实现了Serializable接口
        ds.writeObject(Integer.valueOf(10));
        ds.writeObject(new Person1(55,"双鞭呼延灼")); //写入自定义对象
        //写出的时候一定不能忘记
        ds.flush();
        //文件流需要关闭
        ds.close();
        System.out.println("写入成功");
    }

    public static void readObjectFromFile(String path) throws IOException, ClassNotFoundException {
        /**
         * 从文件还原对象
         */
        //还原对象,流不一样,其余还原方式一样
        ObjectInputStream dis = new ObjectInputStream(
                new BufferedInputStream(new FileInputStream(path)));
        //顺序与写入顺序一致

        String s = (String)dis.readObject(); //读第一个对象
        int in = (Integer)dis.readObject(); //读第二个对象

        System.out.println(s);
        System.out.println(in);

        Object op = dis.readObject(); //读第三个对象
        if(op instanceof Person1){
            Person1 p = (Person1)op;
            System.out.println(p);
        }
        //关闭流
        dis.close();
    }
}

class Person1 implements Serializable{
    /**
     * Person继承了Serializable接口,能够进行序列化
     * age用transient关键字修饰,不会序列化age的数据,值为默认值
     */
    private transient int age;
    private String name;
    public Person1(){}
    public Person1(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return String.format("name: %s ----- age: %s",name,age);
    }
}

打印流

PrintStream

  • System.out是一个PrintStream
  • PrintStream可以将输出由控制台转换到文件
import java.io.*;

public class TestPrintStream {
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps = System.out;
        ps.println("10");

        //输出到文件,第一个true为追加模式,第二个true表示自动刷新缓存
        PrintStream ps1 = new PrintStream(
                new BufferedOutputStream(
                        new FileOutputStream("testdata/print.txt",true)
                ),true);

        ps1.println("hahha");
        ps1.println("true");
        //ps1.flush();
        ps1.close();

        //重定向输出控制台转移到文件,先创建流再设置
        String printPath = "testdata/print1.txt";
        PrintStream ps2 = new PrintStream(new BufferedOutputStream(
                new FileOutputStream(printPath,true)),true);
        System.setOut(ps2);  //设置
        ps2.println("hahah");
        System.out.println("输出的"); //不会打印到控制台了,而是输出到了文件

        //重定向回控制台,autoFlush需要设置为true
        System.setOut(new PrintStream(new BufferedOutputStream(
                new FileOutputStream(FileDescriptor.out)
        ),true));
        System.out.println("打印到控制台了");
        
    }
}

PrintWriter

import java.io.*;

public class TestPrintWriter {
    public static void main(String[] args) throws FileNotFoundException {

        //输出到文件,第一个true为追加模式,第二个true表示自动刷新缓存
        PrintWriter pw = new PrintWriter(
                new BufferedOutputStream(
                        new FileOutputStream("testdata/printwriter.txt",true)
                ),true);

        pw.println("hahha");
        pw.println(true);
        pw.close();
    }
}

RandomAccessFile文件分割和合并

  • RandomAccessFile的seek方法可以指定从哪个位置开始读取
import java.io.*;
import java.util.ArrayList;

/**
 * 将文件按字节切分和合并
 */
public class TestRandomAccess {
    public static void main(String[] args) throws IOException {
        String path = "testdata/print.txt";
        System.out.println("id--->起始位置--->大小---内容\n");
        //切分文件,一个文件10个字节
        read3(path,10);
        //合并文件,先把待合并的文件放到一个列表中
        ArrayList<String> paths = new ArrayList<>();
        for(int i =0;i<7;i++){
            paths.add("testdata/Split"+i+".txt");
        }
        System.out.println(paths);
        //合并
        merge(paths,"testdata/merge.txt");


    }

    static void read3(String path,int size)throws IOException{
        /**
         * 对文件分块读取
         * 传入文件路径,一块读多少个字节
         */
        File src = new File(path);
        RandomAccessFile raf = new RandomAccessFile(src,"r");
        //文件的总字节数
        long length = src.length();
        //文件分多少块
        int num = (int)Math.ceil(length*1.0/size);
        //起始位置
        int beginPos = 0;
        int actualSize = (int)(size>length?length:size); //每块大小
        //对每一块进行遍历读取
        for(int i = 0;i < num;i++){
            beginPos = i*size;
            if(i == num-1){
                //最后一块
                actualSize = (int)length;
            }else{
                actualSize = size;
                length -= actualSize;
            }
            System.out.print(i+"--->"+beginPos+"--->"+actualSize+"---");
            split(raf,i,beginPos,actualSize);
            System.out.println();
        }
        raf.close();
        src=null;
    }

    static void split(RandomAccessFile raf,int id,int beginPos,int size)throws IOException{
        /**
         * 分块读取的函数
         * 传入文件路径,第几块,起始位置,读多少个字节
         */
        //输出到文件
        RandomAccessFile out = new RandomAccessFile(new File("testdata/Split"+id+".txt"),"rw");
        byte[] data = new byte[size];
        int len = -1;
        raf.seek(beginPos); //读文件的起始位置,以字节为单位,从0开始
        while ((len = raf.read(data))!=-1){
            if(size > len){
                String str = new String(data,0,len);
                System.out.print(str);
                out.write(data,0,len); //输出到文件
                size -= len;
            }else{
                String str = new String(data,0,size);
                System.out.print(str);
                out.write(data,0,size); //输出到文件
                break;
            }
            out.close(); //释放资源
        }
    }
    
    public static void merge(ArrayList<String> paths , String outpath) throws IOException {
        /**
         * 将切分的文件合并,
         * paths输入路径的ArrayList
         * outpath为输出路径
         */
        OutputStream os = new BufferedOutputStream(new FileOutputStream(outpath,true));
        for(int i = 0;i<paths.size();i++){
            InputStream is = new BufferedInputStream(new FileInputStream(paths.get(i)));
            byte[] data = new byte[1024];
            int len = -1;
            while ((len = is.read(data)) != -1){
                os.write(data,0,len);
            }
            os.flush();
            is.close();
        }
        os.close();
    }
}

SequenceInputStream

Apache IOUtils和FileUtils

文件或文件夹的大小,列出文件

import org.apache.commons.io.*;
import org.apache.commons.io.filefilter.*;

import java.io.File;
import java.util.Collection;

/**
 * 文件或文件夹大小
 * 列出文件
 * 列出指定后缀的文件
 */

public class TestCommonsIO {
    public static void main(String[] args) {
        //文件大小
        long length = FileUtils.sizeOf(new File("testdata/print.txt"));
        System.out.println(length);
        //文件夹大小
        long sizeDir = FileUtils.sizeOf(new File("testdata"));
        System.out.println(sizeDir);
        //列出文件,非空,一层文件夹的所有非空文件
        Collection<File> files = FileUtils.listFiles(new File("testdata"),
                EmptyFileFilter.NOT_EMPTY,null);
        for(File f : files){
            System.out.println(f.getAbsolutePath());
        }
        System.out.println("--------");
        //列出多层文件
        Collection<File> files2 = FileUtils.listFiles(new File("testdata"),
                EmptyFileFilter.NOT_EMPTY, DirectoryFileFilter.INSTANCE);
        for(File f : files2){
            System.out.println(f.getAbsolutePath());
        }
        System.out.println("--------");
        //列出txt结尾的
        Collection<File> files3 = FileUtils.listFiles(new File("testdata"),
                new SuffixFileFilter("txt"), DirectoryFileFilter.INSTANCE);
        for(File f : files3){
            System.out.println(f.getAbsolutePath());
        }
        System.out.println("--------");
        //列出html或obj结尾的
        IOFileFilter filter  = FileFilterUtils.or(new SuffixFileFilter("html"),new SuffixFileFilter("obj"));
        Collection<File> files4 = FileUtils.listFiles(new File("testdata"),
                filter, DirectoryFileFilter.INSTANCE);
        for(File f : files4){
            System.out.println(f.getAbsolutePath());
        }
    }
}

读写文本文件

  • 对文本文件的读写
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class TestCommonIORead {
    public static void main(String[] args) throws IOException {
        //将文本文件读取为字符串
        File f = new File("testdata/print.txt");
        String data = FileUtils.readFileToString(f,"UTF-8");
        System.out.println(data);

        //读入字节数组
        byte[] bytes = FileUtils.readFileToByteArray(f);
        System.out.println(bytes.length);

        //逐行读取,一行一个元素
        List<String> msgs = FileUtils.readLines(f,"UTF-8");
        for (String s:msgs) {
            System.out.println(s);
        }
        //逐行读取的迭代器
        LineIterator iter = FileUtils.lineIterator(f,"UTF-8");
        while (iter.hasNext()){
            String da = iter.nextLine();
            System.out.println(da);
        }

        //写出文件
        File wf = new File("testdata/abc.txt");
        FileUtils.write(wf,"云计算\n","UTF-8",true);
        //写文件方法2
        FileUtils.writeStringToFile(wf,"物联网\n","UTF-8",true);
        //写出字节数组
        FileUtils.writeByteArrayToFile(wf,"新年\n".getBytes("UTF-8"),true);
        //写出容器
        List<String> list = new ArrayList<>();
        list.add("haha");
        list.add("秋水共长天一色");
        //---为元素之间的连接符 a--b--c--
        FileUtils.writeLines(wf,list,"---",true);

    }
}

复制文件

  • 一行完成复制
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

/**
 * CommonIO复制文件
 */
public class TestComminIOCopy {
    public static void main(String[] args) throws IOException {
        File src = new File("src/images/desk.jpg");
        File dst = new File("testdata/A/desk2.jpg");
        //复制文件
        FileUtils.copyFile(src,dst);
        //复制文件到目录,目标目录不存在则会创建
        FileUtils.copyFileToDirectory(src,new File("testdata/B"));
        //复制文件夹的内容到文件夹,src文件夹中的内容复制过去
        FileUtils.copyDirectory(new File("testdata/B"),new File("testdata/C"));
        //复制文件夹到文件夹
        FileUtils.copyDirectoryToDirectory(new File("testdata/B"),new File("testdata/D"));

        //复制url内容到文件
        FileUtils.copyURLToFile(new URL("http://www.baidu.com"),new File("testdata/a.html"));
        //复制URL到字符串
        String ms = IOUtils.toString(new URL("http://www.baidu.com"),"UTF-8");
        System.out.println(ms);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章