IO基础小结1(文件输出输入流)

* IO流:用来进行设备间数据传输的问题. 电脑与电脑 电脑与手机
*
* 按流向分:
*   相对的是程序
*       输入流:往程序里面输入,也就是读取数据,就是硬盘--->内存
*       输出流:程序往外面输出,也就是写出数据,就是内存--->硬盘
*
* 按类型分:
*   数据类型
*      字节流:
*      字符流:字符流的出现,是为了方便操作文本(中文,日本,韩文..)数据
*       以后我们到底使用哪种类型的流呢?
*           如果操作的是文本文件,就用字符流,否则就用字节流.
*           也就是说如果这个文件用记事本打开,我们能读懂,那就用字符流.否则就用
*           字节流.
*           如果不清楚,就用字节流.
*
* 组合起来就是:
*            字符输入流, Reader
*            字符输出流. Writer
*            字节输入流, InputStream
*            字节输出流. OutputStream
/*
* 创建字节输出流对象做了几件事情:
* A:调用系统功能去创建文件
* B:创建fos对象
* 把fos对象指向这个文件.
* 这样我们就可以对文件进行操作了.
* */
FileOutputStream fos = new FileOutputStream("demo.txt");

fos.write("测试".getBytes());
/*
* 为什么要close()?
*   这个close做了两件事情:
*       1,让流对象变成垃圾,这样就可以被垃圾回收期回收了
*       2,也是最关键的.是通知系统去释放该文件相关的资源.
*       如果我们不关闭,它就一直开着,因为系统不知道我们还需不需要继续使用
*       所以如果我们不用了,就需要关闭.
*       否则它会一直占用系统资源
* */
fos.close();
// 文件输出流
public static void main(String[] args) {
        /*
         *异常处理的标准写法
         * */
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("demo2.txt");
            fos.write("测试".getBytes());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
//            必须要做的事情
//            如果fos不是null,才关闭,如果是空的,就没有关闭的必要了
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
// 文件输入流
public static void main(String[] args) throws IOException {
    FileInputStream fis = new FileInputStream("demo2.txt");
    // 易读版文件输入流
    /* 
    int rs = fis.read();
    while ( rs!= -1) {
    System.out.print((char) rs);
    rs  = fis.read();
    }
    */
    // 最终版代码
    int rs;
    // 读取,赋值,判断
    while ((rs = fis.read())!=-1){
        System.out.print((char)rs);
    }
    fis.close();
}
/*
* 复制文本文件案例.此案例用字节流都可复制文本数据,复制音频,视频是相同的代码,更容易理解
* 数据源:从哪里来.
*   读数据
* 目的地:到哪里去,
*   写数据
* 一个汉字,分成两个字节,第一个字节肯定是负数
* 为什么中文第一个字节肯定是负数?

补充1:

https://www.cnblogs.com/web21/p/6092414.html

UNICODE是万能编码,包含了所有符号的编码,它规定了所有符号在计算机底层的二进制的表示顺序。有关Unicode为什么会出现就不叙述了,Unicode是针对所有计算机的使用者定义一套统一的编码规范,这样计算机使用者就避免了编码转换的问题。Unicode定义了所有符号的二进制形式,也就是符号如何在计算机内部存储的,而且每个符号规定都必须使用两个字节来表示,也就是用16位二进制去代表一个符号,这样就导致了一个问题,英文编码的空间浪费,因为在ANSI中的符号都是一个字节来表示的,而使用了UNICODE编码就白白浪费了一个字节。也就代表着Unicode需要使用两倍的空间去存储相应的ANSI编码下的符号。虽然现在硬盘或者内存都很廉价,但是在网络传输中,这个问题就凸显出来了,你可以这样想想,本来1M的带宽在ANSI下可以代表1024*1024个字符,但是在Unicode下却只能代表1024*1024/2个字符。也就是1MB/s的带宽只能等价于512KB/s,这个很可怕啊。所以为了解决符号在网络中传输的浪费问题,就出现了UTF-8编码,Unicode transfer format -8 ,后面的8代表是以8位二进制为单位来传输符号的,但是这样又导致了一个问题,虽然UTF-8可以使用一个字节来表示ANSI下的符号,但是对于其它类似汉语的符号,得需要两个字节来表示,所以计算机不知道如何去截取一个符号,也就是一个符号对应的二进制的截取开始位置和截取结束位置。所以为了解决Unicode下的ANSI符号的空间浪费和网络传输下如何截取字符的问题,UTF规定:如果一个符号只占一个字节,那么这个8位字节的第一位就为0。如果为两个字节,那么规定第一个字节的前两位都为1,然后第一个字节的第三位为0,第二个字节的前两位为10,然后如果是三个字节的话,那么第一个字节的前三位为111,第四位为0,剩余的两个字节的前两位都为10。按照这样的算法去思考一个中文字符的UTF-8是怎么表示的:一个中文字符需要两个字节来表示,两个字节一共是16位,那么UTF-8下,两个字节是不够的,因为两个字节下,第一个字节已经占据了三位:110,然后剩余的一个字节占据了两位:10,现在就只剩下11位,与Unicode下的两个字节,16位去表示任意一个字符是相悖的。所以就使用三个字节去表示非ANSI字符:三个字节下,一共是24位,第一个字节头四位是:1110,后两个字节的前两位都是:10,那么24位-8位=16位,刚好两个字节去表示Unicode下的任意一个非ANSI字符。这也就是为什么UTF-8需要使用三个字节去表示一个非ANSI字符的原因了!

  题外话:

  中国的汉字多达10多万,常用的汉字3500左右[08年统计],如果用3个字节来表示,一共只有2^16(65535)种可能,不足以表示10多万的汉字。所以中日韩的超大字符集是采用的4个字节来表示的,多达6万多个。但是平时使用超大字符集的概率0.01%都不到。所以我们一般认为日常的中文在UTF-8中占三个字节 即可!

补充2:

https://zhidao.baidu.com/question/342798633.html

汉字的ASCII是负数是因为你错误使用有符号的整型观察它,它实质上不是负数。

相关问题细节如下:

  1. 英文标准的ASCII码中只有128个符号,只需要7位,但是计算机分配存储的最基本单位是字节,至少是8位,因此最高位为0;

  2. 因此常见的西文符号的ASCII都是在0-127之间,无论是有符号还是无符号去观察它们,都是正的。

  3. 中文的符号远超过256个,因此用一个字节不能存储汉字,早期的GB2312采用了两个字节。

  4. 但是很麻烦的问题是一个汉字用两个字节存储在计算机中后,和两个西文字母的ASCII混淆,为了避免这个混淆,汉字两个字节的最高位都是1。

  5. 如果用有符号的数去读取一个汉字的内容,最高位的1正好和负号位置相同,因此此时就会发现汉字的内吗是负的。

    实质上汉字应该用字符型而不是整型去读取和显示它。

* 所以计算机知道什么时候该拼,什么时候是字母.
* read()方法返回的是当前读出的字节
*
* */
public static void main(String[] args) throws IOException {
    FileInputStream fis = new FileInputStream("demo2.txt");
    FileOutputStream fos = new FileOutputStream("demo3.txt");
    int rs = 0;
    while ((rs = fis.read())!=-1){
       fos.write(rs);
    }
    fos.close();
    fis.close();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值