一、前言

Java的IO流主要用途就是文件数据的读写、数据的网络发送与接收等场合。

流是一组有顺序的有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备之间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。对于文件内容的操作主要分为两大类分别是:字符流和字节流。

二、I/O流的分类

根据处理数据类型的不同分为:字符流和字节流

根据数据流向不同分为:输入流和输出流

1.字符流和字节流

字节流以字节为单位,字符流以字符为单位。字节流能处理所有类型的数据,而字符流只能处理字符类型的数据。字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的,而字符流站操作的时候是会用到缓冲区的,是通过缓冲区来操作文件。

2.输入流和输出流

对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。

三、代码实例

1.字节流操作

package day01;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author qx
 * @date 2023/10/20
 * @des
 */
public class IOTest {
    private static final String FILEPATH = "D:" + File.separator + "test.txt";
    private static final String FILEPATH_CHINESE = "D:" + File.separator + "中文.txt";

    public static void main(String[] args) throws IOException {
        test01(false);
        test01(true);
    }

    private static void test01(boolean chineseFile) throws IOException {
        File file = new File(FILEPATH);
        File fileChinese = new File(FILEPATH_CHINESE);
        FileInputStream fis = null;
        if (chineseFile) {
            // 字节流读取中文乱码
            fis = new FileInputStream(fileChinese);
        } else {
            fis = new FileInputStream(file);
        }
        int read = 0;
        while ((read = fis.read()) != -1) {
            System.out.print((char) read);
        }
        System.out.println();
        fis.close();
    }

}

输出:

hello world
我是中国人

我们发现字节流读取中文会出现乱码。

2.字符流操作

package day01;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author qx
 * @date 2023/10/20
 * @des
 */
public class IOTest {
    private static final String FILEPATH = "D:" + File.separator + "test.txt";
    private static final String FILEPATH_CHINESE = "D:" + File.separator + "中文.txt";

    public static void main(String[] args) throws IOException {
        test02();
    }

    private static void test02() throws IOException {
        File file = new File(FILEPATH_CHINESE);
        // 字符流读取中文不会乱码
        FileReader fileReader = new FileReader(file);
        int read = 0;
        while ((read = fileReader.read()) != -1) {
            System.out.println((char) read);
        }
        fileReader.close();
    }
}

输出:

我
是
中
国
人

3.字节流写操作

package day01;

import java.io.*;

/**
 * @author qx
 * @date 2023/10/20
 * @des
 */
public class IOTest {
    private static final String FILEPATH = "D:" + File.separator + "test.txt";
    private static final String FILEPATH_CHINESE = "D:" + File.separator + "中文.txt";

    public static void main(String[] args) throws IOException {
        test03("hello");
    }
    private static void test03(String str) throws IOException {
        File file = new File(FILEPATH);
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(str.getBytes());
        fos.close();
    }
}

执行程序,打开写入内容后的文件

Java基础知识回顾6-IO流_字符流

4.字符流写操作

package day01;

import java.io.*;

/**
 * @author qx
 * @date 2023/10/20
 * @des
 */
public class IOTest {
    private static final String FILEPATH = "D:" + File.separator + "test.txt";
    private static final String FILEPATH_CHINESE = "D:" + File.separator + "中文.txt";

    public static void main(String[] args) throws IOException {
        test04("中国");
    }
    private static void test04(String str) throws IOException {
        File file = new File(FILEPATH_CHINESE);
        FileWriter fw = new FileWriter(file);
        fw.write(str);
        fw.close();
    }
}

执行程序,打开写入内容后的文件

Java基础知识回顾6-IO流_java_02

四、多线程方式进行socket文件传输

1.服务端线程操作

package day01;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

/**
 * @author qx
 * @date 2023/10/20
 * @des 服务端线程操作
 */
public class MyDownload implements Runnable {
    private Socket socket;

    public MyDownload(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            System.out.println("与客户端连接成功");
            OutputStream outputStream = socket.getOutputStream();
            File file = new File("D:" + File.separator + "spepc_assess.sql");
            FileInputStream fis = new FileInputStream(file);
            // 定义每次发送的文件大小
            byte[] bytes = new byte[1024];
            int len = -1;
            while ((len = fis.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
            }
            fis.close();
            outputStream.close();
            socket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

2.服务端

package day01;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author qx
 * @date 2023/10/20
 * @des 服务端
 */
public class MyServer {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(9999);
        while (true) {
            Socket socket = server.accept();
            Thread thread = new Thread(new MyDownload(socket));
            thread.start();
        }
    }
}

3.客户端

package day01;

import java.io.*;
import java.net.Socket;

/**
 * @author qx
 * @date 2023/10/20
 * @des 客户端
 */
public class MyClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 9999);
        InputStream inputStream = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = -1;
        OutputStream outputStream = new FileOutputStream("D:" + File.separator + "my.sql");
        while ((len = inputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, len);
        }
        outputStream.close();
        inputStream.close();
        System.out.println("传输完毕");
    }
}

Java基础知识回顾6-IO流_字符流_03

五、图片和byte数组互转

package day01;

import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.FileImageOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * @author qx
 * @date 2023/10/20
 * @des
 */
public class ImageByteTest {
    public static void main(String[] args) {
        String path = "E:" + File.separator + "img" + File.separator + "logo.jpg";
        byte[] image2byte = image2byte(path);
        System.out.println(image2byte);
        String destPath = "E:" + File.separator + "img" + File.separator + "logo1.jpg";
        byte2image(image2byte, destPath);
    }

    /**
     * byte数组到图片
     *
     * @param image2byte byte数组
     * @param destPath   保存路径
     */
    private static void byte2image(byte[] image2byte, String destPath) {
        FileImageOutputStream outputStream = null;
        try {
            outputStream = new FileImageOutputStream(new File(destPath));
            outputStream.write(image2byte);
            outputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 图片到byte数组
     *
     * @param path 图片地址
     * @return byte数组
     */
    private static byte[] image2byte(String path) {
        byte[] data = null;
        FileImageInputStream input = null;
        try {
            input = new FileImageInputStream(new File(path));
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = input.read(buf)) != -1) {
                output.write(buf, 0, len);
            }
            data = output.toByteArray();
            output.close();
            input.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return data;
    }
}

Java基础知识回顾6-IO流_java_04