java io 基础使用

Posted mlover

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java io 基础使用相关的知识,希望对你有一定的参考价值。

记录一下 java io 基本的使用 以及 编码相关的知识

不得不说,java io 相关的类好多呀,每次看都感觉有些乱,暂时也不打算了解太多,先学习一部分,能够进行基本操作,能用就行。
技术图片
图片来源 https://www.codercto.com/courses/d/1491.html


java io 别人写的一系列教程

java io 相关的类主要可以区分为 字符型 和 字节型

这方面我也是在别的博客上学习的,就是上面的图片描述的,感觉按照这两种方式区分的话就比较容易理解
在 io 方面,我还是比较喜欢 c/c++ 语言的处理方式,用一个 char 型就可以解决所有问题,虽然这种方式可能没有 java io 使用方便


下面还是简要说一下 字符型和字节型 io 的区别

  • 字节型 io,就是读写时以字节为基本单位。计算机中的一切,在本质上,都是 2 进制表示的
    对于基础的 ascii 码,需要使用一个字节(8位2进制)直接来表示,我们从文件中能读取的基本单位就是字节。
    这里我们或许可以考虑一下为什么不是 bit,而是 byte,(个人理解,使用 bit 的话,只有两种状态,不足以区分基础的可显示字符,也就是 ascii 码,使用字节的话就比较方便,一次取出 8 bit,这就很容易地通过值区分不同的字符,还有一个原因,应该和计算机内存的最小单位也是字节有关系)

  • 字符型 io,相比于 字节型,可以认为是编程语言帮你多做了一步,它会依次读取字节,根据编码表,如果判断不是一个有效字符的话,就会继续读,直到形成一个有效的字符。这和编码方式有关系。举个将常见的例子,汉字在不同的编码中占用的字节数目是不同的,汉字 以 GBK 方式编码时,占用 2 个字节,以 utf-8 编码时,占用 3 个字节。所以在这两种情形下,我们就可以描述一下 java 的 字符型 io 的工作,当java 读取 的第一个字节时,在GBK的编码表中找不到这个字节对应的字符,那它就还要再向后读,又会读出一个字节,和前一个字节合并再去查编码表,找到对应的字符是 字,其实到这里并没有结束,因为 java 的 char 使用 2字节表示一个字符,所以 java内部 还需要根据 字找到其对应的 char 值(个人理解,感觉越说越麻烦)。其他编码也是相同。


为了说明一下 二者的关系,用一个简短 c 语言程序说明一下,这里会看到 控制台就类似 java 进行 字符 io 时的解码操作

#include <stdio.h>
#include <string.h>

