秦明 發表於 2025-7-23 13:40:00

java~字节流和字符流

<p>如果要进行文件内容的操作那么必须依靠数据流完成,而数据流分为两种:</p>
<ul>
<li>字节流:InputStream(字节输入流)、OutputStream(字节输出流)</li>
<li>字符流:Reader(字符输入流)、Writer(字符输出流)</li>
</ul>
<p>输入和输出是针对内存来说的:</p>
<ul>
<li>输入流:字节(网络,磁盘)–&gt; 自动转换为 –&gt;字符(内存);</li>
<li>输出流:字符(内存)–&gt; 自动转换为–&gt;字节(网络,磁盘);</li>
</ul>
<p><img src="https://images.cnblogs.com/cnblogs_com/lori/2430318/o_250723054928_9efe702a572e283afd6bb3c889f6b590%E5%89%AF%E6%9C%AC.png" alt="" loading="lazy"></p>
<h1 id="区别">区别</h1>
<p>字节流与字符流操作的本质区别只有一个:字节流是原生的操作,而字符流是经过处理后的操作。</p>
<ul>
<li>在进行<code>网络数据传输</code>、<code>磁盘数据</code>所支持的数据类型只有:<code>字节</code>。</li>
<li>而所有磁盘中的数据必须先读取到内存后才能进行操作,而内存中会帮助我们把<code>字节变为字符</code>。字符更加适合处理中文。</li>
</ul>
<h1 id="操作流程">操作流程</h1>
<p>不管使用的是字节流还是字符流,其基本的操作流程几乎是一样的,以文件操作为例。</p>
<ol>
<li>创建File类对象 ,主要是指明要操作的文件路径;</li>
<li>根据字节流或字符流的子类实例化父类对象 ;</li>
<li>进行数据的读取或写入操作;</li>
<li>关闭流(close());</li>
</ol>
<p>对于IO操作属于资源处理,所有的资源处理操作(IO操作、数据库操作、网络)最后必须要进行关闭。</p>
<h1 id="字节输出流outputstream">字节输出流:(OutputStream)</h1>
<p>字节输出流主要以操作byte数据为主,观察java.io.OutputStream类的定义结构:</p>
<pre><code>public abstract class OutputStream implements Closeable, Flushable
</code></pre>
<p>OutputStream类实现了Closeable,Flushable两个接口,这两个接口中的方法:</p>
<ol>
<li>Closeable: public void close() throws IOException;</li>
<li>Flushable: public void flush() throws IOException;</li>
</ol>
<h1 id="实例文件的输出">实例:文件的输出</h1>
<pre><code>public class Demo {
    public static void main(String[] args) throws IOException {
      //第一步:定义要输出的文件的File类对象
      File file = new File("e:"+File.separator+"hello"+File.separator+"my.txt");
      //输出信息的时候文件可以不存在,但是目录必须存在
      if(!file.getParentFile().exists()) {//父路径不存在
            file.getParentFile().mkdirs();//创建父路径
      }
      //第二步:利用OutputStream的子类为父类进行实例化
      OutputStream output = new FileOutputStream(file);
      //第三步:输出文字信息
      String msg = "富则达济天下,穷则独善其身";//字符串
      //为了方便输出需要将字符串变为字节数组
      byte data[] = msg.getBytes();//变为字节数组
      output.write(data);//输出数据
      output.close();//关闭流
    }
}
</code></pre>
<h1 id="字节输入流inputstream">字节输入流:(InputStream)</h1>
<p>InputStream可以实现数据的读取操作,在java中InputStream类的定义如下:</p>
<pre><code>public abstract class InputStream implements Closeable
</code></pre>
<p>InputStream类中定义有三个数据的读取操作方法:</p>
<ol>
<li>读取单个字节:public abstract int read() throws<br>
IOException;<br>
每次执行此方法将读取当个字节数据,如果已经读取完成了,那么最后返回-1。</li>
<li>读取数据到字节数组中:public int read(byte b[]) throws IOException.最常用方法<br>
每次讲数据读取到数组之中,那么会返回一个读取长度的数据,如果没有数据则返回的长度为-1,可是要考虑两种情况:要读取的内容大于开辟的数组内容:长度就是整个数组的长度。要读取的内容小于开辟数组的内容,<br>
长度就是全部最后的内容长度,数组装不满。</li>
<li>读取部分内容到字节数组中:public int read(byte b[], int off,int len) throws IOException<br>
每次读取内容到部分字节数组,只允许读取满限制的数组的字节个数。此方法依然会返回读取的长度。</li>
</ol>
<p>InputStream是一个抽象类,所以要进行文件的读取使用FileInputStream子类,子类定义的构造方法如下:</p>
<pre><code>构造方法:public FileInputStream(File file) throws FileNotFoundException.
</code></pre>
<pre><code>@SuppressWarnings("unused")
public class Demo {
    public static void main(String[] args) throws IOException {
      //第一步:定义要输出的文件的File类对象
      File file = new File("e:"+File.separator+"hello"+File.separator+"my.txt");
      //第二步:实例化InputStream
      InputStream input = new FileInputStream(file);
      //实现数据的读取操作
      byte data[] = new byte;
      int len = input.read(data);//将数据读取到数组之中
      System.out.println("读取的内容【" +new String(data,0,len)+"】");
      //第四步关闭输入流
      input.close();
    }
}

