1. 程式人生 > >javaI/O——字元編碼集、記憶體操作流、列印流、System類對I/O的支援

javaI/O——字元編碼集、記憶體操作流、列印流、System類對I/O的支援

一、字元編碼集
1.常用的字元編碼
我們以前在notpad++中編寫程式碼執行的時候,如果程式碼中有漢字,但是我們在編譯的時候並沒有使用-encoding UTF-8的時候就會出現亂碼的現象。這是因為字元編碼目的原因;因為不指定用什麼樣 的方式進行編碼的時候,對於漢字就識別不了,這樣的話就會出現錯誤。
那麼接下來我們就介紹一下常見的編碼到底有哪些:
(1)GBK、GB2312:表示的是國際編碼,GBK包含簡體中文和繁體中文,但是GB2312只包含簡體中文。
(2)UNICODE編碼:java提供的16進位制編碼,她可以描述任何一種文字資訊;但是它也有缺點,16進位制是兩個位元組,但是我們的字母是一個位元組,在編碼目的時候還是使用兩個位元組就會造成浪費。
(3)ISO8859-1:國際通過用編碼,但是所有的編碼需要進行轉換。
(4)UTF編碼:相當於結合了UNICODE、ISO8859-1,也就是說需要使用到16進位制文字使用UNICODE,但是如果是字母就使用ISO8859-1編碼,這樣就不會造成浪費。常用的就是UTF-8。
2.亂碼產生分析

//亂碼分析
public class Test {
    public static void main(String[] args) throws UnsupportedOperationException,IOException {
        OutputStream out=new FileOutputStream(Paths.get("E:","learn","javaio","a1").toFile());
        out.write("你好".getBytes("ISO8859-1"));
        out.close();
    }
}

之所以造成亂碼,是因為在解碼和編碼使用的字元編碼集不同。
二、記憶體操作流
1.記憶體流概念
記憶體操作流就是我們在進行I/O處理的時候物件是記憶體,就叫做記憶體流。前面我們學習的都是檔案流,在檔案流的操作中一定會產生一個檔案資料(不管這個檔案資料最後是否被保留)。
那我們的記憶體流一般處理的問題(出現的場景):當我們需要進行I/O檔案處理但是我們不希望產生檔案的時候就可以採用記憶體流了。
2.記憶體流分類
(1)位元組記憶體流:
ByteArrayInputStream、ByteArrayOutputStream
(2)字元記憶體流:
CharArrayReader、CharArrayWriter
(3)
位元組記憶體流輸出流的構造方法:
public ByteArrayInputStream(byte buf[ ])
這個引數是位元組型的陣列,就是在進行讀的時候將讀出來的內容方法這個陣列中。
位元組記憶體流輸入流的構造方法:
public ByteArrayOutputStream( )
3.記憶體流的繼承關係
eg:通過記憶體流實現大小寫轉換

//通過記憶體流實現大小寫的轉換
public class TestMerry {
    public static void main(String[] args) throws IOException {
        String msg="hello world";
        //通過記憶體實現小寫轉大寫
        InputStream input=new ByteArrayInputStream(msg.getBytes());//這一步的操作將msg的資料存到了記憶體中
        OutputStream output=new ByteArrayOutputStream();//將記憶體中的資料寫道檔案中
        int len=-1;
        while((len=input.read())!=-1){//這個read()方法表示一次只讀一個位元組
            //如果可以進入到這個說明還沒有讀完資料
            //將讀到的資料進行處理放到OutputStream類中
            //邊讀編寫,將讀出來的位元組經過轉換以後寫到檔案中
            output.write(Character.toUpperCase(len));
        }
        System.out.println(output);
        input.close();
        output.close();
    }
}

在這裡插入圖片描述
這個時候 我們是通過I/O操作來實現了大小寫的轉換但是沒有產生中間檔案。
2.記憶體流操作
我們也可以通過記憶體流操作來實現兩個檔案的合併。
eg:現在將data1.txt、data2.txt進行合併處理

