美文网首页Java
Java IO流(字节流File读写操作)

Java IO流(字节流File读写操作)

作者: 一亩三分甜 | 来源:发表于2019-09-21 10:03 被阅读0次
  • 字符流:
    FileReader
    FileWriter
    BufferedReader
    BufferedWriter
  • 字节流:
    InputStream OutputStream

需求,想要操作图片数据,这时就要用到字节流。

  • 1.写数据
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileStream {
    public static void main(String[] args) throws IOException
    {
            writeFile();
    }
    public static void writeFile() throws IOException
    {
        FileOutputStream fos = new FileOutputStream("fos.txt");
        fos.write("abcde".getBytes());
        fos.close();
    }
}
Snip20190917_21.png
  • 2.读取数据

一、挨个读取

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileStream {
    public static void main(String[] args) throws IOException
    {
        readFile_1();
    }
    public static void readFile_1() throws IOException
    {
        FileInputStream fis = new FileInputStream("fos.txt");
        int ch = 0;
        while ((ch=fis.read())!=-1)
        {
            System.out.println((char)ch);
        }
        fis.close();
    }
}
//输出
a
b
c
d
e

二、读取一行

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileStream {
    public static void main(String[] args) throws IOException
    {
        readFile_2();
    }
    public static void readFile_2() throws IOException
    {
        FileInputStream fis = new FileInputStream("fos.txt");
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = fis.read(buf))!=-1)
        {
            System.out.println(new String(buf,0,len));
        }
        fis.close();
    }
}
//输出
abcde

三、使用available定义缓冲区。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileStream {
    public static void main(String[] args) throws IOException
    {
        readFile_3();
    }
    public static void readFile_3() throws IOException
    {
        FileInputStream fis = new FileInputStream("fos.txt");
        int num = fis.available();
        byte[] buf = new byte[fis.available()];//定义一个刚刚好的缓冲区,不用再循环了。
        fis.read(buf);
        System.out.println(new String(buf));

        System.out.println("num="+num);
        fis.close();
    }
}
//输出
abcde
num=5

复制一个图片

思路:

1.用字节读取流对象和图片关联。

2.用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。

3.通过循环读写,完成数据的存储。

4.关闭资源。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyPic {
    public static void main(String[] args)
    {
        FileOutputStream fos = null;
        FileInputStream fis = null;
        try
        {
         fos = new FileOutputStream("1.png");
         fis = new FileInputStream("landscape.jpg");
         byte[] buf = new byte[1024];
         int len = 0;
         while ((len = fis.read(buf))!= -1)
         {
             fos.write(buf,0,len);
         }
        }catch (IOException e)
        {
            throw new RuntimeException("复制文件失败");
        }
        finally {
            try{
                if (fis!=null)
                    fis.close();
            }catch (IOException e)
            {
                throw new RuntimeException("读取关闭失败");
            }
            try
            {
             if (fos!=null)
                 fos.close();
            }catch (IOException e)
            {
                throw new RuntimeException("写入关闭失败");
            }
        }
    }
}
Snip20190918_23.png

演示mp3的复制,通过缓冲区。

BufferedOutputStream
BufferedInputStream

循环每次读取一个字节,有多少个字节读取多少次。再把每一个字节写入到1.mp3中。一共有8098212个字节。每次读取到的这个字节用by来接收,by为int型打印by的值为这个二进制的字节所表示的十进制数,循环里面会进行8098212次计算。


Snip20190918_26.png
import java.io.*;

public class CopyMp3 {
    public static void main(String[] args) throws IOException
    {
       long start = System.currentTimeMillis();
       copy_1();
       long end = System.currentTimeMillis();
       System.out.println((end-start) + "毫秒");
    }
    //通过字节流的缓冲区完成复制
    public static void copy_1() throws IOException
    {
        BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("0.mp3"));
        BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("1.mp3"));
        int by = 0;
        int count = 0;
        while ((by=bufis.read())!=-1)
        {
            count++;
            bufos.write(by);
        }
        System.out.println(count);
        bufos.close();
        bufis.close();
    }
}
//输出
8098212
259毫秒
Snip20190918_25.png

自定义缓冲区复制Mp3

import java.io.*;

