企业网站鉴赏,系统优化方法,公司商标设计图案logo,百度网址链接是多少目录
Java的IO流#xff08;二#xff09;
字节缓冲流
基本使用
使用缓冲流复制文件
字符缓冲流
缓冲流读取数据原理
字符编码
字符集
转换流
序列化流与反序列化流
基本使用
禁止成员被序列化
序列号不匹配异常
打印流
基本使用
系统打印流与改变流向
Prop…目录
Java的IO流二
字节缓冲流
基本使用
使用缓冲流复制文件
字符缓冲流
缓冲流读取数据原理
字符编码
字符集
转换流
序列化流与反序列化流
基本使用
禁止成员被序列化
序列号不匹配异常
打印流
基本使用
系统打印流与改变流向
Properties集合结合IO流
Commons-io工具包
介绍与引入工具包
使用工具包的静态方法
IOUtils工具类
FileUtils工具类
整章结构 Java的IO流二
字节缓冲流
基本使用
字节缓冲输入流对应BufferedInputStream类字节输出缓冲流对应BufferedOutputStream类各自常用的构造方法如下
BufferedOutputStream(OutputStream out)使用OutputStream对象进行构造BufferedInputStream(InputStream in)使用InputStream对象进行构造 BufferedOutputStream和 BufferedInputStream都是 OutPutStream和 InputStream的实现类 因为对应的字节流中的两个类 FileOutputStream类和 FileInputStream类也是 OutPutStream和 InputStream的实现类所以此处可以使用多态的向上转型将 FileOutputStream对象或者 FileInputStream对象给 OutputStream对象引用或者 InputStream对象引用从而构造 BufferedOutputStream对象和 BufferedInputStream对象 使用如下
public class Test {public static void main(String[] args) throws IOException {// 字节输出缓冲流BufferedOutputStream bufferedOutputStream new BufferedOutputStream(new FileOutputStream(./a.txt));// 字节输入缓冲流BufferedInputStream bufferedInputStream new BufferedInputStream(new FileInputStream(./a.txt));}
}
使用方法和方式与字节流一致基本使用如下
public class Test {public static void main(String[] args) throws IOException {BufferedOutputStream bufferedOutputStream new BufferedOutputStream(new FileOutputStream(./a.txt));bufferedOutputStream.write(98);bufferedOutputStream.flush();BufferedInputStream bufferedInputStream new BufferedInputStream(new FileInputStream(./a.txt));int word bufferedInputStream.read();System.out.println((char)word);bufferedInputStream.close();bufferedOutputStream.close();}
}
需要注意的是在关流时尽管创建缓冲流相关对象时使用到了基本流对象但是关流只需要关闭缓冲流相关对象因为缓冲流关闭流方法底层会先关闭基本流再关闭缓冲流 使用缓冲流复制文件
public class Test01 {public static void main(String[] args) throws IOException {// 创建字节输入缓冲流BufferedInputStream bufferedInputStream new BufferedInputStream(new FileInputStream(./1.mp3));// 创建字节输出缓冲流BufferedOutputStream bufferedOutputStream new BufferedOutputStream(new FileOutputStream(./1-copy.mp3));// 读取数据int len 0;byte[] bytes new byte[1024];while((len bufferedInputStream.read(bytes)) ! -1) {bufferedOutputStream.write(bytes, 0, len);}// 关流bufferedOutputStream.close();bufferedInputStream.close();}
}
字符缓冲流
字符缓冲输入流对应BufferedReader类字节输出缓冲流对应BufferedWriter类各自常用的构造方法如下
BufferedWriter(Writer w)使用OutputStream对象进行构造BufferedReader(Reader r)使用InputStream对象进行构造 BufferedWriter和 BufferedReader都是 Writer和 Reader的实现类 因为对应的字节流中的两个类 FileWriter类和 FileReader类也是 Writer和 Reader的实现类所以此处可以使用多态的向上转型将 FileWriter对象或者 FileReader对象给 Writer对象引用或者 Reader对象引用从而构造 BufferedWriter对象和 BufferedReader对象 基本使用与字节缓冲流基本一致不再演示
常用方法与基本流一致下面只关注BufferedWriter和BufferedReader的特有方法
BufferedWriter中的特有方法void newLine()作用换行效果BufferedReader中的特有方法String readLine()作用一次读取一行数据如果读到内容结尾则返回null
基本使用如下
public class Test02 {public static void main(String[] args) throws IOException {BufferedWriter bufferedWriter new BufferedWriter(new FileWriter(./b.txt));bufferedWriter.write(99);bufferedWriter.newLine();bufferedWriter.write(100);bufferedWriter.flush();BufferedReader bufferedReader new BufferedReader(new FileReader(./b.txt));String s bufferedReader.readLine();System.out.println(s);String s1 bufferedReader.readLine();System.out.println(s1);}
}
缓冲流读取数据原理
缓冲流之所以比基本流读取快本质原因就是缓冲流在内存中开辟的缓冲区。
在从硬盘读取数据过程中先使用基本流读取数据再将数据交给缓冲流读入到缓冲流对应的缓冲区因为缓冲区大小为8192字节所以每一次缓冲流从基本流读取数据到缓冲区直到读取到8192字节才会停止。
在从内存写数据到硬盘过程中因为输入缓冲区当前已经读取到了8192个字节的数据就需要一个载体将输入缓冲区中的数据输送到输出缓冲区同样输出缓冲区也是8192个字节的大小在没有调用flush方法或close方法情况下除非输出缓冲区满了内容会由输出缓冲流传输到基本流再由基本流输出到硬盘中否则内容会一直留在输出缓冲区
整个过程如下图 字符编码
计算机中储存的信息都是用二进制数表示的而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。[按照某种规则将字符存储到计算机中称为编码] 。反之将存储在计算机中的二进制数按照某种规则解析显示出来称为解码 。比如说按照A规则存储同样按照A规则解析那么就能显示正确的文本f符号。反之按照A规则存储再按照B规则解析就会导致乱码现象。 字符编码Character Encoding : 一套自然语言的字符与二进制数之间的对应规则。
字符集
字符集 Charset也叫编码表。是一个系统支持的所有字符的集合包括各国家文字、标点符号、图形符号、数字等。
计算机要准确的存储和识别各种字符集符号需要进行字符编码一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。 可见当指定了编码它所对应的字符集自然就指定了所以编码才是我们最终要关心的。
ASCII字符集 ASCIIAmerican Standard Code for Information Interchange美国信息交换标准代码是基于拉丁字母的一套电脑编码系统用于显示现代英语主要包括控制字符回车键、退格、换行键等和可显示字符英文大小写字符、阿拉伯数字和西文符号。基本的ASCII字符集使用7位bits表示一个字符共128字符。ASCII的扩展字符集使用8位bits表示一个字符共256字符方便支持欧洲常用字符。ISO-8859-1字符集 拉丁码表别名Latin-1用于显示欧洲使用的语言包括荷兰、丹麦、德语、意大利语、西班牙语等。ISO-8859-1使用单字节编码兼容ASCII编码。GBxxx字符集 GB就是国标的意思是为了显示中文而设计的一套字符集。GB2312简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时就表示一个汉字这样大约可以组合了包含7000多个简体汉字此外数学符号、罗马希腊的字母、日文的假名们都编进去了连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码这就是常说的全角字符而原来在127号以下的那些就叫半角字符了。GBK最常用的中文码表。是在GB2312标准基础上的扩展规范使用了双字节编码方案共收录了21003个汉字完全兼容GB2312标准同时支持繁体汉字以及日韩汉字等。GB18030最新的中文码表。收录汉字70244个采用多字节编码每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字同时支持繁体汉字以及日韩汉字等。Unicode字符集 Unicode编码系统为表达任意语言的任意字符而设计是业界的一种标准也称为统一码、标准万国码。它最多使用4个字节的数字来表达每个字母、符号或者文字。有三种编码方案UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。UTF-8编码可以用来表示Unicode标准中任何字符它是电子邮件、网页及其他存储或传送文字的应用中优先采用的编码。互联网工程工作小组IETF要求所有互联网协议都必须支持UTF-8编码。所以我们开发Web应用也要使用UTF-8编码。它使用一至四个字节为每个字符编码编码规则 128个US-ASCII字符只需一个字节编码。拉丁文等字符需要二个字节编码。大部分常用字含中文使用三个字节编码。其他极少使用的Unicode辅助字符使用四字节编码。
转换流
转换流主要解决的问题是读取文本文件和写入文本文件两个过程中的字符编码不同因为尽管是字符流读取字符也只能保证代码文件的编码和文本文件编码一致情况下的读取正常为了更广泛性得保证读取文本文件编码正常就可以使用转换流
转换流有两类
输入转换流对应InputStreamReader类输出转换流对应OutputStreamWriter类
对应的构造方法如下
InputStreamReader(InputStream in, String charsetName)通过InputStream对象构造第二个参数代表读取内容时解码采用的字符集OutputStreamWriter(OutputStream out, String charsetName)通过OutputStream对象构造第二个参数代表写入内容时采用的字符集
常用方法与字符流一致
基本使用如下
public class Test {public static void main(String[] args) throws IOException {OutputStreamWriter outputStreamWriter new OutputStreamWriter(new FileOutputStream(./a.txt), utf-8);outputStreamWriter.write(你好);outputStreamWriter.flush();InputStreamReader inputStreamReader new InputStreamReader(new FileInputStream(./a.txt), utf-8);char[] chars new char[2];int len 0;while ((len inputStreamReader.read(chars)) ! -1) {System.out.println(new String(chars, 0, len));}inputStreamReader.close();outputStreamWriter.close();}
}
序列化流与反序列化流
在Java中如果需要将对象的属性输出到文件中并且再读取到内存中就需要用到序列化流和反序列化流
序列化流对应的类为ObjectOutputStream反序列化流对应的类为ObjectInputStream
需要注意序列化流和反序列化流写入到文件中的数据并不是让人可以看懂的所以出现奇怪的字符都是正常的 基本使用
序列化流主要作用是向硬盘写对象构造方法ObjectOutputStream(OutputStream out)常用方法void writeObject(Object obj)
反序列化流主要作用是从硬盘读对象构造方法ObjectInputStream(InputStream in)常用方法Object readObject()返回读取到的对象
需要注意要写入类对象属性需要确保对象对应的类实现了Serializable接口否则会抛出NotSerializableException异常
// 自定义类
public class Person implements Serializable {private String name;private int age;public Person() {}public Person(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}Overridepublic String toString() {return Person{ name name \ , age age };}
}// 测试
public class Test {public static void main(String[] args) throws Exception {ObjectOutputStream objectOutputStream new ObjectOutputStream(new FileOutputStream(b.txt));// 写入一个ArrayListPersonArrayListPerson people new ArrayList();people.add(new Person(张三, 23));people.add(new Person(李四, 24));people.add(new Person(王五, 25));// 写入people列表objectOutputStream.writeObject(people);objectOutputStream.flush();// 读取people列表ObjectInputStream objectInputStream new ObjectInputStream(new FileInputStream(./b.txt));Object o objectInputStream.readObject();for (Person person : (ArrayListPerson) o) {System.out.println(person);}}
}输出结果
Person{name张三, age23}
Person{name李四, age24}
Person{name王五, age25}
禁止成员被序列化
如果不想指定的成员被序列化可以使用transient关键字修饰对应成员例如Person类中的age成员修饰为transient
// 自定义类
public class Person implements Serializable {private String name;private transient int age;// ...
}// 测试
public class Test {public static void main(String[] args) throws Exception {ObjectOutputStream objectOutputStream new ObjectOutputStream(new FileOutputStream(b.txt));// 写入一个ArrayListPersonArrayListPerson people new ArrayList();people.add(new Person(张三, 23));people.add(new Person(李四, 24));people.add(new Person(王五, 25));// 写入people列表objectOutputStream.writeObject(people);objectOutputStream.flush();// 读取people列表ObjectInputStream objectInputStream new ObjectInputStream(new FileInputStream(./b.txt));Object o objectInputStream.readObject();for (Person person : (ArrayListPerson) o) {System.out.println(person);}}
}输出结果
Person{name张三, age0}
Person{name李四, age0}
Person{name王五, age0}
序列号不匹配异常
序列号不匹配异常一般出现于向硬盘写入对象属性值时创建的序列号与从硬盘读取对象数值时的序列号不同而造成这种不同的原因一般是写入对象后修改了源码
如果不想出现上面的异常可以在对象对应的类中创建成员
public static final long serialVersionUID 指定具体值;
需要注意这个成员代表序列号必须是 long类型且被 final和 static修饰 打印流
基本使用
打印流表示向某一个文件输出内容
打印流对应类为PrintStream类构造方法PrintStream(String fileName)
常用方法有
println(...)向文件中输出参数内容并且自带换行print(...)向文件中输出参数内容不换行
基本使用如下
public class Test {public static void main(String[] args)throws Exception{PrintStream ps new PrintStream(./a.txt);ps.println(1);ps.println(2);ps.close();}
}
系统打印流与改变流向
前面经常使用System.out.println()输出数据实际上就是在使用打印流只是这个out成员是System类中的静态PrintStream类成员此时调用println方法默认向控制台打印数据
在实际开放中程序在运行过程中控制台的内容会被每一次新打印语句覆盖导致内容不具有持久性所以需要改变内容流向使其不打印在控制台而打印到文件中
当需要改变流向可以使用System类中的静态方法static void setOut(PrintStream out)该方法是静态方法所以可以被直接调用
基本使用如下
public class Test01 {public static void main(String[] args) throws Exception{System.setOut(new PrintStream(./b.txt));System.out.println(这是一个日志文件);System.out.println(现在是 new Date());}
}文件内容
这是一个日志文件
现在是Sun Sep 22 21:15:47 CST 2024
Properties集合结合IO流
前面介绍Properties集合时介绍到一个方法void load(InputStream inStream)该方法和结合InputStream对象使用
因为Properties集合一般存储的是配置文件信息所以可以考虑从文件中读取配置信息原因是将来不能将很多的硬数据放到源码中比如用户名和密码这些数据因为之后有可能换用户名或者密码如果一换我们就需要去源码中修改而因为类和类之间都有联系有可能牵一发动全身所以需要将这些数据提取出来放到文件中改的时候直接去文件中改源码不需要改动
配置文件xxx.properties创建方式
在需要创建配置文件的父文件夹右键 - File - 取名为xxx.properties在xxx.properties文件中写配置数据 key和value都是keyvalue形式key和value都是String的,但是不要加双引号每个键值对写完之后,需要换行再写下一对键值对之间最好不要有空格(空格可以有,但是不建议写)键值对中建议不要使用中文(中文可以有,但是直接读取会乱码,需要转换流转码)
基本使用如下
public class Test {public static void main(String[] args)throws Exception {Properties properties new Properties();FileInputStream fis new FileInputStream(jdbc.properties);properties.load(fis);SetString set properties.stringPropertyNames();for (String key : set) {System.out.println(key...properties.getProperty(key));}}
}
Commons-io工具包
介绍与引入工具包
Commons-io解决的问题IO技术开发中代码量很大而且代码的重复率较高。如果我们要遍历目录拷贝目录就需要使用方法的递归调用也增大了程序的复杂度。
Apache软件基金会开发了IO技术的工具类commons-IO大大简化IO开发。
Commons-io工具包是第三方包所以使用前需要导入包但是这个包是jar包需要先解压下面是IDEA下的引入和解压方式
在指定位置创建文件夹,取名为lib或者libs将准备好的jar包,放到此文件夹下对着jar包,右键 - Add as library (如果想将lib下所有的jar包一起解压,我们就直接对着lib文件夹右键)level可以选择module此时上面name位置会变成空可以不用考虑直接点OK
上面引包的方式后面会被Maven项目管理工具替代具体见后面Maven工具使用介绍 使用工具包的静态方法
IOUtils工具类
IOUtils工具类是Commons-io工具包下的关于IO的一个类里面提供了一些文件操作的方法
IOUtils.copy(InputStream in, OutputStream out)拷贝文件内容到另一个文件中IOUtils.closeQuietly(任意流对象)作用同close方法但是不需要额外处理异常
基本使用如下
public class Test {public static void main(String[] args) /*throws Exception*/{//- 静态方法IOUtils.copy(InputStream in,OutputStream out)IOUtils.copy(new FileInputStream(./1.jpg),new FileOutputStream(./1-copy.jpg));//- 静态方法IOUtils.closeQuietly(任意流对象)FileWriter fw null;try{fw new FileWriter(module22\\commons.txt);fw.write(你好);}catch (Exception e){e.printStackTrace();}finally {if (fw!null){IOUtils.closeQuietly(fw);}}}
}
FileUtils工具类
常用方法如下
FileUtils.copyDirectoryToDirectory(File src, File dest)将src下的文件夹拷贝到dest下的文件夹中整个过程中不需要对src内部的文件夹进行显式递归遍历writeStringToFile(File file, String str)向文件中写入str字符串内容String readFileToString(File file)读取文件中所有的内容
基本使用如下
public class Test01 {public static void main(String[] args)throws Exception {// FileUtils.copyDirectoryToDirectory(File src, File dest)FileUtils.copyDirectoryToDirectory(new File(./test), new File(./test1));//- 静态方法writeStringToFile(File file,String str)写字符串到文本文件中。FileUtils.writeStringToFile(new File(./a.txt),haha);//- 静态方法String readFileToString(File file)读取文本文件返回字符串。String s FileUtils.readFileToString(new File(./a.txt));System.out.println(s);}
}
整章结构