IO流
java.io包下的内容,进行输入和输出的操作。
- 输出:写入数据。
- 输入:读取数据。
输入流:把数据从其他设备上读取到内存中的流。
输入流:把数据从内存中写入到其他设备的流。
- 字节流:以字节为单位,读写数据的流。
- 字符流:以字符为单位,读写数据的流。
流:数据(字符、字节)。
- 1个字符=2个字节。
- 1个字节=8个二进制位。
数据存储以“字节”为单位(byte),数据传输以“位”(bit)为单位,一个位代表一个0或1.每8个位(bit)组成一个字节(byte)。1kib=1024byte。
输入流 | 输出流 | |
字节流 | InputSteam | OutputSteam |
字符流 | Reader | Writer |
一切皆为字节:
一切文件数据(文本图片,视频等)在存储时,都是二进制数字的形式,保存的。都是一个个的字节,那么在传输时一样如此。所以字节流可以传输任意文件数据。无论使用什么样的流对象,底层传输的都是二进制的数据。
java.io.OutputSteam:字节输出流
此抽象类是表示输出字节流的所有类的超类。
成员方法:
- public void close():关闭此输出流,并释放与此流相关联的任何系统资源。
- public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。
- public void write(byte[] b):将b.length字节从指定的字节数组写入输出流。
- public void write (byte[] b,int off,int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。
- public abstract void write(int b):将指定的字节流输出流。
Tips:close方法,当完成流的操作时,必须调用此方法,释放系统资源。
-
java.IO.FileOutputSteam extends OutputSteam
FileOutputSteam:文件字节输出流。
- 作用:把内存中的数据写到硬盘的文件中。
构造方法:
- FileOutputSteam(String name):创建一个向具有指定名称的文件中写入数据的,输出文件流。
- FileOutputStream(File file):创建一个向指定File对象表示的文件中写入数据的一个,文件输出流。
参数:写入数据的目的
String name:目的地是一个文件的路径。
File file:目的地是一个文件。
构造方法的作用:
- 创建一个FileOutputSteam对象。
- 会根据构造方法中传递的文件/文件路径,创建一个空的文件。
- 会把FileOutputSteam对象指向创建好的文件。
写入参数的原理:(内存——>硬盘)
java程序——>JVM——>OS——>OS调用写数据的方法——>把数据写入文件中。
字节输出流的使用步骤:
- 创建一个FileOutputSteam对象,构造方法中传入写入数据的目的地。
- 调用一个FIileOutputStream对象的write方法,把数据写入文件中。
- 释放资源。(流会占用一定的内存,使用完毕后要被内存清空,提高程序的效率)。
文件存储和记事本打开的原理:
常用方法:
- public void write (byte[] b):将b.length字节从指定的字节数组中写入此输出流。
一次写多个字节:
如果第一个写的字节是正整数(0-127),那么显示的时候回查询ASCII表;
如果第一个写的是负数,那第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认GBK。 - public void (byte[] b,int off,int len):int off:数组的开始索引;int len:写几个字节。
- 可以使用String类中的方法把字符串转换成数组。byte[] getBytes()
追加和续写:
使用两个参数的构造方法。
- FileOutputStream(String name,boolean append)
- FileOutputStream(File file,boolean append)
参数:
- String name ;File file :写入数据的目的地。
- boolean append :追加写开关。
ture:创建对象不会覆盖源文件,继续在文件的末尾追加写数据。
false:创建一个新的文件,覆盖源文件。
换行: windows:\r\n;
linux:/n;
mac:/r;
java.io.InputStream:字节输入流
此抽象类是表示字节输入流的所有累的超类。
定义了所有子类共性方法:
- int read():从输入流中读取数据的下一个字节。
- int read(byte[] b):从输入流中读取一定的字节,并将其存储在缓冲区中。
- void close():关闭此输入流并释放该流相关的所所有系统资源。
java.io.FileInputStream extends InputStream
作用:把硬盘中的文件数据,读取到内存中使用。
构造方法:
- FileInputStream(String name)
- FileInputSteam(File file)
作用:
- 会创建一个FileInputStream的对象。
- 会把FileInputStream对象指定的构造方法中读取文件。
读取数据的原理(硬盘—>内存)
java程序—>JVM—>OS—>OS读取数据的方法—>读取文件
字节输入流的使用步骤:
- 创建FileInputStream对象,构造方法中要指定要读取的数据源。
- 使用read方法,读取文件。
- 释放资源。
读取文件是一个循环重复的过程,可以使用循环优化。因为不知道文件有多少个字节,采用while循环,循环结束条件,读取到-1时结束。
布尔表达式:(len=fis.read()!=-1);
- fis.read():读取一个字节。
- len=fis.read():把读取到的字节赋值被变量len。
- (len=fis.read()!=-1):判断变量len的值是否为-1;
eg:
int len=0;
while((len=fis.read())!=-1){
System.out.println((char)len)
}
字节流读取文件的原理:
字节输入流一次读取多个字节的方法:(int byte[] b)
- byte[]:起到缓冲作用,存储每次读取到的多个字节。
数组的长度一般定义为1024(1kb)或1024的整数倍。 - int:每次读取的有效字节数
String类构造方法:
String(byte[] bytes):把字节数组转成字符串。
String(byte[] byte,int offset,int length):把字节数组的部分转成字符串;int offset:数组开始的索引;int length:转换的字节个数。 - 读取文件循环代码:
byte[] byte=new byte[1024];
int len=0;
while((len=fis.read(bytes))!=-1){
System.out.prinln(new String(bytes));
}
Tips:使用数组读取,每次读取多个字节,减少了系统间的IO操作次数,从而提高了读写的效率,建议开发中使
用
案例:文件复制
public class Copy {
public static void main(String[] args) throws IOException {
// 1.创建流对象
// 1.1 指定数据源
FileInputStream fis = new FileInputStream("D:\\test.jpg");
// 1.2 指定目的地
FileOutputStream fos = new FileOutputStream("test_copy.jpg");
// 2.读写数据
// 2.1 定义数组
byte[] b = new byte[1024];
// 2.2 定义长度
int len;
// 2.3 循环读取
while ((len = fis.read(b))!=‐1) {
// 2.4 写出数据
fos.write(b, 0 , len);
}
// 3.关闭资源
fos.close();
fis.close();
}
}
Tips:流的关闭原则:先开后关,后开先关。
-
字符流
当使用字节流读取文件时,可能会有一个小小的问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供了一些字符流类,以字符为单位读写数据,专门用于处理文本文件。
使用字节流读取文件:
中文: GBK:占用2个字节。
UTF-8:占用了3个字节。
java.io.Reader
字符输入流,是字符输入流中最顶层的父类,定义了一些共性的成员方法,是一个抽象类。
- int read():读取单个字符串并返回。
- int read(char[] char):一次读取多个字符,将字符存入数组中。
- void close():关闭流并释放与之相关的所有的资源。
Java.io.FileReader extends InputStreamReader extends Reader
-
FileReader:文件字符输入流
作用:把硬盘中的文件义字符的形式读取到内存中。
构造方法:
- FileReader(String filename)
- FileReader(File file)
作用:
- 创建一个FileReader对象
- 会把FileReader对象指向要读取的文件。
java.io.Writer
字符输出流,是所有字符出输出流的最顶层的父类,是一个抽象类。
成员方法:
- void write (int c):写入单个字符
- void write (char[] cbuf):写入字符数组
- abstract void write (char[] cbuf,int off,int len):写入字符串数组的某一部分,int off开始索引,int len是写入个数。
- void write(String str):写入字符串。
- void write(String str, int off,int len):写入字符串的某一部分,off是开始序列,len是写入个数。
- void flush():刷新该流的缓冲。
- void close():关闭此流,但是先要刷新。
java.io.FileWrite extends OutputStreamWrite extends writer
-
Filewrite
文件字符输出流,把内存中的字符数据写入到文件中。
构造方法:
- FileWrite (File file):根据给定的FIie对象构造一个FileWriter对象。
- FileWrite(String filename):根据给定的文件名构造对象。
参数:写入数据的目的地。
String filenam:文件的路径。
File file:是一个文件。
构造方法的作用:
- 创建一个FileWriter对象。
- 根据构造方法中传递的文件/文件路径,创建文件。
- 会把FileWriter对象指向建好的文件。
字符输出流使用步骤:
- 创建FileWriter对象,构造方法中绑定要写入数据的目的地。
- 使用Write方法,将数据写入到内存缓冲区中(字符转换为字节的过程)。
- 使用flush方法,把缓冲区中的数据,刷新到文件中。
- 释放资源(会先把内存缓冲区中的数据刷新到文件中)。
flush和close的区别:
- flush:刷新缓冲区,流对象可以继续使用。
- close:先刷新缓冲区,然后通知系统释放资源,流对象不可以再被使用了。
续写与换行
- FileWriter(String filename,boolean append)
- FileWriter(File file,boolean append)
参数:String name ,File file:写入目的地。
boolean append:ture—>不会创建新文件,覆盖源文件,可以读写
false—>创建新的文件,覆盖源文件。
换行:windows:\r\n
linux:/n
mac:/r
java.util.Properties集合 extends Hashtable<k,v> implents Map<k,v>
-
Properties集合
java.util.Properties 继承于Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其
对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时, System.getProperties 方法就是返回
一个Properties 对象。
properties集合表示了一个持久化的属性集。Properties可保存在流中或从流中加载。
Properties是唯一一个和IO流相结合的集合。
- 可以使用Properties集合中的方法store,把集合中的临时数据持久化写入硬盘中存储。
- 可以使用load方法,把硬盘中保存的文件(键值对)读取到集合中使用。
属性列表中的每个键及其对应的值都是一个字符串
Properties集合是一个双列集合,key和value默认都是字符串。
使用Properties集合存储数据,遍历取出Properties集合中的数据
构造方法:
- public Properties() :创建一个空的属性列表。
集合特有方法:
- Object setProperties(String key,String value):调用Hashtable的方法put。
- String getProperties(String key):通过key找到value的值,此方法相当于Map集合中的get(key)方法。
- Set<string> stringPropertingName():返回此属性列表中的键集,对应的值应是字符串,相当于Map集合中的keyset()方法。
可以使用propretise集合中方法store,把集合中的临时数据,持久化写到硬盘中存储。
案例:
public class ProDemo {
public static void main(String[] args) throws FileNotFoundException {
// 创建属性集对象
Properties properties = new Properties();
// 添加键值对元素
properties.setProperty("filename", "a.txt");
properties.setProperty("length", "209385038");
properties.setProperty("location", "D:\\a.txt");
// 打印属性集对象
System.out.println(properties);
// 通过键,获取属性值
System.out.println(properties.getProperty("filename"));
System.out.println(properties.getProperty("length"));
System.out.println(properties.getProperty("location"));
// 遍历属性集,获取所有键的集合
Set<String> strings = properties.stringPropertyNames();
// 打印键值对
for (String key : strings ) {
System.out.println(key+" ‐‐ "+properties.getProperty(key));
}
}
}
输出结果:
输出结果:
{filename=a.txt, length=209385038, location=D:\a.txt}
a.txt
209385038
D:\a.txt
filename ‐‐ a.txt
length ‐‐ 209385038
location ‐‐ D:\a.txt}
}
}
与流相关的方法
- public void load(InputStream inStream) : 从字节输入流中读取键值对。
参数中使用了字节输入流,通过流对象,可以关联到某文件上,这样就能够加载文本中的数据了。文本数据格式:
filename=a.txt
length=209385038
location=D:\a.txt
加载代码演示:
public class ProDemo2 {
public static void main(String[] args) throws FileNotFoundException {
// 创建属性集对象
Properties pro = new Properties();
// 加载文本中信息到属性集
pro.load(new FileInputStream("read.txt"));
// 遍历集合并打印
Set<String> strings = pro.stringPropertyNames();
for (String key : strings ) {
System.out.println(key+" ‐‐ "+pro.getProperty(key));
}
}
}
输出结果:
filename ‐‐ a.txt
length ‐‐ 209385038
location ‐‐ D:\a.txt
TIps:文本中的数据,必须是键值对的形式,可以使用空格、等号、冒号等符号分隔。