int main()
{
    const char* str = "汉字";
    int len = strlen(str);
    printf("len is %d
", len);
    // 以 char 形式 逐个输出 
    for (int i = 0; i < len; i++) {
        printf("%c", str[i]);
    }
    puts("");
    return 0;
}
  • 新建一个 test.c,设置编码格式为 GBK, 正常情形下,在 windows 控制台上的输出结果是 len = 4,然后输出 汉字
    如果我们把 在控制台 输入chcp 65001, 将控制台的活动代码页修改为 utf-8,即让控制台以 utf-8 解码输出的字节流,可以观察到输出了 len = 4汉字没有输出或者输出是乱码符号。(请注意程序应该在当前修改过活动页的窗口中运行,因为我们的修改只是单次有效)
  • 同上,这次我们将文本的编码格式 设置为 utf-8,同样测试,可以发现,当控制台将活动代码页修改为 utf-8使,才能正常输出结果,同时能够看到 len = 6

还是给自己记录一下,如果可以使用 linux 的 xxd 工具的话,可以使用这个工具查看不同编码下字符的二进制表示,首先,我们可以确定,对于 GBKutf8,汉字在文本中的表示是不同的,对于 c 语言,它并不关心文本的编码方式,所以它会将所有二进制读取,进行编译,输出时也是将文本中对应的二进制输出来,显示结果不同的原因在于控制台的解码方式。java 字符 io 也是如此。


记录一下学习的 io 操作

  • 字符 io 读写文件
package Learn.Io;

import java.io.*;

public class DemoFirst {

    /**
     * 按字符依次读取
     */
    void readForeach() throws IOException {
        final int MAX_SIZE = 1024;              // 如果不能估计 文件字符个数,最好不要使用常量
        char[] save = new char[MAX_SIZE];
        FileReader in = new FileReader("./File/test.txt");
        int charValue, count = 0;
        while (-1 != (charValue = in.read())) {
            save[count++] = (char) charValue;
        }
        in.close();
        System.out.println(String.valueOf(save, 0, count));
    }

    /**
     * 一次性读取到 char 数组中
     * @throws IOException
     */
    void readOnce() throws IOException {
        final int MAX_SIZE = 1024;
        FileReader in = new FileReader("./File/test.txt");
        char[] data = new char[MAX_SIZE];
        int num = in.read(data);
        in.close();
        System.out.println(String.valueOf(data, 0, num));
    }

    /**
     * 字符方式写入文件
     * @throws IOException
     */
    void write() throws IOException {
        // 文件内容会被清除
        FileWriter out = new FileWriter("./File/test.txt");
        String str = "待写入字符";
        char[] s = {'测', '试', '一', '下'};
        out.write(str);
        out.write(s, 0, 2);
        out.flush();
        out.close(); // 关闭时会进行一次 flush 不过还是显式写一下比较好
    }

    public static void main(String[] args) throws IOException{
        DemoFirst test = new DemoFirst();
        test.readForeach();
        test.readOnce();
        test.write();
    }
}
  • 字节方式 读写文件
package Learn.Io;

import java.io.*;

public class ioByChar {
    File file = new File("./File/test.txt");

    /**
     * 循环处理文本
     * @throws IOException
     */
    void readForeach() throws IOException {
        InputStream read = new FileInputStream(file);
        int byteValue, count = 0;
        byte[] data = new byte[1024];
        while (-1 != (byteValue = read.read())) {
            data[count++] = (byte) byteValue;
        }

        System.out.println(new String(data, 0, count));
    }

    /**
     * 一次将文本全部加载到 内存
     * @throws IOException
     */
    void readOnce() throws IOException {
        InputStream in = new FileInputStream(file);
        byte[] data = in.readAllBytes();
        System.out.println(new String(data, 0, data.length));
    }

    /**
     * 按字节写入
     * @throws IOException
     */
    void write() throws IOException {
        OutputStream out = new FileOutputStream(file);
        String str = "写入文本";
        byte[] data = str.getBytes();
        out.write(data, 0, data.length);
        out.flush();
        out.close();
    }

    /**
     * 复制文件 //
     * @param src 源文件
     * @param dst 目的文件
     * @throws IOException
     */
    void copy(File src, File dst) throws IOException {
        InputStream a = new FileInputStream(src);
        OutputStream b = new FileOutputStream(dst, true);
        a.transferTo(b);
        a.close();
        b.close();
    }
    public static void main(String[] args) throws IOException {
        ioByChar test = new ioByChar();
        test.readForeach();
        test.readOnce();
        test.write();
        test.copy(new File("./File/src.txt"), new File("./File/dst.txt"));
    }
}
  • buffered io
    buffer io 相对于 普通 io 相当于加了一层包装,使用缓冲区避免多次访问文件,方法基本和非缓存一样
package Learn.Io;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
 * 这里只写了 BufferedReader BufferedWriter
 * 还有 BufferedInputStream 和 BufferedOutputStream
 */
public class bufferIo {
    static final String filePath = "./File/test.txt";

    /**
     * 按行处理
     * @throws IOException
     */
    void lineRead() throws IOException {
        // BufferedInputStream 不能按行处理
        BufferedReader charRead = new BufferedReader(new FileReader(filePath));
        String read;
        List<String> data = new ArrayList<>();

        while (null != (read = charRead.readLine())) {
            data.add(read);
        }
        System.out.println(data.toString());
        charRead.close();
        // 使用 Stream 处理
//        BufferedReader ano = new BufferedReader(new FileReader(filePath));
//        ano.lines().map((e) -> e + '|' +  e.length()).forEach(System.out::println);
//        ano.close();
    }

    /**
     *
     * @throws IOException
     */
    void Write() throws IOException {
        BufferedWriter out = new BufferedWriter(new FileWriter(filePath));
        out.write("line 1");
        out.newLine();
        out.write("line 2");
        out.flush();
        out.close();
    }
    public static void main(String[] args) throws IOException {
        bufferIo s = new bufferIo();
        s.lineRead();
        s.Write();
    }
}
  • 根据指定编码读写文件
package Learn.Io;

import java.io.*;

public class fileIo {

    /**
     * 读取指定编码的文件
     * 这里关心文件的编码 所以使用 Reader 和 Writer
     * @param filePath 文件路径
     * @param encoding 文件编码
     */
    void read(String filePath, String encoding) throws IOException {
        File file = new File(filePath);
        InputStreamReader in = new InputStreamReader(new FileInputStream(file), encoding);
        char[] data = new char[1024];
        in.read(data);
        in.close();
        System.out.println(data);
    }

    /**
     * 使用 bufferIo 读取
     * @param filePath
     * @param encoding
     * @throws IOException
     */
    void bufferRead(String filePath, String encoding) throws IOException {
        File file = new File(filePath);
        BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), encoding));
        // Stream 很方便
        in.lines().forEach(System.out::println);
        in.close();
    }

    /**
     * 字节流读取,使用 String 解码
     * 这种方式没有 字符流安全,按字节读取有可能读取到某个字符的一部分就终止了
     * 这时如果使用 字符集去解码,就会造成问题
     * 如果是要将文件整体读入,作为一个字符串处理,则可以用这种方式
     * @param filePath
     * @param encoding
     */
    void byteRead(String filePath, String encoding) throws IOException {
        File file = new File(filePath);
        InputStream in = new FileInputStream(file);
        byte[] data = in.readAllBytes();
        System.out.println(new String(data, encoding));
    }

    /**
     * 输出与上述相反,Reader <=> Writer Input <=> Output 就不写了
     */
    void write() {

    }

    public static void main(String[] args) throws IOException {
        fileIo rw = new fileIo();
        rw.read("./File/test.txt", "gbk");
        rw.read("./File/test.txt", "gbk");
    }
}
  • 格式化数据
