天天看点

Java IO基础(同步阻塞IO)

概述

Java IO是一套Java 用来读写数据(输入和输出)的API,大部分程序都需要处理一些输入,并由输入产生一些输出(PS: 输入和输出是相对CPU而言的,input 就是从外面到CPU,output就是从CPU到外面,CPU是主人公)。java.io 包下有大约80多个类,大概可以分成四组:

  1. 基于字节操作的I/O接口: InputStream和OutputStream
  2. 基于字符操作的I/O接口:Writer和Reader
  3. 基于磁盘操作的I/O接口:File
  4. 基于网络操作的I/O接口:Socket

    java.io 包下的类如下:

    Java IO基础(同步阻塞IO)

File类

Java IO API中的File类可以让你访问底层文件系统,通过File类。你可以做到如下几点:

1.检测文件是否存在 (file.exists())

2.读取文件长度 (file.length())

3.重命名或者移动文件(file.renameTo(new File(“c:\data\new-file.txt”));)

4.删除文件(file.delete())

5.检测某个路径是文件还是目录。(file.isDirectory())

6.读取目录中的文件列表。(String[] fileNames = file.list())

PS: 在项目中用相对路径读取文件

运用相对路径读取文件,其实就是要找到Java编译(class 文件所在的目录)后的存放目录,然后在该目录下找文件。读取方法有如下两种。

public class RelativePath {
    public static void main(String[] args) {
//        方法一
        String fileName = ReaderTest.class.getResource("/inputTest.txt").getFile();
        System.out.println("*****方法一相对路径读取到的文件地址:"+fileName);
//        方法二
        String fileName1 = Thread.currentThread().getContextClassLoader().getResource("inputTest.txt").getFile();
        System.out.println("*****方法二相对路径读取到的文件地址:"+fileName1);
    }
}      

运行结果:

Java IO基础(同步阻塞IO)

输入和输出

输入流 用来表示那些从不同数据源产生输入的类。这些数据源包括:

1.字节数组

2.String 对象

3.文件

4.“管道”,工作方式与实际管道类似,即,从一端输入,从另一端输出

5.一个由其他种类的流组成的序列,以便我们可以将它们收集合并到一个流内

输出流: 决定输出所要去往的目标,目标包括:

  1. 字节数组
  2. 文件
  3. 管道

基于字节操作的I/O接口: InputStream和OutputStream

InputStream 的类图

Java IO基础(同步阻塞IO)

每个子类的功能以及使用如下图表所示:

Java IO基础(同步阻塞IO)

运用InputStream的实现类读取文件

  1. 方法1️⃣
/**
     * 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。
     * 当然也是可以读字符串的。
     *
     * @param fileName
     */
    public static void readString1(String fileName) throws IOException {
//        FileInputStream 用于读取诸如图像数据之类的原始字节流,读取字符流,请使用FileReader
        InputStream is = new FileInputStream(fileName);
        StringBuilder stringBuilder;
        try {
            stringBuilder = new StringBuilder();
            byte[] bytes = new byte[1024];
            int len;
            while ((len=is.read(bytes))>0) {
                stringBuilder.append(bytes,0,len);
            }
        } finally {
            if (is != null) {
                is.close();
            }
        }
        System.out.println("读取到的结果:" + stringBuilder.toString());
    }      
  1. 方法2️⃣
/**
     * 按字节读取字符串,一次性读取完
     * @param fileName
     * @throws IOException
     */
    public static void readString2(String fileName) throws IOException {
        InputStream inputStream = new FileInputStream(fileName);
        try {
            // size  为字串的长度 ,这里一次性读完
            byte[] bytes = new byte[inputStream.available()];
            inputStream.read(bytes);
            System.out.println("读取到的结果是:"+new String(bytes,"UTF-8"));
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }

    }      

按行读取数据

InputStreamReader   inputStreamReader = new InputStreamReader(new FileInputStream(file),"UTF-8");
         BufferedReader  bufferedReader = new BufferedReader(inputStreamReader);
       while (StringUtils.isNotBlank(line = bufferedReader.readLine())) {
              System.out.println("读取到的结果是:"+line);
        }      

OutputStream 的类图

Java IO基础(同步阻塞IO)

每个子类的功能和使用如下图表所示:

Java IO基础(同步阻塞IO)

运用OutputStream的实现类写入文件

  1. 方法1️⃣

    使用FileOutputStream进行写入。

