溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java編程思想學(xué)習(xí)筆記2 - 字節(jié)流和字符流

發(fā)布時(shí)間:2020-08-13 21:57:14 來源:ITPUB博客 閱讀:193 作者:zhuyiquan90 欄目:編程語言

《Thinking in Java》第18章的內(nèi)容是相當(dāng)豐富精彩的,也在網(wǎng)絡(luò)學(xué)習(xí)參考了很多前輩們的筆記,個(gè)人由于能力有限(畢竟和大神Bruce Eckel的能力相差甚遠(yuǎn)),將這一章的內(nèi)容分三個(gè)部分來寫,希望能夠慢慢品味和領(lǐng)悟Java IO的精粹: 1. 起步:File類

令我很吊胃口的一件事情是,當(dāng)我翻開圣經(jīng),想拜讀Java IO的精髓時(shí),Eckel告訴我,在學(xué)習(xí)真正用于流讀寫數(shù)據(jù)的類之前,讓我們先學(xué)習(xí)如何處理文件目錄問題(潛臺(tái)詞仿佛在說,對(duì)不起,菜鳥,你得從基礎(chǔ)班開始!)

File類:Java中File既能代表一個(gè)特定文件的名稱,又能代表一個(gè)目錄下的一組文件(相當(dāng)于Files)

我們要學(xué)會(huì)的是,如何從一個(gè)目錄下篩選出我們想要的文件?可以通過目錄過濾器FilenameFilter+正則表達(dá)式實(shí)現(xiàn)對(duì)文件的篩選:

import java.io.File; import java.io.FilenameFilter; import java.util.Arrays; import java.util.regex.Pattern; /**
 * 目錄過濾器
 * 顯示符合條件的File對(duì)象
 * @author 15070229
 *
 */ class DirFilter implements FilenameFilter { private Pattern pattern; public DirFilter (String regex) {
        pattern = pattern.compile(regex);
    } public boolean accept(File dir, String name) { return pattern.matcher(name).matches();
    }
} public class DirList { public static void main(String[] args) {
        File path = new File(".");
        String[] list; if(args.length == 0)
            list = path.list(); else list = path.list(new DirFilter(args[0]));
        Arrays.sort(list, String.CASE_INSENSITIVE_ORDER); for(String dirItem: list)
            System.out.println(dirItem);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

這個(gè)用匿名內(nèi)部類的方式來實(shí)現(xiàn)是更合適的,DirFilter在內(nèi)部實(shí)現(xiàn),使程序變的更小巧靈活:

* 通過內(nèi)部類方式實(shí)現(xiàn)的目錄列表器
 */ package c18; import java.io.File; import java.io.FilenameFilter; import java.util.Arrays; import java.util.regex.Pattern; public class DirList2 { public static FilenameFilter filter(final String regex) { //內(nèi)部類 return new FilenameFilter() { private Pattern pattern = Pattern.compile(regex); @Override public boolean accept(File dir, String name) { return pattern.matcher(name).matches();
            }
        };      
    } public static void main(String[] args) {
        File path = new File(".");
        String[] list; if(args.length == 0)
            list = path.list(); else list = path.list(new DirFilter(args[0]));
        Arrays.sort(list, String.CASE_INSENSITIVE_ORDER); for(String dirItem: list)
            System.out.println(dirItem);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

針對(duì)一些文件集上的常用操作我們可以封裝成一個(gè)工具類,比如:

/**
 * 目錄實(shí)用工具類
 * 本地目錄操作:local方法產(chǎn)生經(jīng)過正則表達(dá)式篩選的本地目錄的文件數(shù)組
 * 目錄樹操作:walk方法產(chǎn)生給定目錄下的由整個(gè)目錄樹中經(jīng)過正則表達(dá)式篩選的文件構(gòu)成的列表
 */ package c18; import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; public final class Directory { /**
     * 根據(jù)正則表達(dá)式,篩選產(chǎn)生File數(shù)組
     * @param dir
     * @param regex
     * @return */ public static File[] local(File dir, final String regex) { return dir.listFiles(new FilenameFilter() { private Pattern pattern = Pattern.compile(regex); @Override public boolean accept(File dir, String name) { return pattern.matcher(name).matches();
            }
        });
    } // 方法重載 public static File[] local(String path, final String regex) { return local(new File(path), regex);
    } /*
     * TreeInfo的使命是收集返回的目錄和文件信息
     */ public static class TreeInfo implements Iterable<File> { public List<File> files = new ArrayList<File>(); public List<File> dirs = new ArrayList<File>(); // public Iterator<File> iterator() { return files.iterator();
        } void addAll(TreeInfo other) {
            files.addAll(other.files);
            dirs.addAll(other.dirs);
        } public String toString() { return "dirs:" + PPrint.pformat(dirs) + "\n\nfiles: " + PPrint.pformat(files);
        }
    } /**
     * 遍歷目錄
     * @param start
     * @param regex
     * @return */ public static TreeInfo walk(String start, String regex) { return recurseDirs(new File(start), regex);
    } public static TreeInfo walk(File start, String regex) { return recurseDirs(start, regex);
    } public static TreeInfo walk(File start) { return recurseDirs(start, ".*");
    } public static TreeInfo walk(String start) { return recurseDirs(new File(start), ".*");
    } /**
     * 遞歸遍歷文件目錄,收集更多的信息(區(qū)分普通文件和目錄)
     * @param startDir
     * @param regex
     * @return */ static TreeInfo recurseDirs(File startDir, String regex) {
        TreeInfo result = new TreeInfo(); for(File item : startDir.listFiles()) { if (item.isDirectory()) { //持有目錄 result.dirs.add(item);
            } else if(item.getName().matches(regex)) //持有普通文件 result.files.add(item);
        } return result;
    } public static void main(String[] args) { // PPrint.pprint(Directory.walk(".").dirs); // for(File file : Directory.local(".", "T.*"))
            System.out.println(file);       
    }
} /**
 - 格式化打印機(jī),打印格式如下:
 - [
 -   .\.settings
 -   .\bin
 -   .\src
 - ]
 */ class PPrint { public static String pformat(Collection<?> c) { if(c.size() == 0) return "[]";
        StringBuilder result = new StringBuilder("["); for(Object elem : c) { if(c.size()!=1)
                result.append("\n ");
            result.append(elem);
        } if(c.size()!=1)
            result.append("\n ");
        result.append("]"); return result.toString();
    } public static void pprint(Collection<?> c) {
        System.out.println(pformat(c));
    } public static void pprint(Object c) {
        System.out.println(Arrays.asList(c));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135

2. 字節(jié)流和字符流概述

Java IO中處理字節(jié)流和字符流輸入輸出的基類和派生類繁多,本節(jié)主要做兩件事情:(1)給出類的關(guān)系圖;(2)回答一個(gè)問題,為什么字節(jié)流和字符流要分開處理,為什么既要有Reader/Writer,又保留InputStream/OutputStream? 
Java 1.0中是只存在InputStream/OutputStream的,設(shè)計(jì)Reader/Writer 3. 裝飾者模式和適配器模式

Java IO中分別用到了裝飾者模式和適配者模式。

裝飾者模式(Decorator)

裝飾模式(Decorator)又稱為包裝模式(Wrapper),通過創(chuàng)建一個(gè)裝飾(包裝)對(duì)象,來裝飾真實(shí)的對(duì)象。

Java I/O類庫需要多種不同功能的組合,這正是使用裝飾器模式的理由所在。為什么不使用繼承而采用裝飾器模式呢?如果說Java IO的各種組合是通過繼承方式來實(shí)現(xiàn)的話,那么每一種組合都需要一個(gè)類,這樣就會(huì)出現(xiàn)大量重復(fù)性的問題。而通過裝飾器來實(shí)現(xiàn)組合,恰恰避免了這個(gè)問題。

對(duì)于字節(jié)流而言,F(xiàn)ilterInputStream和FilterOutputStream是用來提供裝飾器接口以控制特定輸入\輸出的兩個(gè)類。需要注意的是,對(duì)于字符流而言,同樣用到的是裝飾者模式,但是有一點(diǎn)不同,Reader體系中的FilterRead類和InputStream體系中的FilterInputStream的功能不同,它不再是裝飾者class BufferedReader extends Reader BufferedInputStream:public class BufferedInputStream extends FilterInputStream

  • 1
  • 2

舉一個(gè)例子如下所示,其中BufferedReader是裝飾對(duì)象,F(xiàn)ileReader是被裝飾對(duì)象。

package c18; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class BufferedInputFile { public static String read(String filename) throws IOException{ //BufferedReader是裝飾對(duì)象,F(xiàn)ileReader是被裝飾對(duì)象 BufferedReader in = new BufferedReader(new FileReader(filename));
        String s;
        StringBuilder sb = new StringBuilder(); while ((s = in.readLine())!=null) {
            sb.append(s + "\n");            
        }
        in.close(); return sb.toString();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

適配者模式(Adapter)

適配者模式又可以分為類適配方式(類似多繼承)和對(duì)象適配方式。而Java IO中使用的是對(duì)象適配方式。我們以FileOutputStream為例,可以看到源碼中,F(xiàn)ileOutputStream繼承了OutputStream類型,同時(shí)持有一個(gè)對(duì)FileDiscriptor對(duì)象的引用。這是一個(gè)將FileDiscriptor接口適配成OutputStream接口形式的對(duì)象形適配器模式。

public class FileOutputStream extends OutputStream { private FileDescriptor fd; public FileOutputStream(FileDescriptor fdObj) {
        SecurityManager security = System.getSecurityManager(); if (fdObj == null) { throw new NullPointerException();
        } if (security != null) {
            security.checkWrite(fdObj);
        }
        fd = fdObj;

        fd.incrementAndGetUseCount();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

4. 基于字節(jié)流的IO操作

本節(jié)主要介紹基于字節(jié)流的輸入InputStream和輸出OutputStream,以及用于實(shí)現(xiàn)裝飾模式的FilterInputStream和FilterOutputStream。

字節(jié)流輸入InputStream

InputStream的作用是表示從不同數(shù)據(jù)源產(chǎn)生輸入的類:

  • 字節(jié)數(shù)組
  • String對(duì)象
  • 文件
  • 管道
  • 一個(gè)由其他種類的流組成的序列
  • 其他數(shù)據(jù)源

下面列表展現(xiàn)了InputStream的派生類,所有的派生類都要聯(lián)合裝飾類FilterInputStream ByteArrayInputStream

  • 作用: 允許將內(nèi)存的緩沖區(qū)作為輸入
  • 構(gòu)造器參數(shù):字節(jié)將從緩沖區(qū)中取出
 /**
     * Creates a <code>ByteArrayInputStream
     * so that it  uses <code>buf as its
     * buffer array. 
     * The buffer array is not copied. 
     * The initial value of <code>pos
     * is <code>0 and the initial value
     * of  <code>count is the length of
     * <code>buf.
     *
     * @param buf   the input buffer.
     */ public ByteArrayInputStream(byte buf[]) { this.buf = buf; this.pos = 0; this.count = buf.length;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

舉個(gè)例子:

/**
 * 格式化內(nèi)存輸出
 */ package c18; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.EOFException; import java.io.IOException; public class FormattedMemoryInput { public static void main(String[] args) throws IOException{ try { //DataInputStream面向字節(jié)的裝飾類 DataInputStream in = new DataInputStream( new ByteArrayInputStream( //BufferedInputFile.read上例中已經(jīng)實(shí)現(xiàn)了 BufferedInputFile.read("D:/workspace/java_learning/" + "Java_Learning/src/c18/DirList2.java").getBytes())); while (true) { //readByte按字節(jié)輸出 System.out.println((char)in.readByte());
            }
        } catch (EOFException e) {
            System.err.println("End of stream");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

StringBufferInputStream

  • 作用:將String作為輸入
  • 構(gòu)造器參數(shù):String

需要注意的是StringBufferInputStream已經(jīng)過時(shí)了,JDK給出的過時(shí)原因如下:

This class does not properly convert characters into bytes. As of JDK 1.1, the preferred way to create a stream from a string is via the FileInputStream

  • 作用:用于從文件中讀取信息
  • 構(gòu)造器參數(shù):表示文件路徑的字符串、File對(duì)象、FileDescriptor對(duì)象
//String public FileInputStream(String name) throws FileNotFoundException { this(name != null ? new File(name) : null);
} //File public FileInputStream(File file) throws FileNotFoundException {
    String name = (file != null ? file.getPath() : null);
    SecurityManager security = System.getSecurityManager(); if (security != null) {
        security.checkRead(name);
    } if (name == null) { throw new NullPointerException();
        }
    fd = new FileDescriptor();
        fd.incrementAndGetUseCount();
    open(name);
} //FileDescriptor public FileInputStream(FileDescriptor fdObj) {
    SecurityManager security = System.getSecurityManager(); if (fdObj == null) { throw new NullPointerException();
    } if (security != null) {
        security.checkRead(fdObj);
    }
    fd = fdObj;
    fd.incrementAndGetUseCount();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

PipedInputStream

  • 作用:產(chǎn)生寫入PipedOutputStream中的數(shù)據(jù),實(shí)現(xiàn)“管道化”
  • 構(gòu)造器參數(shù):PipedOutputStream
public PipedInputStream(PipedOutputStream src, int pipeSize) throws IOException {
     initPipe(pipeSize);
     connect(src);
}
  • 1
  • 2
  • 3
  • 4
  • 5

管道流可以實(shí)現(xiàn)兩個(gè)線程之間,二進(jìn)制數(shù)據(jù)的傳輸。管道流就像一條管道,一端輸入數(shù)據(jù),別一端則輸出數(shù)據(jù)。通常要分別用兩個(gè)不同的線程來控制它們。(這里埋個(gè)伏筆,目前筆者對(duì)多線程掌握還不夠成熟,等到后面學(xué)習(xí)Java并發(fā)中會(huì)繼續(xù)提到PipedIntputStream/PipedOutputStream)

SequenceInputStream

  • 作用:將兩個(gè)或多個(gè)InputStream對(duì)象轉(zhuǎn)換成單一InputStream
  • 構(gòu)造器參數(shù):兩個(gè)InputStream或一個(gè)容器Enumeration
public SequenceInputStream(Enumeration<? extends InputStream> e) { this.e = e; try {
        nextStream();
    } catch (IOException ex) { // This should never happen throw new Error("panic");
    }
} public SequenceInputStream(InputStream s1, InputStream s2) {
    Vector  v = new Vector(2);

    v.addElement(s1);
    v.addElement(s2);
    e = v.elements(); try {
        nextStream();
    } catch (IOException ex) { // This should never happen throw new Error("panic");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

舉兩個(gè)例子(源于網(wǎng)絡(luò)):

import java.io.*; import java.util.*;  
class SequenceDemo1  
{ public static void main(String[] args)throws IOException  
    {  

        Vector<FileInputStream> v = new Vector<FileInputStream>();  

        v.add(new FileInputStream("c:\\1.txt"));  
        v.add(new FileInputStream("c:\\2.txt"));  
        v.add(new FileInputStream("c:\\3.txt"));  

        Enumeration<FileInputStream> en = v.elements();  

        SequenceInputStream sis = new SequenceInputStream(en);  

        FileOutputStream fos = new FileOutputStream("c:\\4.txt"); byte[] buf = new byte[1024]; int len = 0; while((len=sis.read(buf))!=-1)  
        {  
            fos.write(buf,0,len);  
        }  
        fos.close();  
        sis.close();  

    }  
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
import java.io.*; import java.util.*;  
class SequenceDemo2  
{ public static void main(String[] args)throws IOException  
    {  
        InputStream is1 = null;  
        InputStream is2 = null;  
        OutputStream os = null;  
        SequenceInputStream sis = new null;  
        is1 = new FileInputStream("d:"+File.separator+"a.txt");  
        is2 = new FileInputStream("d:"+File.separator+"b.txt");  
        os = new FileOutputStream("d:"+File.separator+"ab.txt");  
        sis = new SequenceInputStream(is1,is2); int temp = 0; while((temp)=sis.read()!=-1)  
        {  
            os.write(temp);  
        }  
        sis.close();  
        is1.close();  
        is2.close();  
        os.close();  


    }  
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

另外,還有FilterInputStream,它是抽象類,作為“裝飾器”的接口,筆者將單獨(dú)用一節(jié)來詳述。


字節(jié)流輸出OutputStream

OutputStream的作用是表示從不同數(shù)據(jù)源產(chǎn)生輸入的類:

  • 字節(jié)數(shù)組
  • 文件
  • 管道

下面是OutputStream的派生類。同樣,所有的派生類都要聯(lián)合裝飾類FilterOutputStream ByteArrayOutputStream

與ByteArrayInputStream相對(duì)應(yīng),public ByteArrayOutputStream() { this(32); } public ByteArrayOutputStream(int size) { if (size < 0) { throw new IllegalArgumentException("Negative initial size: " + size); } buf = new byte[size]; }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

FileOutputStream

與FileInputStream相對(duì)應(yīng), PipedOutputStream

  • 作用:任何寫入其中的信息都會(huì)自動(dòng)作為相關(guān)PipedInputStream輸出,實(shí)現(xiàn)“管道化”
  • 構(gòu)造器參數(shù):PipedInputStream

裝飾器FilterInputStream/FilterOutputStream

FilterInputStream/FilterOutputStream同樣也是InputStream/OutputStream DataInputStream/DataOutputStream

  • 作用:搭配使用,可以按照可移植的方式從流讀取基本數(shù)據(jù)類型(int、char、long等)
  • 構(gòu)造器參數(shù):InputStream/OutputStream
public DataInputStream(InputStream in) { super(in);
}
  • 1
  • 2
  • 3
public DataOutputStream(OutputStream out) { super(out);
}
  • 1
  • 2
  • 3

BufferedInputStream/BufferedOutputStream

  • 作用:使用緩沖器輸入輸出
  • 構(gòu)造器參數(shù):InputStream/OutputStream

舉個(gè)例子:

/**
 * 使用緩沖區(qū),讀取二級(jí)制文件
 */ package c18; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class BinaryFile { public static byte[] read(File bFile) throws IOException {
        BufferedInputStream bf = new BufferedInputStream( new FileInputStream(bFile)); try { byte [] data = new byte[bf.available()];
            bf.read(data); return data;
        } finally {
            bf.close();
        }
    } public static byte[] read(String bFile) throws IOException { return read(new File(bFile).getAbsoluteFile());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

LineNumberInputStream

  • 作用:跟蹤輸入流中的行號(hào),可調(diào)用getLineNumber()和setLineNumber(int)
  • 構(gòu)造器參數(shù):InputStream

該類已經(jīng)被廢棄了,推薦使用字符流的類來操作。

PushbackInputStream

  • 作用:回推字節(jié),讀取字節(jié),然后再將它們返回到流中?;赝撇僮饔衭nread()方法實(shí)現(xiàn)
  • 構(gòu)造器參數(shù):InputStream

PushbackInputStream類實(shí)現(xiàn)了這一思想,提供了一種機(jī)制,可以“偷窺”來自輸入流的內(nèi)容而不對(duì)它們進(jìn)行破壞。

//允許將size大小的字節(jié)回推回流 public PushbackInputStream(InputStream in, int size) { super(in); if (size <= 0) { throw new IllegalArgumentException("size <= 0");
        } this.buf = new byte[size]; this.pos = size;
} //每次允許回推一個(gè)字節(jié) public PushbackInputStream(InputStream in) { this(in, 1);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
package c18; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.PushbackInputStream; public class PushbackInputStreamDemo { public static void main(String[] args) { byte[] arrByte = new byte[1024]; byte[] byteArray = new byte[]{'H', 'e', 'l', 'l', 'o',}; /*
           * new PushbackInputStream(is, 10)一次能回推10個(gè)字節(jié)的緩存
           */ InputStream is = new ByteArrayInputStream(byteArray);
          PushbackInputStream pis = new PushbackInputStream(is, 10); try { for (int i = 0; i < byteArray.length; i++) {
                arrByte[i] = (byte) pis.read();
                System.out.print((char) arrByte[i]);
             } //換行 System.out.println(); byte[] b = {'W', 'o', 'r', 'l', 'd'}; /*
              * unread()回推操作
              * 將World回推到PushbackInputStream流中
              * 下次read()會(huì)將這個(gè)字節(jié)再次讀取出來
              */ pis.unread(b); for (int i = 0; i < byteArray.length; i++) {            
                arrByte[i] = (byte) pis.read();
                System.out.print((char) arrByte[i]);
             }
          } catch (Exception ex) {
             ex.printStackTrace();
          }
       }
}

輸出結(jié)果:
Hello
World
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

PrintStream

  • 作用:PrintStream可以方便地輸出各種類型的數(shù)據(jù)(而不僅限于byte型)的格式化表示形式。
  • 構(gòu)造器參數(shù):InputStream

需要注意的是,與其他輸出流不同, PrintStream 永遠(yuǎn)不會(huì)拋出 IOException ;它產(chǎn)生的IOException會(huì)被自身的函數(shù)所捕獲并設(shè)置錯(cuò)誤標(biāo)記, 用戶可以通過 checkError() 返回錯(cuò)誤標(biāo)記,從而查看PrintStream內(nèi)部是否產(chǎn)生了IOException。 5. 基于字符流的IO操作

設(shè)計(jì)Reader和Writer繼承層次結(jié)構(gòu)主要是為了國際化的16位Unicode字符編碼。下表展示了Reader/Writer/** * 文件讀寫工具 */ package c18; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; public class TextFile { public static String read(String filename) { StringBuilder sb = new StringBuilder(); try { BufferedReader in = new BufferedReader(new FileReader( new File(filename).getAbsoluteFile())); try { String s; while ((s = in.readLine())!= null) { sb.append(s); sb.append("\n"); } } finally { in.close(); } } catch (IOException e) { throw new RuntimeException(e); } return sb.toString(); } public static void write(String filename, String text) { try { PrintWriter out = new PrintWriter( new File(filename).getAbsoluteFile()); try { out.print(text); } finally { out.close(); } } catch (IOException e) { throw new RuntimeException(e); } } }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

需要注意以下幾點(diǎn):

1. 參考文獻(xiàn)

感謝并致敬以下前輩的文章:

  • 《Thinking in Java》 作者:Bruce Eckel 
  • Java之美[從菜鳥到高手演變]之Java中的IO 
    http://blog.csdn.net/zhangerqing/article/details/8466532 
    作者:終點(diǎn) 
  • Java IO最詳解 
    http://blog.csdn.net/yczz/article/details/38761237 
    作者:yczz
  • java中的IO操作總結(jié)(一) 
    http://www.cnblogs.com/nerxious/archive/2012/12/15/2818848.html 
    作者:Nerxious
  • java.io包中的字符流(下) 適配器模式和InputStreamReader/OutputStreamWriter  
    http://www.molotang.com/articles/782.html 
    作者: 三石·道
  • SequenceInputStream合并流 
    http://blog.csdn.net/xuefeng1009/article/details/6955707 
    作者:xuefeng1009
  • 探究java IO之PushbackInputStream類 
    http://my.oschina.net/fhd/blog/345011 
    作者:柳哥
  • JAVA中常用IO流類: PrintStream和PrintWriter 
    http://blog.csdn.net/caixiexin/article/details/6719627 
    作者:caixiexin
  • java io系列16之 PrintStream(打印輸出流)詳解 
    http://www.cnblogs.com/skywang12345/p/io_16.html 
    作者:skywang12345
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI