总结

说白了,字节流就是处理类似图片文件、视频文件这些不能直接用记事本打开看的明白的文件。

    字符流就是处理可以用记事本直接看的文件。

无论是字节流还是字符流,都有有输入输出两类。(废话)

如果要读取字节流,我们一般使用FileInputStream就可以了,如果需要设置缓冲区大小,那就用BufferedInputStream。

  读取的时候,我们一般使用数组读取。这样能有效减少程序与硬盘交互的时间,提高效率。(或者使用缓冲区,但是无论是否使用缓冲区,我们都最好使用数组读取)

一般我会这样读取:(数组大小的选取尽量是2的整数次方,另外的大小的选取可参考数学模型分析:不同方式复制文件所需的时间)

byte[] data = new byte[2048];
int length =-1;
while((length = fileInputStream.read(data))>=0)
fileOutputStream.write(data,0,length);

字节流:

  InputStream

    FileInputStream(常用)

    BufferedInputStream 包装流

  OutputStream

    FileOutputStream(常用)

    BufferedOutputStream包装流

字符流:

  Reader

    InputStreamReader

      FileReader(常用)

    BufferedReader

  Writer

    OutputStreamWriter

      FileWriter(常用)

    BufferedWriter

练习

1、复制文件

2、读取文本文件,按行分类

3、复制文件夹以及其中的所有文件

4、统计xxx.txt文件中字母a的数量

参考:

1、复制文件

使用字节流操作。

    //FileInputStream实现字节流文件的复制
public static void CopyFile(String source,String target){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(source);
fileOutputStream = new FileOutputStream(target); byte[] data = new byte[2048];
int length =-1;
while((length = fileInputStream.read(data))>=0)
fileOutputStream.write(data,0,length); } catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

2、读取文本文件,按行分类

按行输出,我们考虑使用字符流中的BufferedWriter和BufferedReader中的ReadLine。

并且使用ArrayList<String>中的add方法进行存储即可。

//BufferedWriter和BufferedReader实现按行输出
public static void showLine(String source){
BufferedReader bufferedReader=null;
//创建String类型的ArrayList
ArrayList<String> strList = new ArrayList<String>();
try {
FileReader fileReader = new FileReader(source);
bufferedReader = new BufferedReader(fileReader);
String data =null;
while((data = bufferedReader.readLine())!=null)
strList.add(data); } catch (IOException e) {
e.printStackTrace();
}finally{
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//输出到控制台
for (String temp:strList)
System.out.println(temp);
}

3、复制文件夹以及其中的所有文件

本题我们分步分解,第一步先复制当前目录下的全部文件,第二步再复制文件夹中包含的子文件夹(有可能子文件夹中还有文件夹)。

第一步:

//复制某一文件夹下的所有文件(不包括子文件夹)到新的目录下
public static void copyFileWithDir(String sourceDir,String targetDir) {
File sDir =new File(sourceDir);
File tDir =new File(targetDir);
tDir.mkdirs();
File[] files = sDir.listFiles();
for (File tempFile : files)
if(!tempFile.isDirectory()){//当File不是目录的时候复制
File newFile = new File(tDir,tempFile.getName());
try {
Files.copy(tempFile.toPath(),newFile.toPath());
} catch (IOException e) {
e.printStackTrace();
}
}
}

第二步:

因为不确定他的目录层级结构,所以我们需要使用递归的操作。

我们只需要对上面的方法稍作修改即可。

当我们判断File是否为目录时,若是目录,则再调用一次copyFileWithDir()方法即可。由于方便区分,我们将方法名字改为copyFileWithDirs()。

//复制某一文件夹下的所有文件(不包括子文件夹)到新的目录下
public static void copyFileWithDirs(String sourceDir,String targetDir) {
File sDir =new File(sourceDir);
File tDir =new File(targetDir);
tDir.mkdirs();
File[] files = sDir.listFiles();
for (File tempFile : files) {
File newFile = new File(tDir, tempFile.getName());
if (!tempFile.isDirectory()) {//当File不是目录的时候复制
try {
Files.copy(tempFile.toPath(), newFile.toPath());
} catch (IOException e) {
e.printStackTrace();
}
} else {//如果temp是目录,则递归
System.out.println(tempFile.getName());
copyFileWithDirs(tempFile.getAbsolutePath(),newFile.getAbsolutePath());
}
}
}

测试文件夹。

本人调用测试方法如下:

copyFileWithDirs("//Users//Shared//JavaIOTest//TestCopyDir//Test01","//Users//Shared//JavaIOTest//TestCopyDir//Test02");

4、统计xxx.txt文件中字母a的数量

这个题就比较简单了,我就不写了,使用FileReader一个一个字符读就好啦。

至于更高效率的方法,就不是现在讨论的内容了,这里重点掌握好FileReader字符流的使用即可。


数据类型
        文本数据
        二进制(字节)数据
    
    数据流
        字节流 可以读取任意类型数据
            抽象基类:InputStream OutputStream
        字符流 只可以读取文本数据
            抽象基类:Reader Writer

文件输入\输出流
    FileOutputStream
        构造方法
            FileOutputStream(File file)
            FileOutputSteram(String name)
            FileOutputStream(File file,boolean append)
            FileOutputSteram(String name,boolean append)
        方法
            write(int b)  (相当于把数字代表的字符写进去)
            write(byte[] b)
            write(byte[] b,int offset,int length)
            close
        备注
            不同操作系统的换行操作:https://blog.csdn.net/tskyfree/article/details/8121951
    FileInputStream
        构造方法
            FileInputStream(String name)
            FileInputStream(File file)
        方法
            int read();一次读取一个字节,-1表示文件末尾
            int read(byte[] b);//一次读取一个字节数组 ,返回值表示读取到了多少个字节,如果读取到了文件末尾,返回-1
                为什么不定义一个很大的数组,然后一次性读取完?
                数组设置多大合适?
    
    练习:    1,文本文件复制。(FileInputStream,FileOutputStream)
            2,其他格式文件复制
    
缓冲区输入\输出流(用来做包装)
    BufferedOutputStream
        构造方法
            BufferedOutputStream(OutputStream stream)
        方法
            同上(FileOutputStream)
    BufferedInputStream
        构造方法一样
        方法
            同上(FileInputStream)
    
    InputStream:    FileInputStream        BufferedInputStream
    OutputStream:    FileOutputStream    BufferedOutputStream
    
    四个方法完成文件复制,比较效率!

字符流(不用编码下,中文字符所占有的字节个数是不一样的)
    
    java中的编码格式:https://www.cnblogs.com/yuan1164345228/p/6937958.html
        ASCII GB2312 GBK UTF-8
    编码是用来表示如何把字符使用数字存储起来的。(比如一个字符占几个字节,判断这个字节里面存储的是中文字符还是英文字符)
        一个字符对应一个数字。
    几乎所有由文字和字符的地方,都有编码的存在!
    数据一般是转换为字节来存储或者传输,我们拿到字节后,要通过编码来转换成人眼可以识别的字符。
    字节和字符之间的转换,需要通过固定的编码来完成。
    
    Java里面默认的编码为GBK
        
    文件设置的编码,程序读取的编码,程序写入的编码
    
    OutputStreamWriter
        构造方法
            OutputStreamWriter(OutputStream stream);
            OutputStreamWriter(OutputStream stream,String charsetName);
        方法
            void write(int c);//写入一个字符
            void write(char[] cbuf);写入字符数组
            void write(char[] cbuf,int off,int len);
            void write(String str);
            void write(String str,int off,int len);
            
            flush();刷新缓冲区
            close();释放资源
    InputStreamReader
        构造方法
            InputStreamReader(InputStream stream);
            InputStreamReader(InputStream stream,String charsetName);
        方法
            int read();
            int read(char[] cbuf);
    
    OutputStreamWriter-->FileWriter
        构造方法
            FileWriter(String fileName)
            FileWriter(String fileName,boolean append)
    InputStreamReader-->FileReader
        构造方法
            FileReader(String fileName)
            
    练习:文本文件复制(1,单个字符    2,字符数组)
    
    BufferedWriter
        BufferedWriter(Writer out)
        BufferedWriter(Writer out,int size)
    
    BufferedReader
        readLine()

字节流
    InputStream
        FileInputStream
        BufferedInputStream 包装流    
    OutputStream
        FileOutputStream
        BufferedOutputStream
字符流
    Reader
        InputStreamReader     包装流(可以包装字节流)
            FileReader
        BufferedReader        包装流(可以包装字符流)
    Writer
        OutputStreamWriter
            FileWriter
        BufferedWriter


至此,我们的IO流就全部学完啦,只要能够独立解决上面的四个问题,那么IO流你就基本掌握了。

下一章,我们将学习多线程相关的知识,下一章再见吧!

【java】学习路径43-IO流总结与练习题!的更多相关文章

  1. Java学习笔记-10.io流

    1.输入流,只能从中读取数据,而不能向其写出数据.输出流,只能想起写入字节数据,而不能从中读取. 2.InputStream的类型有: ByteArrayInputStream 包含一个内存缓冲区,字 ...

  2. Java学习路径及练手项目合集

    Java 在编程语言排行榜中一直位列前排,可知 Java 语言的受欢迎程度了. 实验楼上的[Java 学习路径]中将首先完成 Java基础.JDK.JDBC.正则表达式等基础实验,然后进阶到 J2SE ...

  3. Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)

    声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutpu ...

  4. Java学习路径(抛光砖)

    这就是我刚刚在五孔问答中找到的Java学习路线图抛光砖价格.我个人认为,这条Java学习路线是可以的.它是2018年相对较新的Java学习路线,更符合企业就业标准. Java学习路径的第一阶段:Jav ...

  5. java基础43 IO流技术(输入字节流/缓冲输入字节流)

    通过File对象可以读取文件或者文件夹的属性数据,如果要读取文件的内容数据,那么我们就要使用IO技术. 一.输入字节流 输入字节流的体系:  -------| InputStream:所有输入字节流的 ...

  6. java学习笔记16--I/O流和文件

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note16.html,转载请注明源地址. IO(Input  Output)流 IO流用来处理 ...

  7. Java基础系列8——IO流超详细总结

    该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 在初学Java时,I ...

  8. Java学习日记之 Java-IO流

    Java中的IO流在处理上分为字节流和字符流.字节流和字符流的区别 : 1.字节流读取的时候,读到一个字节就返回一个字节:  字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8 ...

  9. Java 持久化操作之 --io流与序列化

    1)File类操作文件的属性 1.File类的常用方法 1. 文件的绝对完整路径:getAbsolutePath() 文件名:getName() 文件相对路径:getPath() 文件的上一级目录:g ...

  10. Java的递归、IO流

    .t1 { background-color: #ff8080; width: 1100px; height: 40px } 一.递归 [递归] 1. 在函数自身内部,调用函数本身的方式,称为递归. ...

随机推荐

  1. 【zigbee无线通信模块步步详解】ZigBee3.0模块建立远程网络控制方法

    本文以路灯控制应用为例,简述ZigBee3.0模块使用流程. 一.建立网络 1.通过USB转串口模块将出厂的ZigBee自组网模块连接,打开上位机软件"E180-ZG120A-Setting ...

  2. Python爬虫+数据可视化教学:分析猫咪交易数据

    猫猫这么可爱 不会有人不喜欢吧: 猫猫真的很可爱,和我女朋友一样可爱~你们可以和女朋友一起养一只可爱猫猫女朋友都有的吧?啊没有的话当我没说-咳咳网上的数据太多.太杂,而且我也不知道哪个网站的数据比较好 ...

  3. Docker部署jar包运行

    1.上传jar包到服务器 2.在该目录下创建Dockerfile 文件 vi Dockerfile 3.然后将下面的内容复制到Dockerfile文件中 FROM java:8 MAINTAINER ...

  4. 【MAUI】为 Label、Image 等控件添加点击事件

    一.前言 已经习惯了 WPF.WinForm 中"万物皆可点击"的方式. 但是在 MAUI 中却不行了. 在 MAUI 中,点击.双击的效果,是需要通过"手势识别器&qu ...

  5. 《吐血整理》保姆级系列教程-玩转Fiddler抓包教程(2)-初识Fiddler让你理性认识一下

    1.前言 今天的理性认识主要就是讲解和分享Fiddler的一些理论基础知识.其实这部分也没有什么,主要是给小伙伴或者童鞋们讲一些实际工作中的场景,然后隆重推出我们的猪脚(主角)-Fiddler. 1. ...

  6. 临近梯度下降算法(Proximal Gradient Method)的推导以及优势

    邻近梯度下降法 对于无约束凸优化问题,当目标函数可微时,可以采用梯度下降法求解:当目标函数不可微时,可以采用次梯度下降法求解:当目标函数中同时包含可微项与不可微项时,常采用邻近梯度下降法求解.上述三种 ...

  7. 选择结构-扩展if-else语句和练习用if语句实现考试成绩划分

    判断语句3--if..else if...else if语句第三种格式: if...else if ...else if (判断条件1) { 执行语句1; } else if (判断条件2) { 执行 ...

  8. Etcd 使用场景:通过分布式锁思路实现自动选主

    分布式锁?选主? 分布式锁可以保证当有多台实例同时竞争一把锁时,只有一个人会成功,其他的都是失败.诸如共享资源修改.幂等.频控等场景都可以通过分布式锁来实现. 还有一种场景,也可以通过分布式锁来实现, ...

  9. Chrome实现自动化测试:录制回放网页动作

    Chrome 浏览器是真的恐怖,它会把相关的小工具都卷死.从它诞生至今,创造了一个又一个的传奇,现在可以看到基于它的操作系统 chrome os ,还能买到用它做系统的笔记本电脑. 最近,新版本支持录 ...

  10. Git上传仓库

    上传代码到gitee 方法1 1. 将远程仓库克隆到本地 git clone https://gitee.com/abc/aaa.git 2. 添加或修改本地文件 3. 将本地代码push到远程仓库 ...