</code></pre>
<h1 id="字符输出流writer">字符输出流:(Writer)</h1>
<p>Writer是进行字符输出操作使用的类,这个类属于抽象类,观察定义:</p>
<pre><code>public abstract class Writer implements Appendable, Closeable, Flushable
</code></pre>
<p>这个Writer类可以直接输出字符串:public void write(String str) throws IOException</p>
<p>Writer是一个抽象类,要进行文件字符流操作,其构造方法为:</p>
<pre><code>@SuppressWarnings("unused")
public class Demo {
    public static void main(String[] args) throws IOException {
      //第一步:定义要输出的文件的File类对象
      File file = new File("e:"+File.separator+"hello"+File.separator+"my.txt");//你的路径
      if(!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
      }
      Writer out = new FileWriter(file);
      String str = "一定要好好学习,天天向上。。。";
      out.write(str);
      out.close();
    }
}
</code></pre>
<p>虽然Writer类提供有字符数组的输出操作能力,但是从本质上来讲使用Writer类就意味着要执行字符串的直接输出。<br>
<code>字符流最适合操作中文,但并不意味着字节流就无法操作中文。</code></p>
<h1 id="字符输入流reader">字符输入流:(Reader)</h1>
<p>Reader一定是一个抽象类,其定义为:</p>
<pre><code>public abstract class Reader extends Object implements Readable,Closeable
</code></pre>
<p>在Reader类中也提供有一系列的read()方法。</p>
<ul>
<li>数据的读取:public int read(char[] cbuf) throws IOException。</li>
</ul>
<p>范例:数据的读取</p>
<pre><code>@SuppressWarnings("unused")
public class Demo {
    public static void main(String[] args) throws IOException {
      //第一步:定义要输出的文件的File类对象
      File file = new File("e:"+File.separator+"hello"+File.separator+"my.txt");//你的路径
      if(file.exists()) {
            Reader in = new FileReader(file);
            char data[] = new char;
            int len = in.read(data);//向字符数组保存数据,返回长度。
            System.out.println(new String(data,0,len));
            in.close();
      }
    }
}
</code></pre>
<h1 id="字节流与字符流的区别">字节流与字符流的区别</h1>
<p>首先必须要明确一点,通过任何终端(网络、文件)读取或者输出的数据都一定是字节,字符是经过内存处理后的数据。</p>
<pre><code>字符输入:字节(磁盘)–&gt; 自动转换为 –&gt;字符(内存);
字符输出:字符(内存)–&gt; 自动转换为–&gt;字节(磁盘);
</code></pre>
<p>在利用字符流输出的时候,所有的内容实际上都只是输出到了缓冲区中(内存)。在使用close()方法关闭的时候会将我们缓冲区的数据进行输出,如果没有关闭,那么就将无法进行输出,此时可以利用flush()方法进行强制的输出。</p>
<p>字符使用到了缓冲区,而字节流没有使用到缓冲区。</p>
<p>如果处理中文使用字符流,其他的任何数据都使用字节流。</p>


</div>
<div id="MySignature" role="contentinfo">
    <p></p>
<div class="navgood">
<p>作者:仓储大叔,张占岭,<br>
荣誉:微软MVP<br>QQ:853066980</p>

<p><strong>支付宝扫一扫,为大叔打赏!</strong>
<br><img src="https://images.cnblogs.com/cnblogs_com/lori/237884/o_IMG_7144.JPG"></p>
</div><br><br>
来源:https://www.cnblogs.com/lori/p/19000596
頁: [1]
查看完整版本: java~字节流和字符流