字节流和字符流

File类虽然可以操作文件,但是并不是操作文件的内容,如果要进行内容的操作只能通过两种途径:字节流、字符流

如果要进行输入,输出操作一般都会按照如下的步骤(以文件操作为例):

  • 通过File类定义一个要操作文件的路径;
  • 通过字节流或字符流的子类对象为父类对象实例化;
  • 进行数据的读(输入)、写(输出)操作;
  • 数据流属于资源操作,资源操作必须关闭。

java.io包定义了两类流:

  • 字节流(JDK 1.0) : InputStream、OutputStream;
  • 字符流(JDK 1.1) : Reader、Writer。

1 字节输出流:OutputStream(重点)

OutputStream类是一个专门进行字节数据输出的一个类,定义如下:

public abstract class OutputStream
extends Object
implements Closeable, Flushable

可以发先OutputStream类实现了个两个接口:Closeable, Flushable;这两个接口定义如下:

Closeable接口(JDK 1.5) Flushable接口(JDK 1.5)
public interface Closeable extends AutoCloseable public interface Flushable

在JDK 1.7 中引入了自动关闭机制,所以Closeable又继承AutoCloseable接口,定义如下:

public interface AutoCloseable {
    public void close() throws Exception;
}

但是OutputStream类在JDK 1.0的时候就提供了,这个类原本就定义了close()和flush()两个方法,所以现在以上的两个接口就几乎可以忽略。
在OutputStream类里面提供有三个输出的方法:

  • 输出单个字节:public abstract void write(int b) throws IOException
  • 输出全部字节数组:public void write(byte[] b) throws IOException
  • 输出部分字节数据public void write(byte[] b, int off, int len) throws IOException
    OutputStream是抽象类,如果为抽象类进行实例化操作,那么必须使用抽象类的子类,由于要使用文件操作,可以使用FileOutputStream子类,这个子类里面定义如下的构造方法:
  • 创建或覆盖已有文件:public FileOutputStream(File file) throws FileNotFoundException
  • 文件内容追加:public FileOutputStream(File file, boolean append) throws FileNotFoundException

范例:文件内容的输出

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class IntOrOutPutStream {
    public static void main(String[] args) throws Exception {
        File file = new File("D:" + File.separator + "Document" + File.separator + "test.txt");
        if (!file.getParentFile().exists()) {
            file.mkdirs();
        }
        
        OutputStream output = new FileOutputStream(file);
        
        String str = "好好学习,天天向上!";
        byte[] data = str.getBytes();
        output.write(data);
        output.close();
    }
}

以上是整个字节数组的内容进行了输出,如果此时要输出的文件不存在,就会自动创建文件。
范例:单个字节的方式输出

        for (int x = 0 ; x < data.length ; x++) {
            output.write(data[x]);
        }

范例:输出部分字节数组内容

output.write(data, 6, 4);

以上都是直接覆盖原有文件内容,也可以实现内容的追加,只需要更换FileOutputStream类的构造方法即可:

OutputStream output = new FileOutputStream(file , true);
//  \r\n 可以实现换行
String str = "好好学习,天天向上!\r\n";

2 字节输入流:InputStream

如果需要进行数据的读取操作,可以利用InputStream类实现功能,此类定义:public abstract class InputStream extends Object implements Closeable
虽然此类实现了Closeable接口,但是与OutputStream类一样,可以不用考虑接口的存在,在InputStream类里面也定义又数据读取的方法:

  • 读取单个字节:public abstract int read() throws IOException
    · 返回值:返回读取的字节内容,如果结尾没有数据了,返回 -1
  • 将读取的数据保存在里字节数组里:public int read(byte[] b) throws IOException
    · 返回值:返回读取的数据长度,如果已经读取到结尾,返回 -1
  • 将读取的数据保存在部分字节数据里:public int read(byte[] b, int off, int len) throws IOException
    · 返回值:读取的部分数据的长度,如果已经读取到结尾,返回 -1

InputStream是一个抽象类,如果要进行文件读取使用子类FileInputStream,此子类的构造方法:public FileInputStream(File file) throws FileNotFoundException
范例:向数组里面读取数据

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class InputStreamTest {
    public static void main(String[] args) throws Exception{
        //1.定义要输入的文件路径
        File file = new File("D:" + File.separator + "Document" + File.separator + "test.txt");
        if (file.getParentFile().exists()) {
            //2. 使用InputStream进行读取
            InputStream input = new FileInputStream(file);
            //3. 读取数据
            byte[] data = new byte[1024];   //准备长度为1024的数组
            int len = input.read(data);     //将内容保存到字节数组中
            //4. 关闭输入流
            input.close();
            System.out.println("{" + new String(data , 0 ,len) + "}");
        }
        
    }
}

