Java-IO流的总结-字节流

IO流在java中存在的本质是用来进行数据的传输。其中按照流的方向分为:输入流和输出流;按照数据处理的单位分为:字节流和字符流。(字符是无符号类型,字节是有符号类型)。

本文将分别讨论输入流、输出流、字节流和字符流。
一、以字节为单位的输入流的框架图:


20160928084335969.jpg

从图中可以看出以字节为单位的输入流的公共父类是InputStream:
(1) InputStream是以字节为单位的输入流超类,提供了接口从输入流中读取字节数据。
(2) ByteArrayInputStream是字节数组输入流,它的内部缓冲区是一个字节数组,本质是通过字节数组来实现的。
(3) BufferedInputStream是缓冲输入流,作用是为另一个输入流添加缓冲功能。
(4) FileInputStream是文件输入流,通常用于对文件进行读取操作。
(5) ObjectInputStream是对象输入流,和ObjectOutputStream一起来对基本数据或对象进行持久存储。
(6) PipedInputStream是管道输入流,能够实现多线程间的管道通信。
(7) DataInputStream是数据输入流,用来装饰其他输入流,允许应用程序以与机器无关方式从底层输入流中读取基本Java数据类型。
(8) FileDescriptor是文件描述符,用来表示开放文件,开放套接字等。

二、以字节为单位的输出流的框架图:

从中我们可以看出,以字节为单位的输出流的公共父类是OutputStream:

image

从中我们可以看出,以字节为单位的输出流的公共父类是OutputStream:
(1)OutputStream是以字节为单位的输出流的超类,提供了write()函数从输出流中读取字节数据。
(2)ByteArrayOutputStream是字节数组输出流,写入ByteArrayOutputStream的数据被写入到一个byte数组,缓冲区会随着数据的不断写入而自动增长,可使用toByteArray()和toString()获取数据。
(3)PipedOutputStream是管道输出流,和PipedInputStream一起使用,能实现多线程间的管道通信。
(4)FilterOutputStream是过滤输出流,是DataOutputStream,BufferedOutputStream和PrintStream的超类
(5)DataOutputStream是数据输出流,用来装饰其他的输出流,允许应用程序以与机器无关方式向底层写入基本Java数据类型。
(6)BufferedOutputStream是缓冲输出流,它的作用是为另一个输出流添加缓冲功能。
(7)PrintStream是打印输出流,用来装饰其他输出流,为其他输出流添加功能,方便的打印各种数据值
(8)FileOutputStream是文件输出流,通常用于向文件进行写入操作。
(9)ObjectOutputStream是对象输出流,它和ObjectInputStream一起对基本数据或者对象的持久存储。

输入流和输出流都有对应的关系,如图:

image

三、字节转换为字符流的框架图

在java中,字节流能转换为字符流,转换关系图

image

从上图可以看出:
(1)FileReader继承于InputStreamReader,而InputStreamReader依赖于InputStream,因为InputStreamReader的构造函数是以InputStream为参数,传人InputStream会在InputStreamReader内部通过转码,将字节转换成字符。
(2)FileWriter继承于OutputStreamWriter,而OutStreamWriter依赖于OutputStream,因为OutputStreamWriter的构造函数是以OutputStream为参数,我们传人OutputStream会在OutputStreamWriter内部通过转码,将字节转换成字符。字节转换为字符流的框架图

在java中,字节流能转换为字符流,转换关系图

image

从上图可以看出:

(1)FileReader继承于InputStreamReader,而InputStreamReader依赖于InputStream,因为InputStreamReader的构造函数是以InputStream为参数,传人InputStream会在InputStreamReader内部通过转码,将字节转换成字符。

(2)FileWriter继承于OutputStreamWriter,而OutStreamWriter依赖于OutputStream,因为OutputStreamWriter的构造函数是以OutputStream为参数,我们传人OutputStream会在OutputStreamWriter内部通过转码,将字节转换成字符。

附上源码:
基于JDK8的InputStream类源码:

public abstract class InputStream implements Closeable {

    //最大跳过的缓冲区大小  
    private static final int MAX_SKIP_BUFFER_SIZE = 2048;  
    //从输入的流中读取下一个字节  
    public abstract int read() throws IOException;  
    //从输入流中读取一定大小的字节,没有数据返回-1  
    public int read(byte b[]) throws IOException {  
        return read(b, 0, b.length);  
    }  
    //从输人流中读取的数据放到b数组中起始位置为off,长度为len  
    public int read(byte b[], int off, int len) throws IOException {  
        if (b == null) {  
            throw new NullPointerException();  
        } else if (off < 0 || len < 0 || len > b.length - off) {  
            throw new IndexOutOfBoundsException();  
        } else if (len == 0) {  
            return 0;  
        }  
  
        int c = read();  
        if (c == -1) {  
            return -1;  
        }  
        b[off] = (byte)c;  
  
        int i = 1;  
        try {  
            for (; i < len ; i++) {  
                c = read();  
                if (c == -1) {  
                    break;  
                }  
                b[off + i] = (byte)c;  
            }  
        } catch (IOException ee) {  
        }  
            return i;  
        }  
  