//將兩個檔案進行合併
public class TestAddFile {
    public static void main(String[] args) throws IOException {
        File[] files=new File[]{
                new File("E:"+File.separator+"learn"+File.separator+"javaio"+File.separator+"data1.txt"),
                new File("E:"+File.separator+"learn"+File.separator+"javaio"+File.separator+"data2.txt")
        };
        String[] data=new String[2];
        for(int i=0;i<files.length;i++){
            data[i]=readFile(files[i]);//這是我們自己定義的一個方法
        }
        StringBuffer buf=new StringBuffer();
        String contentA[]=data[0].split(" ");
        String contentB[]=data[1].split(" ");
        for(int i=0;i<contentA.length;i++){
            buf.append(contentA[i]).append("(").append(contentB[i]).append(")").append(" ");
        }
        System.out.println(buf);
    }

    private static String readFile(File file) throws IOException {
        if(file.exists()){
            InputStream input=new FileInputStream(file);
            ByteArrayOutputStream bos=new ByteArrayOutputStream();
            int len=-1;
            byte[] data=new byte[10];
            while((len=input.read(data))!=-1){
                //將資料儲存在bos中
                bos.write(data,0,len);
            }
            bos.close();
            input.close();
            return new String(bos.toByteArray());
        }
        return null;
    }
}

三、列印流
1.列印流的概念
我們之前要向一個檔案輸入資訊的話用的是OutputStream,但是這個又缺陷:她要求所有的資料必須轉換為位元組陣列,那麼如果我們想要輸出的是Int,double這些型別就不方便了。列印流就是為就解決這個問題的。
我們的System.out.println()可以輸出任何型別的資料,下面我們自己來設計一個列印流,可以列印任意的基本資料型別。

//列印流
 class PrintUtil {
    private OutputStream out;
    public PrintUtil(OutputStream out){
        this.out=out;
    }
    //其核心功能就一個
    public void print(String str){
        try{
            this.out.write(str.getBytes());
        }catch(IOException e){
            e.printStackTrace();
        }
    }
    public void println(String str){
        this.print(str+"\n");
    }
    public void print(int data){
        this.print(String.valueOf(data));
    }
    public void println(int data){
        this.print(String.valueOf(data));
    }
    public void print(double data){
        this.print(String.valueOf(data));
    }
    public void println(double data){
        this.print(String.valueOf(data));
    }
}
public class Print{
    public static void main(String[] args) throws FileNotFoundException {
        PrintUtil p1=new PrintUtil(new FileOutputStream(new File("E:"+File.separator+"learn"+File.separator+"javaio"+File.separator+"data1.txt")));
        p1.print(27);
        p1.print("年號");
        p1.print(10.25);
        p1.println(15);
    }
}

在這裡插入圖片描述
2.系統提供的列印流
列印流和我們的輸入輸出流一樣,系統也是給我們提供的:(列印其本質就是往某個地方寫內容)
(1)位元組列印流:
PrintStream
(2)字元列印流:
PrintWriter
eg:使用我們的列印流實現輸出:

//使用列印流輸出
public class Print{
    public static void main(String[] args) throws FileNotFoundException {
        PrintWriter print1=new PrintWriter(new FileOutputStream(new File("E:"+File.separator+"learn"+File.separator+"javaio"+File.separator+"data1")));
        print1.print(12);
        print1.print('A');
        print1.print(12.05);
        print1.close();
    }
}

3.格式化輸出
這個和C語言的輸出有些相似:
public PrintStream printf(String format,object … args)
eg:格式化輸出

//格式化輸出
public class Print{
    public static void main(String[] args) throws FileNotFoundException {
        String name="小明";
        int age=20;
        double salary=1000.23456;
        PrintWriter printUtil=new PrintWriter(new FileOutputStream(new File("E:"+File.separator+"learn"+File.separator+"javaio"+File.separator+"data1.txt")));
        printUtil.printf("姓名:%s,年齡:%d,工資:%1.4f",name,age,salary);
        printUtil.close();
    }
}

在這裡插入圖片描述
四、System類對I/O的支援
在這有一個面試的考點,需要掌握:
1.System.out.println()
System:表示一個類(java.lang.System)
out:表示一個物件
println():是PrintStream類的成員方法,是out物件的方法
2.System.in.read()
System:是一個類(java.lang.System)
in:是一個物件
read():是InputStream類的成員方法,是in物件的方法。
3.System.err.println()