Java-io流--字节流与字符流

1、常见字符编码

1.1、ACSII码

美国信息交换标准代码,是一种基于拉丁字母的字符编码标准。用一个字节来表示一个字符,共8位,首位是数字0,后7位二进制数表示2^{7}(即128)个字符。其中,(十进制)数字0对应48,大写字母A对应65,小写字母a对应97。

1.2、GBK

是一种汉字编码标准,由中国国家标准总局发布。用两个字节来表示一个字符,共16位,首位是1,后15位二进制数表示2^{15}个字符。它兼容GB 2312编码,共收录了21886个汉字和符号,覆盖了绝大部分常用的汉字。

1.3、UTF-8

是当下使用最广泛的一种字符编码,是一种针对 Unicode 的可变长度字符编码,使用 1 到 4 个字节来表示每个字符,与 ASCII 兼容。

  • 1 字节:0xxxxxxx(ASCII 字符)
  • 2 字节:110xxxxx 10xxxxxx
  • 3 字节:1110xxxx 10xxxxxx 10xxxxxx(常用汉字字符)
  • 4 字节:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

注意:编码与解码时使用的字符集如果不相同,一般会出现乱码问题(数字,字母一般不会乱码)

2、字节流

2.1、字节输入流InputStream的实现类文件字节输入流FileInputStream

FileInputStream:从文件中按字节读取

常用构造器:

// 通过指定文件路径创建 FileInputStream
FileInputStream(String name) throws FileNotFoundException

// 通过 File 对象创建 FileInputStream
FileInputStream(File file) throws FileNotFoundException

 常用方法:

// 从输入流中读取一个字节的数据,返回字节的整数值,如果到达文件末尾则返回 -1
int read() throws IOException

// 从输入流中读取多个字节数据并存储在字节数组 b 中,返回实际读取的字节数,如果到达文件末尾则返回 -1
int read(byte[] b) throws IOException

// 从输入流中读取最多 len 个字节的数据并存储在字节数组 b 中,从 off 位置开始存储,返回实际读取的字节数,如果到达文件末尾则返回 -1
int read(byte[] b, int off, int len) throws IOException

// 跳过并丢弃输入流中的 n 个字节数据,返回实际跳过的字节数
long skip(long n) throws IOException

// 关闭输入流并释放与之相关的系统资源
void close() throws IOException

测试用例:

当使用 FileInputStream 读取包含中文的文本文件

import java.io.InputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class ReadFile {
    public static void main(String[] args) {
        try (InputStream is = new FileInputStream("a.txt")) {
            int content;
            while ((content = is.read()) != -1) {
                System.out.print((char) content);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            is.close();
        }
    }
}
 

乱码问题:

上述代码可能会出现乱码问题。这是因为 FileInputStream 是按字节读取文件的,读取包含中文的文本文件时,中文字符通常占用多个字节(如 UTF-8 编码下,一个中文字符通常占用 3 个字节)。如果直接将这些字节转换为字符,可能会导致字符编码不匹配,从而出现乱码。

解决:

1、一次性读完文件所有字节。

2、使用高级流读取(以后再讲)。

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class ReadFile {
    public static void main(String[] args) throws Exception {    // 不推荐直接抛异常
        File file = new File("a.txt");
        InputStream inputStream = new FileInputStream(file);

        // 方式1
        long size = file.length();
        byte[] b1 = new byte[(int)size];  // 仅适用文件不会超过int的最大值的情况
        int len;
        while((len =i nputStream.read(b1)) != -1){
            System.out.println(new String(b1,0,len));
        }
        // 方式2
        byte[] b2 = inputStream.readAllBytes();
        System.out.println(new String(b2));

        inputStream.close();
    }
}

2.2、字节输出流OutputStream的实现类文件字节输入流FileOutputStream

FileOutputStream :通常用于写入字节数据到文件中。

常用构造器:

// 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
public FileOutputStream(File file);

// 创建一个向指定 File 对象表示的文件中写入数据的文件输出流,如果第二个参数为 true,则将字节写入文件末尾而不是文件开头(追加)。
public FileOutputStream(File file, boolean append);

// 创建一个向具有指定名称的文件中写入数据的文件输出流。
public FileOutputStream(String name);

// 创建一个向具有指定名称的文件中写入数据的文件输出流,如果第二个参数为 true,则将字节写入文件末尾而不是文件开头(追加)。
public FileOutputStream(String name, boolean append);

常用方法:

// 将指定字节写入此文件输出流。
public void write(int b);

// 将指定字节数组中的字节写入此文件输出流。
public void write(byte[] b);

// 将指定字节数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
public void write(byte[] b, int off, int len);

// 关闭此文件输出流并释放与此流关联的所有系统资源。
public void close();

// 刷新此输出流并强制写出所有缓冲的输出字节。
public void flush();

测试用例:

使用 FileOutputStream 将字符串写入文件

import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamExample {
    public static void main(String[] args) {
        String s= "Hello, World!";
        try (OutputStream os = new FileOutputStream("b.txt")) {
            byte[] byteArray = s.getBytes();
            os.write(byteArray);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            os.close();
        }
    }
}
 

3、释放资源方式

3.1、try-catch-finally

try {
    //定义资源
    // 可能出现异常的代码块
} catch(Exception e) {
    // 异常处理
} finally {
    // 无论try中代码块是否正常执行还是出现异常,此处的代码都会执行,即使有return;也仍然会执行,除非直接终止JVM
    // 将流的关闭放在此处可保证流可以正常关闭释放资源
}

 3.2、try-with-resource

try(定义资源1; 定义资源2;) {    // 将定义对象放在此处,当使用完后,系统会自动帮我们管理资源,不需要我们手动释放
    //可能异常代码块
} catch(Exception e) {
    //异常处理
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一轮弯弯的明月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值