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);
    }
}

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