Java基础(八)
IO流
概述与分类
Java中的IO流技术主要用于传输数据.典型的应用场景有:读写本地文件,上传下载文件等.按照数据传输的方向可以分为两种:
l 输入流(Input):既让数据进入应用程序中.
l 输出流(Output):既让数据离开应用程序.
按照数据的种类还可以有另外一种分法:
l 字节流:可以处理任何一种数据.
l 字符流:只能处理纯文本数据.
现阶段我们主要学习:字符输入流,字符输出流,来实现读写文件的功能.
整理一下IO流的分类:
字节输入流
字节输出流
字符输入流: 读纯文本文件
字符输出流: 写纯文本文件
FileWriter写文件
一般步骤
使用java.io.FileWriter类可以将数据写到文本文档中,使用步骤为三步:
1. 调用构造方法来创建一个FileWriter对象:
public FileWrier(String filename);构造参数为文件路径名.
备注:创建对象时,如果文件不存在,则会自动创建该文件.
2. 调用写数据的成员方法向文件中写入数据:
public void write(String text);参数为需要写入的字符串.
3. 调用关闭的成员方法释放相关资源;
public void close();
三步走:”创,写,关”.
注意事项:
1. 千万不要忘记最后调用close方法进行关闭.
2. 创建的时候,如果提示有可能有异常,点击Add throws…即可.
覆盖与追加
在使用FileWriter的时候:
1. 如果指定的文件不存在,那么会自动创建该文件.
2. 如果指定的文件已经存在,那么将会覆盖写入.
3. 如果不希望进行覆盖写入,而是希望进行追加,那么要用另外一种重载形式的构造方法:
public FileWriter(String fileName,boolean append);第二个参数是true值,那么将会追加写入.
换行符
如何才能实现换行的效果?
换行其实也是一种字符,叫做”换行符”.
Windows当中的换行符是: \r\n 这叫做两个字符,一个是\r,一个是\n
macOS当中的换行符是:早期是 \r ,现在是 \n
Linux当中的换行符是:\n
数字与文字的转换
其实所有数据在计算机底层都是二进制数字,所以一切数据都是数字。文件当中存放的其实并不是文字图形,而是数字序列。之所以打开文件可以看到文字图形,是因为软件对文件当中的数字进行了“翻译”。而翻译就需要一个对照词典,如:ASCll码表或Unicode码表。
ASCll当中的字符种类比较少;而Unicode 包含了ASCll的内容,还扩展了数以万计的字符,可以涵盖全世界所有的文字。
FileWriter提供了一种重载形式的write方法,可以省去将文字翻译成为数字的步骤,直接在文件当中写对应的数字:
public void write(int ch):参数就是ASCll或Unicode表当中的数字,最小为0。
FileWriter的write方法重载
FileWriter当中写数据的方法write有5种重载形式:
public void write(int ch);参数是单个文字对应的数字(参考ASCII或者Unicode表)
public void write(String str);写一个完整的字符串.
public void write(String str,int offset,int count);写字符串当中的一部分内容.
public void write(char[] array);写一个完整的字符数组.
public void write(char[] array,int offset,int count);写字符数组当中的一部分内容.
FileReader读文件
一般步骤
使用java.io.FileReader类可以读取文本文件当中的字符(对应的ASClI或Unicode值)。
使用步骤为:
1.调用构造方法来创建一个FileReader对象:
public FileReader(String fileName):参数仍然为文件的路径名。!
备注:如果文件不存在,不会自动创建,而会发生异常。
2.调用读取数据的read方法获取单个字符:
public int read():返回值为单个字符对应的ASCll或Unicode值。
备注:每次调用都会读取下一个字符,如果没有更多,将返回-1值。
3.调用close方法关闭流:
public void close():释放相关资源。
由于并不确定文件当中包含多少个字符,所以次数不确定的重复代码,应该使用while循环。当得到-1值时退出循环。
读取单个字符
调用一次输出一个字符,直到关闭流
循环调用输出字符,直到关闭流
读取字符数组
如果读取字符是一个一个地,那么效率很低.
为了提高效率,FileReader提供了另外一种重载形式的read方法:
public int read(char[] buf);一次读取整个字符数组的数据.
参数是一个字符数组,用来承载读取到的多个字符.
返回值代表的是数组当中读取到的有效个数.
画图理解ol出现问题
解决以上的ol出现问题写法
为了减少硬编码,利用标准while循环写法
读写数据的过程
BufferedWriter的缓冲原理
BufferedWriter和FileWriter差不多,也是一种用来写文件的类,属于字符输出流。
区别在于BufferedWriter肚子里有一个长度为8192的char[]字符数组,当作缓冲区使用。
每次在写数据的时候,实际上都是在不断地向缓冲数组当中添加字符。
如果缓冲数组已经满了,那么将会统一地写到硬盘的文件当中。
如果还没有写满,那么就等待下一次写入。
如果最终关闭流的时候,数组仍然没满,那么也会将剩余的有效部分写到硬盘文件里。
基本使用
如何使用BufferedWriter?
- 首先创建一个普通的FileWriter
- 将这个普通的FileWriter包装成为缓冲的BufferedWriter,用构造方法.
- 后面BufferedWriter使用的方法和FileWriter基本一样.
构造方法: public BufferedWriter(FileWriter fw); 参数就是一个普通的FileWriter对象.
newLine方法
BufferedWriter额外提供了一个换行的方法.
public void newline();将会自动根据操作系统的不同,选择写入\r\n或者是\r或者是\n.
BufferedReader的缓冲原理
BufferedReader和FileReader差不多,也是用来读取文件的一种字符输入流。
区别就在于BufferedReader肚子里也有一个8192长度的char[]字符数组,当做缓冲区使用。
当读取数据的时候,一次性从硬盘当中读职最多8192个字符,放在数组缓冲区当中。
在调用read方法的时候,只是从缓冲区当中拿出来字符进行使用。
如果缓冲区当中的字符被“取空”,那么将会自动再次读取最多8192个再次放在缓冲区当中。
基本使用
如何使用BufferedReader?
- 首先创建一个普通的FileReader
- 将这个普通的FileReader包装成为缓冲的BufferedReader,构造方法.
- 使用起来和普通的FileReader基本没有区别.
构造方法: public BurreredReader(FileReader fr); 参数就是一个普通的FileReader对象.
readLine方法
BufferedReader额外提供了一个方法,可以读取一整行字符串.
Public String readLine();读取一整行字符串,返回值当中不包含换行符.
while循环节省代码量
练习
将集合的字符串写到文件中
题目:
定义一个集合用于存储多个字符串,向其中添加一些字符串,然后将集合的所有字符串内容写到文件中.要求每个字符串独占一行.
步骤:
1.定义一个集合,那就是创建ArrayList
2.用来存储多个字符串,那么泛型就是<String>
3.添加字符串到集合当中,就是调用方法:add
4.既然需要写文件那么就用:FileWriter、BufferedWriter。
5.谁的性能更高:Buffereduriter
6.集合当中的每一个字符串都需要逐一处理:for循环遍历集合
7.在循环当中将字符串写到文件里:调用write方法
8.要求字符串独占一行,所以调用:newline方法
9.最后不要忘记关闭流。
将文件中的字符串读到集合中
题目:
与上一题相反,将文件中的字符串文本读取到集合当中,并且每一行文本作为集合中的一个字符串元素.
步骤:
1.需要读文件,那么可以使用:FileReader、BufferedReader
2.为了性能更高,最好用谁:BufferedReader(只有BufferedReader才有)
3.需要有一个集合来存放读取出来的字符串:ArrayList<String>
4.读取一行:readLine
5.将读到的字符串添加到集合当中:add
6.上述4-5步骤是一个循环的过程,读取得到null就要停止。
7.关闭流。
8.遍历集合,查看所有字符串元素的内容。
反转藏头情诗
1 世界上怎么会有你这种人
2 一点也不知道温柔体贴
3 生气的时候凶得像条狗
4 一天到晚就知道瞎BB
5 你以为你是谁呀
6 爱咋地咋地
7 我特么就这样
分析:
1.肯定需要读取文件,所以创建一个BufferedReader。
2.定义一个集合,用来存放所有的句子:ArrayList<String>
3.添加需要add,读取一行需要readLine
4.要将结果写到另一个文件当中,另外创建一个BufferedWriter
5.倒序遍历集合。for循环,但是i不是从0开始,而是从.size()-1开始。
6.在倒序遍历集合的时候,当前字符串写到文件中:write
7.不要忘记换行:newLine
8.关闭流
方法的参数类型解析
方法的参数可以是什么类型?
- 基本类型
- 数组
- 字符串
- 自定义的类
结论:所有数据类型都可以作为方法的参数类型.
Test测试类
public class Test {
public static void mian(String[] args) {
method1(100);
System.out.println("===================="); int[] arr = {10,20,30};
method2(arr);
System.out.println("===================="); method3("How do you do?");
System.out.println("===================="); Student stu = new Student("赵丽颖",20);
method4(stu);
} //使用基本类型作为方法的参数,可以
public static void method1(int num) {
num += 20;
System.out.println(num); //
} //使用数组作为方法的参数,也可以
public static void method2(int[] array) {
System.out.println(array[0]); //
System.out.println(array[1]); //
System.out.println(array[2]); //
} //使用字符串作为方法的参数,还可以
public static void method3(String str) {
String result = str.replace("o","*");
System.out.println(result); //H*w d* y*u d*?
} //使用自定义的类作为方法的参数,照样可以
public static void method4(Student stu) {
//姓名:赵丽颖,年龄:20
System.out.println("姓名: " +stu.getName()+ ",年龄:" +stu.getAge());
}
}
Student类
public class Student { private int age; private String name; //无参构造 public Student() { } //有参构造 public Student(String name, int age) { this.name = name; this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
方法的返回值类型解析
方法的返回值可以是什么类型?
- 基本类型
- 数组
- 字符串
- 自定义的类
结论:所有数据类型都可以作为方法的返回值类型.
测试类:
public class Test { public static void main(String[] args) { int result = method1(); System.out.println(result); // System.out.println("======================="); int[] result2 = method2(); System.out.println(result2[0]); // System.out.println(result2[1]); // System.out.println("======================="); String result3 = method3(); System.out.println(result3.replace("0", "*")); //H*w d* y*u d*? System.out.println("======================="); Student result4 = method4(); System.out.println("姓名:" +result4.getName() + ",年龄:" + result4.getAge()); } //使用基本类型作为方法的返回值,可以 public static int method1() { int num = 100; return num; } //使用数组类型作为方法的返回值,也可以 public static int[] method2() { int[] array = {10,20}; return array; } //使用字符串作为方法的返回值,可以 public static String method3() { String str ="How do you do?"; return str; } //使用自定义的类作为方法的返回值,仍然可以 public static Student method4() { Student stu = new Student("赵丽颖",20); return stu; } }
Student类
public class Student { private int age; private String name; //无参构造 public Student() { } //有参构造 public Student(String name, int age) { this.name = name; this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
知识总结
Java基础(八)的更多相关文章
- Java基础八--构造函数
Java基础八--构造函数 一.子父类中构造函数的特点 1.1 为什么在子类构造对象时,发现,访问子类构造函数时,父类也运行了呢? 原因是:在子类的构造函数中第一行有一个默认的隐式语句. super( ...
- Java基础(八)--String(源码)、StringBuffer、StringBuilder
String源码:基于jdk1.8 public final class String implements Serializable, Comparable<String>, CharS ...
- java基础八 [序列化和文件的输入/输出](阅读Head First Java记录)
对象具有状态和行为两种属性.行为存在类中的方法中,想要保存状态有多种方法,这里介绍两种: 一是保存整个当前对象本身(通过序列化):一是将对象中各个状态值保存到文件中(这种方式可以给其他非JAVA程序用 ...
- 重学JAVA基础(八):锁的基本知识
1.线程状态 如上图,当我们新建一个线程,并start后,其实不一定会马上执行,因为只有操作系统调度了我们的线程,才能真正进行执行,而操作系统也随时可以运行其他线程,这时线程又回到可运行状态.这个过程 ...
- java基础(八)-----深入解析java四种访问权限
Java中的访问权限理解起来不难,但完全掌握却不容易,特别是4种访问权限并不是任何时候都可以使用.下面整理一下,在什么情况下,有哪些访问权限可以允许选择. 一.访问权限简介 访问权限控制: 指的是本类 ...
- 《温故而知新》JAVA基础八
集合接口与泛型 定义: 集合接口会操作一系列相同属性数据的对象类型的数据结构,类似于数组,但是相对于数组来说更显得高端大气 集合的接口分为Collention和Map两大类,不直接操作,而是通过子类的 ...
- java基础(八) 深入解析常量池与装拆箱机制
引言 本文将介绍常量池 与 装箱拆箱机制,之所以将两者合在一起介绍,是因为网上不少文章在谈到常量池时,将包装类的缓存机制,java常量池,不加区别地混在一起讨论,更有甚者完全将这两者视为一个整体, ...
- java基础(八)之函数的复写/重写(override)
复写的意思就是子类对父类的修改. 复写的条件: 1.在具有父子类关系的两个类当中:2.父类和子类各有一个函数,这两个函数的定义保持一致(返回值类型.函数名.参数列表) 还是老样子,3个文件来说明. P ...
- java基础知识文章汇总
将之前的所有关于Java基础知识的随笔,整理成质量较高的十几篇随笔,几乎是好几篇比较零散的随笔合成现在的一篇,自认为还不错. java基础(一) 深入解析基本类型 java基础(二) 自增自减与贪心规 ...
随机推荐
- BZOJ 3073: [Pa2011]Journeys Dijkstra+线段树优化建图
复习一下线段树优化建图:1.两颗线段树的叶子节点的编号是公用的. 2.每次连边是要建两个虚拟节点 $p1,p2$ 并在 $p1,p2$ 之间连边. #include <bits/stdc++.h ...
- C++回调函数、静态函数、成员函数踩过的坑。
C++回调函数.静态函数.成员函数踩过的坑. 明确一点即回调函数需要是静态函数.原因: 普通的C++成员函数都隐含了一个this指针作为参数,这样使得回调函数的参数和成员函数参数个数不匹配. 若不想使 ...
- JavaWeb-SpringSecurity使用短信验证码登陆
相关博文 JavaWeb-SpringBoot_一个类实现腾讯云SDK发送短信 传送门 系列博文 项目已上传至guthub 传送门 JavaWeb-SpringSecurity初认识 传送门 Java ...
- docker的数据管理
容器中管理数据主要有两种方式: 1.数据卷:容器内数据直接映射到本地宿主机. 2.数据卷容器:使用特定容器维护数据卷 数据卷: 数据卷是一个可供容器使用的特殊目录,他将主机操作系统目录直接映射进容器. ...
- C++入门经典-类成员的可访问性,继承后的可访问性
1:关键字public.private.protected说明类成员是共有的.私有的,还是保护的.这3个关键字将类划分为3个区域,在public区域的类成员可以在类作用域外被访问,而private区域 ...
- VMware NAT模式设置静态IP(可上网)
在搞电商架构的高并发高可用时,需要在VMware新建几个linux虚拟机,如果使用VMware的默认网络是自动获取的,但有时候启动虚拟机IP地址会改变,使用很不方便,所以就整理一份静态IP地址设置的方 ...
- HearthBuddy Plugin编写遇到的问题
错误1 赋值问题 貌似编译器版本有点低,无法识别C#的高级语法糖 属性的初始值,必须是public bool IsEnabled { get{return true;} } 不能写成public bo ...
- Python中函数的使用
函数让代码的编写,阅读,测试和修改都变得更容易,提高代码的复用性,python中使用def关键字定义函数 如下代码在python3.7.3的Genay开发工具中编写测试通过. 一.简单函数定义及调用 ...
- Mybaits和Spring的那点事
前言 在spring中使用mybaits简直不要太简单,只需要几个配置,一个DAO接口和一个mapper.xml就可以完成一次数据库交互.但是简单背后往往是复杂的实现,现在我们来探讨一下里面的一点原理 ...
- 阶段3 3.SpringMVC·_02.参数绑定及自定义类型转换_7 获取Servlet原生的API
控制器里面获取常用的request对象或者Response对象. 想拿到谁, 就在参数上写上谁 再获取servletConetext并输出