范例:单个字节数据读取

  • 文件有很多字节数据,所以读取数据应采用循环的方式,但由于不确定循环次数,所以使用while循环。
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;

public class InputStreamWhileTest {
    public static void main(String[] args) throws Exception {
        File file = new File("D:" + File.separator + "Document" + File.separator + "test.txt");
        if (file.getParentFile().exists()) {
            InputStream input = new FileInputStream(file);
            byte[] data = new byte[1024];
            int temp = 0;
            int foot = 0;
            //temp = input.read() , 表示将read() 方法读取的字节内容赋值给temp变量
            //(temp = input.read()) != -1 , 判断读取temp的内容是否是-1
            while ((temp = input.read()) != -1) {
                data[foot++] = (byte) temp;     //有内容进行保存
            }
            input.close();
            System.out.println("{" +new String(data , 0 , foot)+ "}");
        }
    }
}

3 字符输出流:Writer

Writer类是在JDK1.1之后增加的,其类的定义如下:
public abstract class Writer extends Object implements Appendable, Closeable, Flushable
这个类除了实现了Closeable与Flushable接口外,又多实现了一个Appendable,这个接口的定义如下:

public interface Appendable {
  public Appendable append(char c) throws IOException {}
  public Appendable append(CharSequence csq) throws IOException {}
  public Appendable append(CharSequence csq, int start, int end) throws IOException {}
}

在Appendable接口里面定义了追加类的操作,而且追加的数据都是字符或者字符串。
在Writer类里面定义有一下的输出方法(部分):

  • 输出全部字符数组:public void write(char[] cbuf) throws IOException
  • 输出字符串:public void write(String str) throws IOException
    Writer是一个抽象类,如果想要为这个类的对象实例化,应该使用FileWriter子类:
    范例:使用Writer类实现内容输出
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;

public class WriterTest {
    public static void main(String[] args) throws Exception {
        File file = new File("D:" + File.separator + "Document" 
                + File.separator + "Document" + File.separator + "test.txt");
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        
        Writer writerfile = new FileWriter(file);
        String str = "Hello world!";
        writerfile.write(str);
        writerfile.close();
    }
}

4 字符输入流:Reader

Reader 是进行字符数据读取的输入流,其本身也是一个抽象类:
public abstract class Reader extends Object implements Readable, Closeable
在Reader类里面也提供有一系列的read()方法:

  • 读取内容到字符数组:public int read(char[] cbuf) throws IOException
    · 返回值:表示读取的数据长度,如果已经读取到结尾了,返回 -1;
    为Reader类实例化的可以使用FileReader子类完成。
    范例:使用Reader读取数据
import java.io.File;
import java.io.FileReader;
import java.io.Reader;

public class ReaderTest {
    public static void main(String[] args) throws Exception {
        File file = new File(
                "D:" + File.separator + "Document" + File.separator + "Document" + File.separator + "test.txt");
        if (file.getParentFile().exists()) {
            Reader readerfile = new FileReader(file);
            char[] data = new char[1024];
            int len = readerfile.read(data);
            readerfile.close();
            System.out.println(new String(data, 0, len));
        }
    }
}

5 字节流与字符流的区别?

  1. 字节流直接与终端进行数据交互,字符流需要将数据经过缓冲去处理后才可以输出。
  2. 在使用OutputStream输出数据的时候,即使最后没有关闭输出流,内容也可以正常输出,但是不关闭字符输出流,就表示在缓冲区中处理的内容不会被强制性清空,所以就不会输出数据;如果有特殊情况不能够关闭字符输出流,可以使用flush()方法强制清空缓冲区。
    范例:强制清空缓冲区
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;

public class FlushTest {
    public static void main(String[] args) throws Exception{
        File file = new File("D:" + File.separator + "Document" + File.separator + "Document" + File.separator + "test.txt");
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        Writer out = new FileWriter(file);
        String str = "Hello world @!";
        out.write(str);
        out.flush();
    }
}

在开发之中,对字节数据处理是比较多的,例如:图片、音乐、电影;而对字符流最大的好处就是可以处理中文,所以在日后的开发之中,如果要处理中文, 优先考虑字符流,没有中文时,建议使用字节流。

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

推荐阅读更多精彩内容