/**
     * 使用FileOutputStream
     * @param file
     * @throws IOException
     */
    public static void  writeStringToFile1(File file) throws IOException {
        FileOutputStream fos = new FileOutputStream(file);
        try {
            fos.write("www.jay".getBytes());
            fos.flush();
        } finally {
            if (fos != null) {
                fos.close();
            }
        }
    }      
  1. 方法2️⃣

    使用PrintStream进行写入

/**
     * 使用PrintStream写入
     * @param file
     * @throws FileNotFoundException
     */
    public static void writeStringToFile2(File file) throws FileNotFoundException {
        PrintStream printStream = null;
        try {
            printStream = new PrintStream(new FileOutputStream(file));
            printStream.append("你好");
            printStream.append("java");
        } finally {
            if (printStream != null) {
                printStream.close();
            }
        }
    }      
  1. 方法3

    通过 IOUtil 进行数据操作

ByteArrayOutputStream outputStream  = new ByteArrayOutputStream();
   IOUtils.copy(inputStream, outputStream);
   byte[]  buffer=outputStream.toByteArray()      

或者

byte[] buff = new byte[1024];
        BufferedInputStream bis = null;
        OutputStream os = null;
        try {
            os = new ByteArrayOutputStream();
            bis = new BufferedInputStream(stream);
            int len;
            while ((len = bis.read(buff)) >0) {
                os.write(buff, 0, len);
            }
              os.flush();
        }catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                IOUtils.closeQuietly(bis);
            }
            IOUtils.closeQuietly(os);
        }      

基于字符操作的I/O接口:Writer和Reader

Reader 和Writer 与InputStream和OutputStream 的最大区别是,InputStream和OutputStream是基于字节操作的I/O接口。而Reader 和Writer是基于字符操作I/O 接口。通过InputStreamReader适配器可以把InpuStream转换成Reader。通过OutputStreamWriter 适配器可以把OutputStream 转换成Writer。

如下图表示在两个继承层次结构中,信息的来源于去处。

Java IO基础(同步阻塞IO)

Reader 的类图

Java IO基础(同步阻塞IO)

运用Reader的实现类读取文件内容(只能读取字符流)

  1. 方法1️⃣
public static void readFileToString1(String fileName ) throws IOException {
        File file = new File(fileName);
        FileReader fileReader = new FileReader(file);
        int length = Integer.valueOf(String.valueOf(file.length()));
        //定义一个大小等于文件大小的字符数组
        char[] chars = new char[length];
        StringBuilder str = new StringBuilder();
        try {
            int data;
            while ((data=fileReader.read(chars))>0) {
                System.out.println("读取到的字符是="+data);
                str.append(chars);
            }
            System.out.println("读取到的结果:"+str.toString());
        } finally {
            if (fileReader != null) {
                fileReader.close();
            }
        }
    }      
  1. 方法2️⃣
/**
     * InputStreamReader+BufferedReader读取字符串 ,
     * InputStreamReader类是从字节流到字符流的桥梁,
     * 按行读对于要处理的格式化数据是一种读取的好方式
     * @param fileName
     * @throws IOException
     */
    public static void readFileToString2(String fileName) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new FileReader(fileName));
        try {
            StringBuilder stringBuilder = new StringBuilder();
            String data = null;
            while ((data = bufferedReader.readLine()) != null) {
                stringBuilder.append(data);
            }
            System.out.println("读取到的结果:"+stringBuilder.toString());
        } finally {
            if (bufferedReader != null) {
                bufferedReader.close();
            }
        }
    }      

Writer 的类图

Java IO基础(同步阻塞IO)

运用Writer的实现类写入内容到文件

  1. 方法1️⃣
/**
     * 使用BufferedWriter写入
     * @param file
     * @throws IOException
     */
    public static void writeStringToFile1(FileWriter file) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(file);
        bufferedWriter.append("bufferedWriter");
        bufferedWriter.append("测试2111");
        bufferedWriter.close();
    }      
  1. 方法2️⃣
/**
     * 使用PrintWriter写入
     * @param fileWriter
     * @throws IOException
     */
    public static void writeStringToFile2(FileWriter fileWriter) throws IOException {
        PrintWriter printWriter = new PrintWriter(fileWriter);
        printWriter.append("printWriter");
        printWriter.append("实验");
        printWriter.close();
    }      
  1. 方法三

    利用字节流向文件中写入数据。

//创建文件
        File file = new File("test.txt");
        //写入数据
        OutputStream os = null;
        try {
            os = new FileOutputStream(file);
            String testStr = new String("I LOVE YOU");
            os.write(testStr.getBytes());
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                os.close();
            }
        }      

总结

源代码