class MyBufferedInputStream
{
    private InputStream in;
    private byte[] buf = new byte[1024];
    private int pos = 0,count = 0;
    MyBufferedInputStream(InputStream in)
    {
        this.in = in;
    }
    //一次读一个字节,从缓冲区(字节数组)获取。
    public int myRead() throws IOException
    {
        //通过in对象读取硬盘上数据,并存储在buf中
        if (count==0) {
            count = in.read(buf);
            System.out.println("输出的字节数组长度:"+count);
            if (count < 0)
                return -1;
            pos = 0;
            byte b = buf[pos];

            count--;
            pos++;
            System.out.println("读到的字符数组中第"+pos+"个字节十进制表示为:"+b);
            return b;
        }
        else if (count>0)
        {
            byte b = buf[pos];
            count --;
            pos++;
            System.out.println("读到的字符数组中第"+pos+"个字节十进制表示为:"+b);
            return b;
        }
        return -1;
    }
    public void myClose()throws IOException
    {
        in.close();
    }
}
public class CopyMp3 {
    public static void main(String[] args) throws IOException
    {
       long start = System.currentTimeMillis();
       copy_2();
       long end = System.currentTimeMillis();
       System.out.println((end-start) + "毫秒");
    }
    public static void copy_2() throws IOException
    {
        MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("0.mp3"));
        BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("2.mp3"));
        int by = 0;
        int count = 0;
//        System.out.println("第一个字节十进制表示为:"+bufis.myRead());
        while ((by=bufis.myRead())!=-1)
        {
//            System.out.println("当前的字节"+by);
            count++;
            System.out.println("写入计数"+count);
            bufos.write(by);
        }
        System.out.println("写入的字节数:"+count);
        bufos.close();
        bufis.myClose();
    }
}
//输出

输出的字节数组长度:1024
读到的字符数组中第1个字节十进制表示为:73
写入计数1
读到的字符数组中第2个字节十进制表示为:68
写入计数2
读到的字符数组中第3个字节十进制表示为:51
写入计数3
读到的字符数组中第4个字节十进制表示为:4
写入计数4
读到的字符数组中第5个字节十进制表示为:0
写入计数5
读到的字符数组中第6个字节十进制表示为:0
写入计数6
读到的字符数组中第7个字节十进制表示为:0
写入计数7
读到的字符数组中第8个字节十进制表示为:0
写入计数8
读到的字符数组中第9个字节十进制表示为:0
写入计数9
读到的字符数组中第10个字节十进制表示为:35
写入计数10
读到的字符数组中第11个字节十进制表示为:84
写入计数11
读到的字符数组中第12个字节十进制表示为:83
写入计数12
读到的字符数组中第13个字节十进制表示为:83
写入计数13
读到的字符数组中第14个字节十进制表示为:69
写入计数14
读到的字符数组中第15个字节十进制表示为:0
写入计数15
读到的字符数组中第16个字节十进制表示为:0
写入计数16
读到的字符数组中第17个字节十进制表示为:0
写入计数17
读到的字符数组中第18个字节十进制表示为:15
写入计数18
读到的字符数组中第19个字节十进制表示为:0
写入计数19
读到的字符数组中第20个字节十进制表示为:0
写入计数20
读到的字符数组中第21个字节十进制表示为:3
写入计数21
读到的字符数组中第22个字节十进制表示为:76
写入计数22
读到的字符数组中第23个字节十进制表示为:97
写入计数23
读到的字符数组中第24个字节十进制表示为:118
写入计数24
读到的字符数组中第25个字节十进制表示为:102
写入计数25
读到的字符数组中第26个字节十进制表示为:53
写入计数26
读到的字符数组中第27个字节十进制表示为:53
写入计数27
读到的字符数组中第28个字节十进制表示为:46
写入计数28
读到的字符数组中第29个字节十进制表示为:49
写入计数29
读到的字符数组中第30个字节十进制表示为:57
写入计数30
读到的字符数组中第31个字节十进制表示为:46
写入计数31
读到的字符数组中第32个字节十进制表示为:49
写入计数32
读到的字符数组中第33个字节十进制表示为:48
写入计数33
读到的字符数组中第34个字节十进制表示为:52
写入计数34
读到的字符数组中第35个字节十进制表示为:0
写入计数35
读到的字符数组中第36个字节十进制表示为:0
写入计数36
读到的字符数组中第37个字节十进制表示为:0
写入计数37
读到的字符数组中第38个字节十进制表示为:0
写入计数38
读到的字符数组中第39个字节十进制表示为:0
写入计数39
读到的字符数组中第40个字节十进制表示为:0
写入计数40
读到的字符数组中第41个字节十进制表示为:0
写入计数41
读到的字符数组中第42个字节十进制表示为:0
写入计数42
读到的字符数组中第43个字节十进制表示为:0
写入计数43
读到的字符数组中第44个字节十进制表示为:0
写入计数44
读到的字符数组中第45个字节十进制表示为:0
写入计数45
读到的字符数组中第46个字节十进制表示为:-1
写入的字节数:45
3毫秒

发现的Mp3文件字节有缺省,循环只进行了45次,复制也只复制了45个字节。复制的mp3文件有缺省,打不开。通过打印发现循环只进行了45次就停止了,也就是只读到了45个字节,读到第46个字节的时候返回-1了,跳出循环。说明读到的第46个字节的十进制数为-1,二进制表示为11111111。详情请参考负数的二进制表示

Snip20190919_31.png

为什么读到的第46个字节的二进制为11111111?有什么办法可以避免终止循环?

读到的每一个字符是byte类型1个字节(8个二进制位),但是用int类型4个字节(32个二进制位)接收。类型提升了,但是十进制表示还是保持原值。
11111111 -->提升了一个int类型,那不还是-1吗?是-1的原因是因为在8个1前面补的是1导致的。那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。
怎么补0呢?

11111111 11111111 11111111 11111111

& 00000000 00000000 00000000 11111111

00000000 00000000 00000000 11111111

所以需要对返回的字节和255(00000000 00000000 00000000 11111111)做与运算。

import java.io.*;
class MyBufferedInputStream
{
    private InputStream in;
    private byte[] buf = new byte[1024];
    private int pos = 0,count = 0;
    MyBufferedInputStream(InputStream in)
    {
        this.in = in;
    }
    //一次读一个字节,从缓冲区(字节数组)获取。
    public int myRead() throws IOException
    {
        //通过in对象读取硬盘上数据,并存储在buf中
        if (count==0) {
            count = in.read(buf);
//            System.out.println("输出的字节数组长度:"+count);
            if (count < 0)
                return -1;
            pos = 0;
            byte b = buf[pos];

            count--;
            pos++;
//            System.out.println("读到的字符数组中第"+pos+"个字节十进制表示为:"+b);
            return b & 255;
        }
        else if (count>0)
        {
            byte b = buf[pos];
            count --;
            pos++;
//            System.out.println("读到的字符数组中第"+pos+"个字节十进制表示为:"+b);
            return b & 0xff;
        }
        return -1;
    }
    public void myClose()throws IOException
    {
        in.close();
    }
}
public class CopyMp3 {
    public static void main(String[] args) throws IOException
    {
       long start = System.currentTimeMillis();
       copy_2();
       long end = System.currentTimeMillis();
       System.out.println((end-start) + "毫秒");
    }
    public static void copy_2() throws IOException
    {
        MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("0.mp3"));
        BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("2.mp3"));
        int by = 0;
        int count = 0;
//        System.out.println("第一个字节十进制表示为:"+bufis.myRead());
        while ((by=bufis.myRead())!=-1)
        {
//            System.out.println("当前的字节"+by);
            count++;
//            System.out.println("写入计数"+count);
            bufos.write(by);
        }
        System.out.println("写入的字节数:"+count);
        bufos.close();
        bufis.myClose();
    }
}
//输出
写入的字节数:8098212
196毫秒
Snip20190921_40.png
Snip20190921_41.png

可能会有一个疑问,就是本来只有一个字节的byte类型,最后被写入的时候变成了int类型四个字节?大小变了4倍吗?实际上最后bufos.write(by);的时候又对int类型进行了强制转换,只取了最后8位。write方法只将指定的字节写入此缓冲的输出流。即最后一个字节,最后八位。read方法是读取时候强制转化提升,write方法是强制降低,只取最低八位。

相关文章

  • Java IO流(字节流File读写操作)

    字符流:FileReaderFileWriterBufferedReaderBufferedWriter字节流:I...

  • Java 学习笔记(14)—— 文件操作

    java文件操作主要封装在Java.io.File中,而文件读写一般采用的是流的方式,Java流封装在 java....

  • Java IO 第3篇:不能不懂的 IO 处理流

    不能不懂的 IO 处理流 我们在掌握了 File 类、字节流、字符流,学会了 IO 操作的套路之后,IO 操作基本...

  • Java IO流的使用

    下面部分内容是参考Oubo的博客——Java IO流学习总结 Java流操作有关的类或者接口: 字符流和字节流 字...

  • Android 基础之文件和数据库

    Java 文件流 1. 字节流文件操作(读写)的代码 2. 字符流文件操作(读写)的代码 3. 按行(读写)的代码...

  • Java I/O流(一)

    学习了Java中的i/o流来读取文件 1.File类的操作文件和目录属性2.字符流字节流讲解3.使用字节流读写文件...

  • IO流简介

    io流的作用:读写设备上的数据,硬盘文件、内存、键盘、网络.... io流分类:输入流和输出流,字节流和字符流 字...

  • 记录JAVA的IO学习

    JAVA的IO流按流向分为两种:输入流,输出流。* 流按操作类型分为两种:* 字节流 : 字节流可以操作任何数据,...

  • Java 中 IO 流分为几种?BIO,NIO,AIO 有什么区

    java 中 IO 流分为几种? 按照流的流向分,可以分为输入流和输出流; 按照操作单元划分,可以划分为字节流和字...

  • Scala编程基础29:Scala读写操作

    Scala进行文件读写操作,都是直接调用的Java中的IO类:java.io.File。 1.Scala写文件 下...

网友评论

    本文标题:Java IO流(字节流File读写操作)

    本文链接:https://www.haomeiwen.com/subject/bfthuctx.html