        //跳过输入流的长度为n字节  
        public long skip(long n) throws IOException {  
  
            long remaining = n;  
            int nr;  
  
            if (n <= 0) {  
                return 0;  
            }  
  
            int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);  
            byte[] skipBuffer = new byte[size];  
            while (remaining > 0) {  
                nr = read(skipBuffer, 0, (int)Math.min(size, remaining));  
                if (nr < 0) {  
                    break;  
                }  
                remaining -= nr;  
            }  
  
        return n - remaining;  
        }  
    //返回从输入流中可以读取的数据  
    public int available() throws IOException {  
        return 0;  
    }  
    //关闭输入流,释放任何与这个流有关的资源  
    public void close() throws IOException {}  
        //标记在这个输入流的当前位置  
    public synchronized void mark(int readlimit) {}  
        //返回到最近标记的位置  
    public synchronized void reset() throws IOException {  
        throw new IOException("mark/reset not supported");  
    }  
    //测试这个输入流是否支持标记或者重置方法  
    public boolean markSupported() {  
        return false;  
    }  
  
}  

基于JDK8的OutputStream类源码:

public abstract class OutputStream implements Closeable, Flushable {  
    //写特定的字节到输出流  
    public abstract void write(int b) throws IOException;  
    //写特定的长度的字节数组到输出流中  
    public void write(byte b[]) throws IOException {  
        write(b, 0, b.length);  
    }  
    //从b数组中,起始值为off,长度为len的数据到输出流中  
    public void write(byte b[], int off, int len) throws IOException {  
        if (b == null) {  
            throw new NullPointerException();  
        } else if ((off < 0) || (off > b.length) || (len < 0) ||  
                ((off + len) > b.length) || ((off + len) < 0)) {  
                throw new IndexOutOfBoundsException();  
        } else if (len == 0) {  
            return;  
        }  
        for (int i = 0 ; i < len ; i++) {  
            write(b[off + i]);  
        }  
    }  
    //刷新输出流,强制任意的缓冲输出都被输出  
    public void flush() throws IOException {  
    }  
    //关闭输出流,释放与这个输出流相关的所有系统资源  
    public void close() throws IOException {  
    }  
}  

File是“文件”和“目录路径名”的抽象表示形式。File之间继承Object,实现了Serializable和Comparable接口,因此文件支持File对象序列化,同时File对象之间可以比较大小。

File类中主要的函数有:

// 静态成员  
public static final String     pathSeparator        // 路径分割符":"  
public static final char     pathSeparatorChar    // 路径分割符':'  
public static final String     separator            // 分隔符"/"  
public static final char     separatorChar        // 分隔符'/'  
  
// 构造函数  
File(File dir, String name)  
File(String path)  
File(String dirPath, String name)  
File(URI uri)  
  
