Java SE学习总结 Day (22)

Day 22开篇:
      
        "
今天java基础主要学习了I/O流的概念,I/O流进行分类,I/O流的类型(40多种),FileOutputStream的写出方式,构造方法, 递归的定义,注意事项,FileOutputStream的构造等 "


知识点反馈:

今天的知识点总结的思维导图

 
 

一.I/O流
1. 概念:
(1)I/O是input/output的缩写,I/O技术是一个非常实用的技术,被广泛的应用在设备之间的数据传输,读写文件、网络通信等
(2)在Java当中,对于所有在物理硬件输入/输出都要依靠stream(流)的方式进行操作
(3)Scanner sc = new Scaner(System.in) 从键盘获取数据的对象(数据怎么来的,是不是从硬件[键盘]识别过来),也就意味着这个对象就必须依靠stream(流)来进处理,System.in = InputStream(输入流)
2. I/O流进行分类:
(1)input(输入):从java当中读取外部数据(磁盘、光盘等存储设备的介质)到内存当中
(2)output(输出):将JVM内存的数据,写出(输出)到存储介质当中
3.I/O流的类型(40多种):
(1)字节流(1个字节,8bit):
<1>字节输出流:outputStream
<2>字节输入流:inputStream
(2)字符流(2个字节,16bit):
<1>字符输出流:Writer
<2>字符输入流:Reader
(3)他们40多种的流,基本上都是这个4个衍生出来的,所有每一个流的命名都是基于父类命名;一旦出现了Stream的字样基本就是字节流的子类,一旦出现Reader的字样基本都是字符流;输出流一定会有output,输入流一定会有input。
(4)除了如上4中流的分类,还有几个特殊的流,高效流(也是字节或者字符的一种,只不过带有缓冲区,处理的速度比较高效),转换流(其实就是一个字节转换为字符的中转流)等
(5)注意:我们一般在商讨使用某一种流的时候,基本上上都是说按照某种分类来说,比如说,我需要写一句话,"香港的废青,快开学了"
(6)分析:
<1>使用什么流向?
    输出流:output
    什么分类?
字符流(我们现在不讲字符,因为java本质上没有所谓的字符流,都是基于字节转换过来的,所以先讲字节)  Stream = outputStream
<2>通过分析,我们知道要使用的outputStream
看API得出结论:
a. OutputStream是一个抽象类,无法直接实例,必须依靠具体的子类来实例
b. 得到具体子类FileOutputStream,文件输出流是用于将数据写入File 或 FileDescriptor 的      输出流;本质上,只要能够在你的计算机上面存储任何东西都可以表示文件,FileOutputStream 都可以写
c.  FileOutputStream的构造
FileOutputStream(File file):通过一个File对象构建一个写出的路径地址
FileOutputStream(File file, boolean append):通过一个File对象构建一个写出的路径地址,并指定是否可以对内容进行追加
第一次写:a.txt -> hello
第二次写:
无追加 a.txt -> word
有追加 a.txt -> helloword
FileOutputStream(String name) 直接提供一个String类型路径,会自动转换为File对象
FileOutputStream(String name, boolean append):直接提供一个String类型路径,会自动转换为File对象,并指定是否可以对内容进行追加
d.  FileOutputStream的成员方法
write(int b):按照整数用字节的方式写出到文件当中 char c = 97; = a
(7)注意:
a. 如果使用FileOutputStream(file),如果目录下存在同名文件,则会被直接覆盖,如果不存在则直接创建
b. 如果使用FileOutputStream(file,true),如果目录下存在同名文件不会被覆盖,并且在末尾追加新的内容
c. 写出文件,如果不存在会有自动创建的操作,读取文件,如果文件不存在则直接GG
d. 字节流可以操作一切具备字节的文件:mp3 avi rmvb doc ppt
e. 字符流只能操作字符,只能操作比较普通的文本内容,txt java .c .cpp,一定要注意,doc excel ppt这些文件不属于文本内容,不能读取
(8)简单记:
a. 字符能操作的,字节都能操作
b. 右键用记事本打开能够看得懂的都用字符,否则用字节
4.FileOutputStream的写出方式:
(1)void write(byte[] b):一次写出一个数组的数据
(2)void write(byte[] b, int off, int len) 一次写入一个指定长度开始,一次写入多少给
(3)void write(int b) 按照整数用字节的方式写出到文件当中 char c = 97; = a,一次只能写出一个数据
5.如何使用字节的方式存储一个字符串:
(1)使用String的getBytes()进行字符串转字节数组就可以了
6.如何进行换行:
(1)针对不同的操作系统,换行的识别方式也不一致
(2)Windows:\r\n
(3)linux:\n
(4)Mac:\r
(5)在编码过程当中,如果存在编译可以不用太多考虑,因为编译器会帮你处理好
     但是如果上线到生产环境,请务必考虑生产环境的的操作系统,决定使用什么换行
7. 哪一种的效率会比较的高:
第一种:
        单个字节的输入和输出
    第二种:
        构建一个带有缓冲区数组的输入输出
答:第二种,因为第二种存在了有个数据缓冲区的问题。(以后凡是看见所谓带缓冲区字样的技术,基本上都是效率优化相关的操作)既然带有缓冲区的输入输出比较效率,java本身也考虑到这个问题了,就给我们的字节输入输出流都分别提供一个缓冲区流(高效流)这个所谓的高效流,并没有多神奇,只不过我们之前创建数组的步骤,他给封装了起来了哦
8. 构造:
(1)BufferedInputStream(InputStream in)封装一个InputStream对象,构造成一个高效流默认构建一个8192大小的缓冲区,是1024的8倍大小
(2)BufferedInputStream(InputStream in, int size)创建具有指定缓冲区大小的 BufferedInputStream.这个构造基本不用,因为默认的缓冲区大小已经足够我们使用了,当不够的时候可以自定义
9.输入:
inputStream:所有字节输入流的基类(抽象类)
10.子类:
FileInputStream:从文件中以字节的方式流入到Java的内存当中
11. 构造方法:
(1)FileInputStream(File file):通过file对象构建一个字节输入流
(2)FileInputStream(String name):通过字符串构建一个file对象,构造一个字节输入流
12.成员方法:
(1)int        read():从输入流获取下一个字节,返回的是0-255的范围内的int字节值,如果到达文件末尾或者说文件不存在任何字节则返回-1.
问题1:int read()读取的只是下一个字节,将字节转换为字符,输出数字和字母的时候 没有任何问题,但是读取到中文只显示一个?号.
原因:因为int read()读取的单个字节,而一个中文是一个字符,一个字符需要两个字节组成,所有1个字节是无法组成一个中文的
问题2:int read()读取一个字节太麻烦,如何一个文件存在很多字节,是不是要写n个?
解决:使用循环解决重复步骤,什么时候停止循环,当返回值为-1的时候
参考:
                        int b = fis.read();
                        while (b != -1){
                            System.out.println((char)b);
                            b = fis.read();
                        }
                        -------------------------
                        int by = 0;
                        while ((by = fis.read()) != -1){
                            System.out.println((char)by);
                        }
(2)int read()读取字节无法转换为中文的问题: 1个 != 中文
原因就是read()只读取单个字节,而一个中文字符需要两个字节组成
(3)int        read(byte[] b):20个 = 中文
    在输入流当中获取获取一个byte数组的数据,一次可以获取n个字节。如果到达文件末尾或者说文件不存在任何字节则返回-1,否则以整数形式返回实际读取的数据的字节数
(4)使用read(byte[] b)构建新的String
A. 创建一个用于存储的字节容器数组
   byte [] bys = new byte[500];
   bys的数组长度,尽量和文件字节数量进行匹配,长度不够则部分无法显示,长度太长则内存浪费
B. 使用read(byte[] b),将每一次读取的字节存储到容器当中
   int len = fis.read(bys);
len接收的是当前文件字节的总长度
C. 此时,bys会存储文件所有的字节值,使用String的构造,对bys的字节进行构造成字符串String s = new String(bys);
   
(5)举例:
public class FileinputStreamDemo01 {
    public static void main(String[] args) throws Exception {
        File file = new File("D:\\Input\\hello2.txt
")
        FileInputStream fis = new FileInputStream(file);
 
        //返回的是数据对应的字节值
        //int by = fis.read();
        //System.out.println(by);
        //这个字节值,给我们 也看不懂啥情况,我需要显示出来具体的内容,怎么办?
        //当我们将一个字节转换为char的时候,数字和字母和转换显示是没有问题的。
        //但是当我们转换的是一个中文的时候,出来的是一个?号
        //原因呢?一个中文几个字节?2个字节! fis.read()读取几个字节?1个字,是不是中文只读一半,所有无法识别。
        //System.out.println((char)by);
 
        //第二次读取
        //by = fis.read();
        //System.out.println((char)by);
 
        //我需要显示中文,咋办?
        //方式一
//        int b = fis.read();
//        while (b != -1){
//            System.out.println((char)b);
//            b = fis.read();
//        }
 
        //方式二
        int by = 0;
        while ((by = fis.read()) != -1){
            System.out.println((char)by);
        }
}
}
13.解决问题:
虽然我们上一个案例当中,已经可以对中文进行处理,但是不是特别好数组的长度,不好确定!长了,短了都不好用
怎么解决?
        int        read(byte[] b, int off, int len):
            指定一个字节数组容器,
            从指点位置开始读取,
            读取多少个数据
 
        String(byte[] bytes, int offset, int length)
 
 
 
二.Recursion
1. 递归的定义:
          一般是指一个方法被重复的自身调用或者其他方法无止境的调用,递归应该调用是方法
所以对内存的消耗开支比较大,GC回收的速度,低于内存开辟的速度。(极容易造成内存溢出)
2. 注意:
如非必要,不建议去使用递归,除非你能精确的控制停止的时机


 

发布了29 篇原创文章 · 获赞 7 · 访问量 3160

猜你喜欢

转载自blog.csdn.net/weixin_45406656/article/details/104288256