亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747


「JAVA」字節流、字符流、緩沖流、轉換流、內存流、字符編碼

文件流、字節流、字符流、緩沖流、轉換流、內存流

文件流: 在JAVA 中,文件流負責操作文件,包括讀取和寫入;

FileInputStream        // 文件的字節輸入流;
FileOutputStream     // 文件的字節輸出流;
FileReader                 // 文件的字符輸入流;
FileWriter                  // 文件的字符輸出流;

FileInputStream 和 FileOutputStream的父類分別是InputStream和OutputStream,都是字節流,以面向字節的形式提供IO操作。FileReader 和 FileWriter的父類則是Reader和Writer,都是字符流,字符流以面向字符提供IO操作,同時,字符流兼容Unicode,能夠提供更好的國際化支持。

在讀取數據時,字節流的數據存儲單位是字節,在接收字節流數據時,會新建一個字節類型的數組(byte[])來接收讀取的數據;字符流的數據存儲單位是字符,在接收字符流數據時,會新建一個字符類組(char[])的數據來接收讀取的數據。

InputStream 和 OutputStream

InputStream:

InputStream及其子類的作用是用來表示不同數據源輸入數據的類,其中封裝了用于從數據源中讀取數據的操作。這些數據源包括:

  • 字節數組:byte[];
  • String對象;
  • 資源文件:File;
  • 資源管道;
  • 其他流組成的流序列;
  • 其他數據源,如網絡資源;

InputStream子類:

  • ByteArrayInputStream:將內存的緩沖區當作數據源輸入;
  • StringBufferInputStream:將String轉換成InputStream;
  • FileInputStream:從本地文件中讀取數據;
  • PipedInputStream:資源管道的輸入端,也是PipedOutputStream的輸入源;
  • SequenceInputStream:能夠將2個或者以上的InputStream合并成一個單一的InputStream;
  • FileterInputStream:為文件資源讀取提供篩選功能;

 

OutputStream:

OutputStream及其子類的作用是用來表示數據輸出將要去向的目標,比如:文件、資源管道、字節數組等。OutputStream也是因不同的目標有不同的子類:

  • ByteArrayOutputStream:在內存中創建緩沖區,所有輸出的數據都會暫存在緩沖區中;
  • FileOutputStream:將數據寫出到文件中;
  • PipedOutputStream:作為PipedInputStream的輸出端,與PipedInputStream一起實現資源的“管道化”;
  • FileterOutputStream:為文件資源寫出提供篩選功能;

 

Reader 和 Writer

字符流有著和字節流近乎一樣的功能,每個字節流api都能在字符流中找到與之相對應的,而且,字符流比字節流有著更好的性能;盡管如此,字符流的設計并不是為了取代字節流,相反,二者同時存在,相輔相成。

Reader 和 Writer及其子類都提供了對Unicode的支持,這是他們和InputStream與OutputStream系拓展最大的不同,詳細如下圖所示:

「JAVA」字節流、字符流、緩沖流、轉換流、內存流、字符編碼

字節流和字符流的api對應

 

文件過濾器

Java IO中提供了過濾器:FilterInputStream和FilterOutputstream,用于篩選特定的輸入流和輸出流。因為FilterInputStream和FilterOutputstream也是自InputStream與OutputStream繼承而來,所以他們都可以讀寫來自InputStream與OutputStream的數據。

FilterInputStream子類:

  • DataInputStream:用于從流中讀取基本類型的數據,比如:char、int、long等,往往與DataOutputStream配合使用;
  • BufferedInputStream:代表“緩沖區”,可以將數據暫存在緩沖區,使用它可以防止每次讀取都進行實際的寫操作;
  • LineNumberInputStream:追蹤輸入流中的行號,可做調試用;
  • PushbackInputStream:能彈出一個字節的緩沖區,能夠將文件的最后一個字符返回(操作系統使用-1表示磁盤文件的結尾標記),通常作為編譯器的掃描器,往往被編譯器調用;

 