package Learn.Io;

import java.io.*;
import java.util.stream.IntStream;

public class formatIo {

    /**
     * 利用 printf 格式化数据写入文件
     * @throws FileNotFoundException
     */
    void writeFormatDataToFile() throws FileNotFoundException {
        PrintWriter out = new PrintWriter("./File/test.txt");
        IntStream.range(0, 10).forEach(e -> out.printf("number of this line is %3d
", e));
        out.flush();
        out.close();
    }

    /**
     * 格式化数据输入 字符串
     * @throws IOException
     */
    void formatDataToString() throws IOException {
        StringWriter str = new StringWriter();
        PrintWriter w = new PrintWriter(str);
        w.printf("10 的 16进制表示 : %#06x", 10);
        w.flush();
        w.close();
        str.close();
        System.out.println(str);
    }

    public static void main(String[] args) throws IOException {
        formatIo rw = new formatIo();
        rw.writeFormatDataToFile();
        rw.formatDataToString();
    }
}
  • 其他一些
package Learn.Io;

import java.io.*;

public class vector {

    /**
     * 感觉 java 中的 ByteArrayOutputStream CharArrayWriter 实现的功能类似 c++ 中的 vector
     * @throws IOException
     */
    void readIntoByteArray() throws IOException {
        InputStream in = new FileInputStream("./File/test.txt");
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        int num;
        while (-1 != (num = in.read())) {
            data.write(num);
        }
        in.close();
        System.out.println(data);
    }

    /**
     * 使用 StringReader 和 StringWriter
     * @throws IOException
     */
    void rwString() throws IOException {
        String str = "this is a string";
        StringReader in = new StringReader(str);
        StringWriter out = new StringWriter();
        PrintWriter w = new PrintWriter(out);
        w.println("first line");
        in.transferTo(out);         // 输入流传送到输出流
        in.close();
        out.close();
        System.out.println(str);
        System.out.println("---------------");
        System.out.println(out);
    }

    public static void main(String[] args) throws IOException {
        vector s = new vector();
        s.readIntoByteArray();
        s.rwString();
    }
}

还有一些还没学...

以上是关于java io 基础使用的主要内容,如果未能解决你的问题,请参考以下文章

Java语言基础之方法的设计

JSP基础

iOS代码片段CodeSnippets

iOS开发CGRectGetMidX. CGRectGetMidY.CGRectGetMinY. CGRectGetMaxY. CGRectGetMinX. CGRectGetMaxX的使用(代码片段

iOS开发CGRectGetMidX. CGRectGetMidY.CGRectGetMinY. CGRectGetMaxY. CGRectGetMinX. CGRectGetMaxX的使用(代码片段

如何使用 Swift 使用此代码片段为 iOS 应用程序初始化 SDK?