// 成员函数  
boolean    canExecute()    // 测试应用程序是否可以执行此抽象路径名表示的文件。  
boolean    canRead()       // 测试应用程序是否可以读取此抽象路径名表示的文件。  
boolean    canWrite()      // 测试应用程序是否可以修改此抽象路径名表示的文件。  
int    compareTo(File pathname)    // 按字母顺序比较两个抽象路径名。  
boolean    createNewFile()         // 当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。  
static File    createTempFile(String prefix, String suffix)    // 在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。  
static File    createTempFile(String prefix, String suffix, File directory)    // 在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。  
boolean    delete()             // 删除此抽象路径名表示的文件或目录。  
void    deleteOnExit()       // 在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。  
boolean    equals(Object obj)   // 测试此抽象路径名与给定对象是否相等。  
boolean    exists()             // 测试此抽象路径名表示的文件或目录是否存在。  
File    getAbsoluteFile()    // 返回此抽象路径名的绝对路径名形式。  
String    getAbsolutePath()    // 返回此抽象路径名的绝对路径名字符串。  
File    getCanonicalFile()   // 返回此抽象路径名的规范形式。  
String    getCanonicalPath()   // 返回此抽象路径名的规范路径名字符串。  
long    getFreeSpace()       // 返回此抽象路径名指定的分区中未分配的字节数。  
String    getName()            // 返回由此抽象路径名表示的文件或目录的名称。  
String    getParent()          // 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。  
File    getParentFile()      // 返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。  
String    getPath()            // 将此抽象路径名转换为一个路径名字符串。  
long    getTotalSpace()      // 返回此抽象路径名指定的分区大小。  
long    getUsableSpace()     // 返回此抽象路径名指定的分区上可用于此虚拟机的字节数。  
int    hashCode()               // 计算此抽象路径名的哈希码。  
boolean    isAbsolute()         // 测试此抽象路径名是否为绝对路径名。  
boolean    isDirectory()        // 测试此抽象路径名表示的文件是否是一个目录。  
boolean    isFile()             // 测试此抽象路径名表示的文件是否是一个标准文件。  
boolean    isHidden()           // 测试此抽象路径名指定的文件是否是一个隐藏文件。  
long    lastModified()       // 返回此抽象路径名表示的文件最后一次被修改的时间。  
long    length()             // 返回由此抽象路径名表示的文件的长度。  
String[]    list()           // 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。  
String[]    list(FilenameFilter filter)    // 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。  
File[]    listFiles()                        // 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。  
File[]    listFiles(FileFilter filter)       // 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。  
File[]    listFiles(FilenameFilter filter)   // 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。  
static File[]    listRoots()    // 列出可用的文件系统根。  
boolean    mkdir()     // 创建此抽象路径名指定的目录。  
boolean    mkdirs()    // 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。  
boolean    renameTo(File dest)    // 重新命名此抽象路径名表示的文件。  
boolean    setExecutable(boolean executable)    // 设置此抽象路径名所有者执行权限的一个便捷方法。  
boolean    setExecutable(boolean executable, boolean ownerOnly)    // 设置此抽象路径名的所有者或所有用户的执行权限。  
boolean    setLastModified(long time)       // 设置此抽象路径名指定的文件或目录的最后一次修改时间。  
boolean    setReadable(boolean readable)    // 设置此抽象路径名所有者读权限的一个便捷方法。  
boolean    setReadable(boolean readable, boolean ownerOnly)    // 设置此抽象路径名的所有者或所有用户的读权限。  
boolean    setReadOnly()                    // 标记此抽象路径名指定的文件或目录,从而只能对其进行读操作。  
boolean    setWritable(boolean writable)    // 设置此抽象路径名所有者写权限的一个便捷方法。  
boolean    setWritable(boolean writable, boolean ownerOnly)    // 设置此抽象路径名的所有者或所有用户的写权限。  
String    toString()    // 返回此抽象路径名的路径名字符串。  
URI    toURI()    // 构造一个表示此抽象路径名的 file: URI。  
URL    toURL()    // 已过时。 此方法不会自动转义 URL 中的非法字符。建议新的代码使用以下方式将抽象路径名转换为 URL:首先通过 toURI 方法将其转换为 URI,然后通过 URI.toURL 方法将 URI 装换为 URL。  

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

File常用的方法:
一、创建目录常用的方法
(1)根据相对路径创建目录
[java] view plain copy
print?

File dir = new File("dir");  
dir.mkdir();//在当前目录下创建目录  

(2)根据绝对路径创建目录

[java] view plain copy
print?

File dir = new File("/home/skywang/dir");  
dir.mkdirs();  

(3)URI方法
[java] view plain copy
print?

URI uri = new URI("file:/home/skywang/dir");  
File dir = new File(uri);  
dir.mkdir();  

二、新建子目录几种常用方法
(1)在当前子目录下创建一个目录
[java] view plain copy
print?

File sub1 = new File("dir", "sub1");//目录dir必须是存在的  
sub1.mkdir();  

(2)通过目录创建目录
[java] view plain copy
print?

File sub3 = new File("dir/sub3");//dir不一定存在,当不存在时会创建  
sub3.mkdirs();  

(3)绝对目录创建目录

[java] view plain copy
print?

File sub4 = new File("/home/skywang/dir/sub4");//当目录不存在时会创建  
sub4.mkdirs();  

(4)URI方式
[java] view plain copy
print?

URI uri = new URI("file:/home/skywang/dir/sub5");//和(3)一样,目录不存在就创建  
File sub5 = new File(uri);  
sub5.mkdirs();  

三、新建文件的常用方法
(1)在当前子目录下创建文件
[java] view plain copy
print?

try {  
    File dir = new File("dir");    // 获取目录“dir”对应的File对象  
File file1 = new File(dir, "file1.txt");  
file1.createNewFile();  
} catch (IOException e) {  
    e.printStackTrace();  
}  

(2)相对目录下创建文件

[java] view plain copy
print?

try {  
    File file2 = new File("dir", "file2.txt");  
file2.createNewFile();  
} catch (IOException e) {  
    e.printStackTrace();  
}  

(3)绝对路径创建文件

[java] view plain copy
print?

try {  
    File file3 = new File("/home/skywang/dir/file3.txt");  
file3.createNewFile();  
} catch (IOException e) {  
    e.printStackTrace();  
}  

(4)URI方式创建文件

[java] view plain copy
print?

try {  
    URI uri = new URI("file:/home/skywang/dir/file4.txt");  
File file4 = new File(uri);  
file4.createNewFile();  
} catch (IOException e) {  
    e.printStackTrace();  
}  
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容