FilterOutputStream子類:

  • DataOutputStream:用于從流中寫出基本類型的數據,比如:char、int、long等,往往與DataInputStream配合使用;
  • PrintStream:用于格式化輸出,比如:java 的運行控制臺打印;能夠與DataOutputStream相互配合使用:DataOutputStream負責數據的存儲,PrintStream負責數據的顯示;
  • BufferedOutputStream:代表“緩沖區”,可以將數據暫存在緩沖區,使用它可以防止每次都進行實際的寫操作;可以使用flush()方法將緩沖區數據一次性寫出;

同樣,在Reader 和 Writer中也提供了與之對應的類,詳細如下:

「JAVA」字節流、字符流、緩沖流、轉換流、內存流、字符編碼

文件過濾器 子類

 

字節流

字節流又分字節輸入流(InputStream)和字節輸出流(OutputStream),分別對應讀和寫;

字節輸入流:FileInputStream,字節輸入流的使用案例代碼如下:

import java.io.*;

/**
 * 案例:使用字節流完成文件拷貝任務。
 */
public class StreamCopyDemo {

    public static void main(String[] args) throws Exception {

        // 分別創建文件的源對象和目標對象
        File src = new File("stream.txt");
        File target = new File("stream_copy.txt");
        // 創建輸入和輸出管道
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(target);
        // 讀取/寫出數據
        byte[] buffer = new byte[1024]; // 設置每次讀取的字節數
        int len = -1; // 讀取到的字節總數
        while ((len = in.read(buffer)) != -1) {

            // 寫出數據
            out.write(buffer, 0, len);
        }
        // 關閉輸入/輸出管道
        in.close();
        out.close();

    }

}

字節輸入流在讀取數據時使用的是read()方法,該方法還有另外的重載方法:

void read(int b); 
// 讀取單個字節

void read(byte[] b); 
// 讀取多個字節,并存儲到(byte[] b)中

void read(byte[] b, int off, int len); 
// 讀取多個字節,并存儲到(byte[] b)中,從數組b的off索引為止開始存儲

 

字節輸出流:FileOutputStream,字節輸出流的使用案例代碼如下:

import java.io.*;

/**
 * 案例:使用字節流完成文件拷貝任務。
 */
public class StreamCopyDemo {

    public static void main(String[] args) throws Exception {

        // 分別創建文件的源對象和目標對象
        File src = new File("stream.txt");
        File target = new File("stream_copy.txt");
        // 創建輸入和輸出管道
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(target);
        // 讀取/寫出數據
        byte[] buffer = new byte[1024]; // 設置每次讀取的字節數
        int len = -1; // 讀取到的字節總數
        while ((len = in.read(buffer)) != -1) {

            // 寫出數據
            out.write(buffer, 0, len);
        }
        // 關閉輸入/輸出管道
        in.close();
        out.close();

    }

}

與字節輸入流在讀取數據時使用的read()方法相對應的,字節輸出流也提供了對應的寫出數據的方法:write(),該方法也有一些重載方法:

out.write(int b); 
// b 寫入文件的字節

out.write(byte[] b); 
// b 要寫入文件的數據,類型為byte數組

out.write(byte[] b, int off, int len); 
// 把字節數組中的從off索引開始的len個字節寫到文件中

注意:字節流讀寫中的數據類型是字節數據類型(byte[])。

 

案例1,使用字節流完成文件拷貝任務。

import java.io.*;

/**
 * 案例:使用字節流完成文件拷貝任務。
 */
public class StreamCopyDemo {

    public static void main(String[] args) throws Exception {

        // 分別創建文件的源對象和目標對象
        File src = new File("stream.txt");
        File target = new File("stream_copy.txt");
        // 創建輸入和輸出管道
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(target);
        // 讀取/寫出數據
        byte[] buffer = new byte[1024]; // 設置每次讀取的字節數
        int len = -1; // 讀取到的字節總數
        while ((len = in.read(buffer)) != -1) {
            // 寫出數據
            out.write(buffer, 0, len);
        }
        // 關閉輸入/輸出管道
        in.close();
        out.close();
    }
}

 

字符流

字符流又分字符輸入流(Reader)和字符輸出流(Writer),分別對應文件讀和寫;需要注意的是:字符流讀寫中的數據類型是字符數據類型(char[]),區別于字節流中的字節類型(byte[])。

字符輸入流,FileReader,字符輸入流的使用案例代碼如下:

import java.io.File;
import java.io.FileReader;
import java.io.Reader;

/**
 * 文件的字符輸入流案例
 */
public class FileReaderDemo {

    public static void main(String[] args) throws Exception {
        // 創建資源對象
        File src = new File("file_reader.txt");
        // 創建文件字符輸入流
        Reader reader = new FileReader(src);
        char[] buffer = new char[1024]; // 每次讀取1024個字符
        int len = -1; // 當前讀取到的字符長度
        while ((len = reader.read(buffer))!= -1) {
          	String line = new String(line, 0, len);
            System.out.println(line);
        }
        // 關閉字符輸入流
        reader.close();
    }
}

字符輸入流在讀取數據時使用的是read()方法,該方法還有另外的重載方法:

int read(); 
// 每次讀取一個字符,直至文件末尾,返回-1為止int read(char[] buffer); // 每次都能讀物多個字符,并把讀取到的字符存儲到buffer中

 

字符輸出流,FileWriter,字符輸出流的使用案例代碼如下:

import java.io.*;

/**
 * 文件的字符輸出流案例
 */
public class FileWriterDemo {

    public static void main(String[] args) throws Exception {
        // 創建目標對象
        File target = new File("file_writer.txt");
        // 創建文件字符輸出流
        Writer writer = new FileWriter(target);
        writer.write("dkgfkdsfowmsdfmowemfsdmfkemfkmfd");
        writer.flush();
        // 關閉字符輸出流
        writer.close();
    }

}

字符輸出流在讀取數據時使用的是write()方法,該方法還有另外的重載方法:

void write(int c); 
// 向文件中寫出一個字符

void write(char[] buffer);
// 向文件中寫出多個字符(char[] buffer)

void write(char[] buffer, int off, int len);
// 向文件中寫出多個字符(char[] buffer),從off位置開始,長度為len

void write(String str);
// 向文字中寫出一個字符串

 

案例2,使用字符流完成文件拷貝任務

import java.io.*;

/**
 * 案例:使用字符流完成文件拷貝任務。
 */
public class FileCopyDemo {

    public static void main(String[] args) throws Exception {
        // 創建文件源對象和目標對象
        File src = new File("file_reader.txt");
        File target = new File("file_reader_copy.txt");
        // 創建輸入流和輸出流
        Reader reader = new FileReader(src);
        Writer writer = new FileWriter(target);
        // 文件讀和寫
        char[] buffer = new char[1024];
        int len = -1;
        while((len = reader.read(buffer)) != -1) {
            writer.write(buffer, 0, len);
        }
        // 關閉輸入流和輸出流
        reader.close();
        writer.close();
    }

}
「JAVA」字節流、字符流、緩沖流、轉換流、內存流、字符編碼

文件拷貝

 

案例3,使用流完成Java 代碼動態編譯、運行

import java.io.*;

/**
 * 案例3,使用流完成Java 代碼動態編譯、運行
 */
public class EvalDemo {

    public static void main(String[] args) {
        String code = "System.out.println("Eval Java");";
        try {
						// 構建java代碼
            buildJavaCode(code);
						// 編譯Java 代碼
						compileJavaCode();
						// 運行Java 代碼
						runJavaCode();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
	
	/**
	 * 構建java代碼
	 */
	private static void buildJavaCode(String code) throws Exception {
				// 拼接Java 主函數
        StringBuilder builder = new StringBuilder(80);
        builder.Append("public class Eval {");
        builder.append("public static void main(String[] args) {");
        builder.append(code);
        builder.append("}");
        builder.append("}");
        // 保存拼接好的java代碼到文件中
        OutputStream out = new FileOutputStream("Eval.java");
        out.write(builder.toString().getBytes("UTF-8"));
        out.close();
	}

	/**
	 * 編譯Java 代碼
	 */
    private static void compileJavaCode() throws Exception {
        
        // 調用javac 編譯保存的java文件
        Process javacProcess = Runtime.getRuntime().exec("javac Eval.java");
        // 讀取編譯錯誤結果,并輸出
        InputStream error = javacProcess.getErrorStream();
        byte[] buffer = new byte[1024];
        int len = -1;
        while ((len = error.read(buffer)) != -1) {
            String msg = new String(buffer, 0, len);
            System.out.println("Eval 編譯:" + msg);
        }
        // 關閉javac 編譯進程
        error.close();

    }
	
	/**
	 * 運行Java 代碼
	 */
    private static void runJavaCode() throws Exception {

        // 調用java 運行編譯好的java字節碼文件
        Process javaProcess = Runtime.getRuntime().exec("java Eval");
        // 讀取java字節碼文件的運行信息。并打印輸出
        InputStream info = javaProcess.getInputStream();
        len = -1;
        buffer = new byte[1024];
        while ((len = info.read(buffer)) != -1) {
            String msg = new String(buffer, 0, len);
            System.out.println("Eval 運行: " + msg);
        }
        info.close();
        // 刪除java問價和class文件
        new File("Eval.java").delete();
        new File("Eval.class").delete();
    }

}

 

緩沖區

在上述的字符輸出流的使用案例中,使用了flush()方法,該方法有何作用呢?

因為計算機訪問外部設備(磁盤文件)時,要比直接訪問內存慢很多,如果每次調用write()方法都要直接把數據寫出到磁盤文件中,CPU會花更多的時間,計算機執行性能會大大降低。

因此,我們可以準備一個內存緩沖區,程序每次調用write()方法時,會將數據先寫到內存緩沖區中,暫存于緩沖區中;當內存緩沖區滿后,系統才把緩沖區中暫存的數據一次性寫出到磁盤文件中。這樣就能減少直接操作本地文件系統的頻率,使得系統性能得以提升。

 

flush()方法

flush(),刷新操作,輸出流中都有flush方法。該方法的作用正是把緩沖區中暫存的數據一次性寫出到磁盤文件中。

 

使用緩沖區的好處:

  1. 提高CPU使用率,提高系統的執行性能;
  2. 有機會回滾寫入的數據,能避免一定的臟數據;
  3. 緩沖區大小一般使用容量整數倍,可以提高IO性能;

 

對于字節流,flush方法不是都有作用(部分字節流才有作用),對于字符流、緩沖流則都起作用。如果我們調用close方法關閉系統資源,那么,系統在關閉資源前,會先調用flush方法。

.

資源關閉

資源關閉分為手動關閉和自動關閉兩種:

  • 手動關閉:手動調用流的close()方法;
  • 自動關閉:不需要手動調用close方法,不過,前提是資源對象實現了AutoClose接口;
import java.io.*;

/**
 * 資源關閉案例
 */
public class StreamCloseDemo {

    public static void main(String[] args) {
		
				// 資源手動關閉
				closeManual();
		
				// 資源自動關閉
				closeAuto();
    }
	
	/**
	  * 資源手動關閉
	  */
    private static void closeManual() {

        InputStream in = null;
        OutputStream out = null;
        try {
            // 分別創建文件的源對象和目標對象
            File src = new File("stream.txt");
            File target = new File("stream_copy.txt");
            // 創建輸入和輸出管道
            in = new FileInputStream(src);
            out = new FileOutputStream(target);
            // 讀取/寫出數據
            byte[] buffer = new byte[1024]; // 設置每次讀取的字節數
            int len = -1; // 讀取到的字節總數
            while ((len = in.read(buffer)) != -1) {

                // 寫出數據
                out.write(buffer, 0, len);
            }

        } catch (Exception e ) {
            e.printStackTrace();
        } finally {
            // 關閉輸入/輸出管道
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

	/**
	  * 資源自動關閉
	  */
    private static void closeAuto() {
        // 分別創建文件的源對象和目標對象
        File src = new File("stream.txt");
        File target = new File("stream_copy.txt");

        try (// 創建輸入和輸出管道
             InputStream in = new FileInputStream(src);
             OutputStream out = new FileOutputStream(target);
        ) {
            // 讀取/寫出數據
            byte[] buffer = new byte[1024]; // 設置每次讀取的字節數
            int len = -1; // 讀取到的字節總數
            while ((len = in.read(buffer)) != -1) {

                // 寫出數據
                out.write(buffer, 0, len);
            }

        } catch (Exception e ) {
            e.printStackTrace();
        }
    }

}

 

包裝類/緩沖流

字節緩沖輸入流,BufferedInputStream,案例代碼如下:

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * 字節緩沖輸入流
 */
public class BufferedInputStreamDemo {

    public static void main(String[] args) throws Exception {
        // 字節輸入流
        InputStream in = new FileInputStream("stream.txt");
        // 字節緩沖輸入流
        BufferedInputStream bis = new BufferedInputStream(in);
        // 寫出到文件的內容
        String content = "BufferedOutputStream";
        // 通過字節緩沖輸入流讀取數據
        byte[] buffer = new byte[1024];
        int len = -1;
        while ((len = bis.read(buffer)) != -1) {
            String line = new String(buffer, 0, len);
            System.out.println(line);
        }
        in.close();
        bis.close();
    }

}

 

字節緩沖輸出流,BufferedOutputStream,案例代碼如下:

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

/**
 * 字節緩沖輸出流
 */
public class BufferedOutputStreamDemo {

    public static void main(String[] args) throws Exception {
        // 字節輸出流
        OutputStream out = new FileOutputStream("stream.txt", true);
        // 字節緩沖輸出流
        BufferedOutputStream bos = new BufferedOutputStream(out);
        // 寫出到文件的內容
        String content = "BufferedOutputStream";
        // 通過字節緩沖輸出流寫出數據
        bos.write(content.getBytes());
        out.close();
        bos.close();
    }

}

 

字符緩沖輸入流,BufferedReader,案例代碼如下:

import java.io.*;

/**
 * 字符緩沖輸入流
 */
public class BufferedReaderDemo {

    public static void main(String[] args) throws Exception {
        // 字符輸入流
        Reader reader = new FileReader("stream.txt");
        // 字符緩沖輸入流
        BufferedReader br = new BufferedReader(reader);
        // 讀取文件內容
        String line = null;
        while ((line = br.readLine()) != null) {

            System.out.println(line);
        }
        // 關閉流
        reader.close();
        br.close();
    }

}

 

字符緩沖輸出流,BufferedWriter,案例代碼如下:

import java.io.*;

/**
 * 字符緩沖輸出流
 */
public class BufferedWriterDemo {

    public static void main(String[] args) throws Exception {
        // 字符輸出流
        Writer writer = new FileWriter("stream.txt");
        // 字符緩沖輸出流
        BufferedWriter bw = new BufferedWriter(writer);
        bw.write("這世界很美好");
        bw.newLine();
        bw.write("世界也很美好");
        // 關閉流
        writer.close();
        bw.close();
    }

}

 

字節流、緩沖流性能測試比較:

import java.io.*;

/**
 * 字節流、緩沖流性能測試
 */
public class BufferedDemo {
	
      public static void main(String[] args) {

        File src = new File("stream.txt");
        File target = new File("stream_copy.txt");

        try {
            // 字節流性能測試
            testSingleByteStream(src, target);
            testSingleBufferedStream(src, target);
            // 緩沖流性能測試
            testMultiByteStream(src, target);
            testMultiBufferedStream(src, target);
        } catch (Exception e) {
          e.printStackTrace();
        }
    }

    /**
     * 字節流性能測試
     * 每次讀寫都是一個字節
     *
     */
    private static void testSingleByteStream(File src, File target) throws Exception {
        long begin = System.currentTimeMillis();
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(target);
        int len = -1;
        while ((len = in.read()) != -1) {
            out.write(len);
        }
        in.close();
        out.close();
        long end = System.currentTimeMillis();
        System.out.println("SingleByteStream 耗費:" + (end - begin) + "ms");
    }
    
    /**
     * 緩沖流性能測試
     * 每次讀寫都是一個字節
     *
     */
    private static void testSingleBufferedStream(File src, File target) throws Exception {
        long begin = System.currentTimeMillis();
        // 創建文件流
        InputStream srcStream = new FileInputStream(src);
        OutputStream targetStream = new FileOutputStream(target);
        // 穿甲緩沖流
        InputStream in = new BufferedInputStream(srcStream);
        OutputStream out = new BufferedOutputStream(targetStream);
        int len = -1;
        while ((len = in.read()) != -1) {
            out.write(len);
        }
        // 關閉流
        in.close();
        out.close();
        long end = System.currentTimeMillis();
        System.out.println("SingleBufferedStream 耗費:" + (end - begin) + "ms");
    }

    /**
     * 字節流性能測試
     * 使用多字節讀寫
     *
     */
    private static void testMultiByteStream(File src, File target) throws Exception {
        long begin = System.currentTimeMillis();
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(target);
        int len = -1;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
        in.close();
        out.close();
        long end = System.currentTimeMillis();
        System.out.println("MultiByteStream 耗費:" + (end - begin) + "ms");
    }

    /**
     * 緩沖流性能測試
     * 使用多字節讀寫
     *
     */
    private static void testMultiBufferedStream(File src, File target) throws Exception {
        long begin = System.currentTimeMillis();
        // 創建文件流
        InputStream srcStream = new FileInputStream(src);
        OutputStream targetStream = new FileOutputStream(target);
        // 穿甲緩沖流
        InputStream in = new BufferedInputStream(srcStream);
        OutputStream out = new BufferedOutputStream(targetStream);
        int len = -1;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
        // 關閉流
        in.close();
        out.close();
        long end = System.currentTimeMillis();
        System.out.println("MultiBufferedStream 耗費:" + (end - begin) + "ms");
    }
}

上述測試運行結果如下:

SingleByteStream 耗費:3610ms
SingleBufferedStream 耗費:31ms
MultiByteStream 耗費:16ms
MultiBufferedStream 耗費:0ms

性能孰高孰低,測試結果已經很能說明問題了。

 

轉換流

由于字節流和字符流同時存在,有時候會把二者結合起來使用,甚至在二者之間實現轉換;為了實現這樣的功能,Java IO中提供了字節流和字符流的適配器:

  • InputStreamReader:可以把InputStream轉換為Reader;
  • OutputStreamWriter:可以把OutputStream轉換為Writer;

以下便是這個適配器—“轉換流”的使用案例,案例通過文件的拷貝操作來體現,在讀寫的過程中,均使用了特定編碼。案例代碼實現如下:

import java.io.*;

/**
 * 轉換流案例
 */
public class StreamConvertDemo {

    public static void main(String[] args) throws Exception {
        // 創建文件對象
        File src = new File("stream.txt");
        File target = new File("stream_copy.txt");
        // 創建文件流
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(target);
        // 創建字節/字符轉換流
        Reader reader = new InputStreamReader(in, "UTF-8");
        Writer writer = new OutputStreamWriter(out, "UTF-8");
        // 操作字符流完成文件讀寫
        char[] buffer = new char[1024];
        int len = -1;
        while ((len = reader.read(buffer)) != -1) {

            writer.write(buffer, 0, len);
        }
        // 關閉流
        in.close();
        out.close();
        reader.close();
        writer.close();
    }

}

為什么只有字節轉字符流,卻沒有字符轉字節流呢?原因也很簡單:

  • 字節流可以操作一切文件,包括純文本文件、二進制文件;
  • 字符流是對字節流的增強,是用來操作純文本使用的;

字節流和字符流之間并不對等,無法實現轉換,就比如C++程序可以運行C程序,但C程序卻不能運行C++程序。

數組流/內存流

面向字節的數組流/內存流:ByteArrayInputStream和ByteArrayOutputStream;該“流”會把數據暫存到內存中,以便實時讀寫,讀寫時使用的字節類型(byte[]);

  • ByteArrayInputStream:把數據從程序輸出到內存中;
  • ByteArrayOutputStream:把數據從內存讀取到程序中;

代碼案例如下:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/**
 * 面向字節的數組流/內存流
 */
public class ByteArrayDemo {

    public static void main(String[] args) throws Exception {

        String content = "dfjdslkfjdlsfjld";
        // 字節數組輸出流:程序 -> 內存
        ByteArrayOutputStream bas = new ByteArrayOutputStream();
        bas.write(content.getBytes());

        // 緩存字節區
        byte[] data = bas.toByteArray();

        // 字節數組輸入流:內存 -> 程序
        ByteArrayInputStream bai = new ByteArrayInputStream(data);
        byte[] buffer = new byte[1024];
        int len = -1;
        while ((len = bai.read(buffer)) != -1) {
            String line = new String(buffer, 0, len);
            System.out.println(line);
        }
				// 關閉流
        bas.close();
        bai.close();
    }

}

 

面向字符的數組流/內存流,CharArrayReader和CharArrayWriter,該“流”會把數據暫存到內存中,以便實時讀寫,讀寫時使用的字符類型(char[]);

代碼案例如下:

import java.io.CharArrayReader;
import java.io.CharArrayWriter;

/**
 * 面向字符的數組流/內存流
 */
public class CharArrayDemo {

    public static void main(String[] args) throws Exception {
        // 字符數組輸出流
        CharArrayWriter writer = new CharArrayWriter();
        writer.write("這世界很美好");

        char[] data = writer.toCharArray();
        // 字符數組輸入流
        CharArrayReader reader = new CharArrayReader(data);
        char[] buffer = new char[1024];
        int len = -1;
        while ((len = reader.read(buffer)) != -1) {
            String line = new String(buffer, 0, len);
            System.out.println(line);
        }
        // 關閉流
        writer.close();
        reader.close();
    }

}

 

面向字符串的內存流,StringReader/StringWriter,把數據臨時存儲到字符串中,也同樣是在內存中,但數據的類型是字符串;

案例代碼如下:

import java.io.StringReader;
import java.io.StringWriter;

/**
 * 面向字符串的內存流
 */
public class StringWriterReaderDemo {

    public static void main(String[] args) throws Exception {
        // 字符串輸出流
        StringWriter stringWriter = new StringWriter();
        stringWriter.write("這世界很美好");
        stringWriter.write("社會也很美好");
        System.out.println(stringWriter.toString());

        // 字符串輸入流
        StringReader stringReader = new StringReader(stringWriter.toString());
        char[] buffer = new char[1024];
        int len = -1;
        while ((len = stringReader.read(buffer)) != -1) {
            String line = new String(buffer, 0, len);
            System.out.println(line);
        }

        // 關閉流
        stringReader.close();
        stringWriter.close();
    }

}

 

合并流

合并流,SequenceInputStream:能夠將2個或者以上的InputStream合并成一個單一的InputStream,進而進行合并操作;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;

/**
 * 合并流
 */
public class SequenceInputStreamDemo {

    public static void main(String[] args) throws Exception {
        // 創建輸入隊列流
        SequenceInputStream seqIn = new SequenceInputStream(
                new FileInputStream("stream1.txt"),
                new FileInputStream("stream2.txt"),
								new FileInputStream("stream3.txt"));
        byte[] buffer = new byte[1024];
        int len = -1;
        while ((len = seqIn.read(buffer)) != -1) {
            String line = new String(buffer, 0, len);
            System.out.println(line);
        }
        seqIn.close();
    }

}

 

字符編碼

字符編碼的發展歷程:

階段1:計算機只認識數字0和1,計算機里的一切數據都是以數字來表示;因為英文符號有限,所以規定使用的字節的最高位是0,每一個字節都是以0~127之間的數字來表示,比如:A對應65,a對應97..這就是美國標準信息交換碼-ASCII

階段2:隨著計算機在全球的普及,很多國家和地區都把自己的字符引入了計算機中,比如漢字;但是ASCII中的一個字節能表示數字范圍太小,不能包含所有的中文漢字,所以就規定使用兩個字節來表示一個漢字;

所以決定,原有的ASCII字符的編碼保持不變,仍然使用一個字節表示;為了區別一個中文字符與兩個ASCII碼字符:

  • 中文字符的每個字節最高位規定為1(中文的二進制是負數),這個規范就是GB2312編碼;
  • 后來在GB2312的基礎上增加了更多的中文字符,比如簡體中文,GBK應運而生;

階段3:新的問題產生了,在中國是認識漢字的,支持GBK編碼,但是如果把GBK編碼的漢字傳遞給其他國家,該國家的編碼表中沒有收錄該漢字的字符,故不能正常顯示,很容易就出現了亂碼。

為了解決各個國家因為本地化字符編碼帶來的影響,把全世界所有的符號統一進行編碼-Unicode編碼;此時某一個字符在全世界任何地方都是固定的,比如字符:'哥',在任何地方都是以十六進制的54E5來表示。Unicode的每個編碼字符都占有2個字節大小。

 

常見的字符集:

  • ASCII:每個字符占一個字節,只能包含128個符號,不能表示漢字;
  • ISO-8859-1:每個字符占一個字節,收錄西歐語言,不能表示漢字;
  • ANSI:每個字符占兩個字節,在簡體中文的操作系統中,ANSI 就指的是 GB2312;
  • GB2312/GBK/GB18030:每個字符占兩個字節,中文專用編碼;
  • UTF-8:是一種針對Unicode的可變長度字符編碼,又稱萬國碼,是Unicode的實現方式之一,目前的應用率最高;
  • UTF-8 BOM:是微軟搞出來的編碼,默認占3個字節,使用率并不高;

編碼中的第一個字節仍與ASCII兼容,這使得原來處理ASCII字符的軟件無須或只須做少部份修改,即可繼續使用。因此,它逐漸成為電子郵件、網頁及其他存儲或傳送文字的應用中,優先采用的編碼。

互聯網工程工作小組(IETF)要求所有互聯網協議都必須支持UTF-8編碼。

 

存儲字母,數字和漢字

存儲字母和數字時無論是什么字符集都只占1個字節(因為和ASCII兼容),但是存儲漢字:GBK家族占兩個字節,UTF-8家族占3個字節。

存儲中文時,GBK和UTF-8都是OK的。

import java.util.Arrays;

/**
 * 字符編碼
 */
public class EncodingDemo {

    public static void main(String[] args) throws Exception {
        String str = "老夫不正經";
        // 以特定編碼格式編碼字符串
        byte[] data = str.getBytes("UTF-8");
        System.out.println(Arrays.toString(data));
        // 解碼字符串
        str = new String(data, "ISO-8859-1");
        System.out.println(str);
        // 此時,字符串str是亂碼:è??夫ä¸?æ­£ç»?
        // 解決方案便是,使用ISO-8859-1來讀取字節數據,然后使用UTF-8重新編碼
        data = str.getBytes("ISO-8859-1");
        System.out.println(Arrays.toString(data));
        str = new String(data, "UTF-8");
        System.out.println(str);
    }

}

 

小結

  1. InputStream 和 OutputStream
  2. Reader 和 Writer
  3. 文件過濾器
  4. 字節流
  5. 字符流
  6. 緩沖區
  7. 資源關閉
  8. 緩沖流
  9. 轉換流
  10. 內存流
  11. 合并流
  12. 字符編碼

完結,老夫雖不正經,但老夫一身的才華。

分享到:
標簽:JAVA
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定