文章目录
- 字节流、字符流、属性集
- 一、字节流
- 1. 字节输出流和文件字节输出流
- 2. 字节输出流写入数据到文件
- 3. 文件存储原理与记事本打开文件的原理
- 4. 字节输出流写多个字节的方法
- 5. 字节输出流的续写和换行
- 6. 字节输入流和文件字节输入流
- 7. 字节输入流读取字节数据
- 8. 字节输入流一次读取多个字节
- 9. 练习:文件复制
- 二、字符流
- 1. 使用字节流读取中文的问题
- 2. 字符输入流、文件字符输入流
- 3. 字符输入流读取字符数据
- 4. 字符输出流和文件字符输出流
- 5. 字符输出流将单个字符写入文件
- 6. flush方法和close方法的区别
- 7. 字符输出流写数据的其他方法
- 8. 字符输出流的续写和换行
- 9. JDK7 和 JDK9 流中异常的处理
- 三、属性集
字节流、字符流、属性集
一、字节流
1. 字节输出流和文件字节输出流
-
java.io.OutputStream:字节输出流- 此抽象类是表示输出字节流的所有类的超类。
- 一些子类共性的成员方法:
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):将指定的字节输出流。
-
java.io.FileOutputStream extends OutputStream-
FileOutputStream:文件字节输出流。 -
作用:把内存中的数据写入到硬盘的文件中。
-
构造方法:
FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据到输出文件流。FileOutputStream(File file):创建一个向指定File对象表示的文件中写入数据的文件输出流。- 参数:
String name:一个文件的路径。File file:一个文件。
-
构造方法的作用:
- 创建一个
FileOutputStream对象。 - 会根据构造方法中传递的文件/文件路径,创建一个空的文件。
- 会把
FileOutputStream对象指向创建好的文件。
- 创建一个
-
2. 字节输出流写入数据到文件
- 写入数据的原理(内存 —> 硬盘):
java程序 —>JVM—>OS—>OS调用写数据的方法 —> 把数据写入到文件中
- 字节输出流的使用步骤:
- 创建一个
FileOutputStream对象,构造方法中传递写入数据的目的地。 - 调用
FileOutputStream对象中的方法write,把数据写入到文件中。 - 释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序的效率)。
- 创建一个
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("/Users/zgl/Desktop/a.txt");
fos.write(97);
fos.close();
}
}
3. 文件存储原理与记事本打开文件的原理
-
写数据的时候,会将10进制的整数转换为2进制输入存入硬盘。
-
任意的文本编辑器在打开文件的时候,把字节转换为字符表示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rAnVj6do-1589461317122)(https://raw.githubusercontent.com/zhugulii/picBed/master/02_%E6%96%87%E4%BB%B6%E5%AD%98%E5%82%A8%E7%9A%84%E5%8E%9F%E7%90%86%E5%92%8C%E8%AE%B0%E4%BA%8B%E6%9C%AC%E6%89%93%E5%BC%80%E6%96%87%E4%BB%B6%E7%9A%84%E5%8E%9F%E7%90%86.bmp)]
4. 字节输出流写多个字节的方法
public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流。- 如果写的第一个字节是正数(0~127),那么显示的时候会查询ASCII表。
- 如果写的第一个字节是负数,那么第一个字节会和第二个字节组成一个中文显示,查询系统默认码表(GBK)。
public void write(byte[] b, int off, int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。int off:数组的开始索引。int len:写入len个字节。
- 写入字符的方法:可以使用
String类中的方法把字符串转换为字节数组。byte[] getBytes():把字符转换为字节数组。
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream(new File("/Users/zgl/Desktop/b.txt"));
byte[] bytes1 = {97,98,99};
byte[] bytes2 = {-97,98,-99};
byte[] bytes3 = "你好".getBytes();
fos.write(bytes1);
fos.write(bytes2);
fos.write(bytes3);
fos.write(bytes1,1,1);
fos.close();
}
}
5. 字节输出流的续写和换行
-
追加写/续写:使用两个参数的构造方法。
FileOutputStream(String name, boolean append):创建一个向具有指定name的文件写入数据的输出文件流。FileOutputStream(File file, boolean append):创建一个向具有指定file的文件写入数据的输出文件流。- 参数:
String name、File name:写入数据的目的地。boolean append:追加写开关。true:创建对象不会覆盖源文件,继续在文件的末尾追加写数据。false:创建一个新文件,覆盖源文件。
- 参数:
import java.io.FileOutputStream; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("/Users/zgl/Desktop/a.txt",true); for (int i = 0; i < 5; i++) { fos.write("你好".getBytes()); } fos.close(); } } -
写换行:写换行符号
- win:
\r\n - Linux:
\n - Mac:
\r
import java.io.FileOutputStream; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("/Users/zgl/Desktop/a.txt",true); for (int i = 0; i < 5; i++) { fos.write("你好".getBytes()); fos.write("\r".getBytes()); } fos.close(); } } - win:
6. 字节输入流和文件字节输入流
java.io.InputStream:字节输入流。此抽象类是表示字节输入流的所有类的超类。- 一些子类共性的方法:
int read():从输入流中读取数据的下一个字节并返回,读取到文件的末尾返回-1。int read(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区的数组b中。void close():关闭此输入流并释放与该流关联的所有系统资源。
- 一些子类共性的方法:
java.io.FileInputStream extends InputStreamFileInputStream:文件字节输入流- 作用:把硬盘中的数据,读取到内存中使用。
- 构造方法:
FileInputStream(String name)FileInputStream(File file)- 参数:读取文件的数据源
String name:文件的路径File file:文件
- 构造方法的作用:
- 会创建一个
FileInputStream对象。 - 会把
FileInputStream对象指向构造方法中要读取的文件。
- 会创建一个
7. 字节输入流读取字节数据
- 读取数据的原理(硬盘 —> 内存):
java程序 —>JVM—>OS—>OS读取数据的方法 —> 读取文件
- 字节输入流的使用步骤:
- 创建
FileInputStream对象,构造方法中绑定要读取的数据源。 - 使用
FileInputStream对象中的方法read,读取文件。 - 释放资源。
- 创建
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("/Users/zgl/Desktop/a.txt");
int tmp;
while ((tmp = fis.read()) != -1) {
System.out.print((char) tmp); // abc
}
fis.close();
}
}
8. 字节输入流一次读取多个字节
int read(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区的数组b中。- 参数
byte[] b,起到缓冲作用,存储每次读取到的多个字节。 - 数组的长度一般定义为1024(1KB)或者1024的整数倍。
- 返回值为每次读取到的有效字节个数。
- 参数
String类的构造方法:String(byte[] bytes):把字节数组转换为字符串。String(byte[] bytes, int offset, int length):把字节数组的一部分转换为字符串,offset为数组的开始索引,length:转换的字节个数。
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("/Users/zgl/Desktop/a.txt");
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1) {
System.out.println(new String(bytes,0,len)); // abcdefgh
}
fis.close();
}
}
9. 练习:文件复制
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
long s = System.currentTimeMillis();
FileInputStream fis = new FileInputStream("/Users/zgl/Desktop/a.txt");
FileOutputStream fos = new FileOutputStream("/Users/zgl/Desktop/b.txt");
int len = 0;
byte[] bytes = new byte[1024];
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes,0,len);
}
fis.close();
fos.close();
long e = System.currentTimeMillis();
System.out.println("复制文件共用时:" + (e-s) + "毫秒!");
}
}
二、字符流
1. 使用字节流读取中文的问题
- 可能会出现乱码问题。
- 1个中文字符:
GBK:占用两个字节。UTF-8:占用三个字节。
2. 字符输入流、文件字符输入流
java.io.Reader:字符输入流,是字符输入流的最顶层的父类,定义了一些共性的成员方法,是一个抽象类。- 共性的成员方法:
int read():读取单个字符并返回。int read(char[] cbuf):一次读取多个字符,将字符读入数组。void close():关闭该流并释放与之关联的所有资源。
java.io.FileReader extends InputStream extends ReaderFileReader:文件字符输入流。- 作用:把硬盘文件中的数据以字符的方式读取到内存中。
- 构造方法:
FileReader(String fileName)FileReader(File file)- 参数:
String filename:文件的路径File file:文件
FileReader:构造方法的作用:- 创建一个
FileReader对象。 - 会把
FileReader对象指向要读取的文件。
- 创建一个
3. 字符输入流读取字符数据
- 使用步骤:
- 创建
FileReader对象,构造方法中绑定要读物的数据源。 - 使用
FileReader对象中的方法read读取文件。 - 释放资源。
- 创建
String类的构造方法:String(char[] value):把字符数组转换为字符串。String(char[] value, int offset, int count):把字符数组的一部分转换为字符串,offset为数组的开始索引,length:转换的符节个数。
import java.io.FileReader;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("/Users/zgl/Desktop/a.txt");
//使用read()
/*int tmp1;
while ((tmp1 = fr.read()) != -1) {
System.out.print((char)tmp1); // 你好,朱古力!
}*/
//使用read(char[] chars)
int len;
char[] chars = new char[1024];
while ((len = fr.read(chars)) != -1) {
System.out.println(new String(chars,0,len)); // 你好,朱古力!
}
fr.close();
}
}
4. 字符输出流和文件字符输出流
java.io.Writer:字符输出流,是所有字符输出流的最顶层的父类,是一个抽象类。- 共性的成员方法:
void write(int c):写入单个字符。void write(char[] cbuf):写入字符数组。void write(char[] cbuf, int off, int len):写入字符数组的某一部分,off为数组的开始索引,len为写的字符个数。void write(String str):写入字符串。void write(String str, int off, int len):写入字符串的某一部分,off为字符串的开始索引,len为写的字符个数。void flush():刷新该流的缓冲。void close():关闭此流,但要先刷新它。
java.io.FileWriter extends OutputStreamWriter extends WriterFileWriter:文件字符输出流。- 作用:把内存中字符数据写入到文件中。
- 构造方法:
FileWriter(File file):根据给定的file对象构造一个FileWriter对象。FileWriter(String filename):根据给定的文件名构造一个FileWriter对象。- 参数:
String filename:文件的路径。File file:文件。
- 作用:
- 会创建一个
FileWriter对象。 - 会根据构造方法中传递的文件/文件的路径,创建文件。
- 会把
FileWriter对象指向创建好的文件。
- 会创建一个
5. 字符输出流将单个字符写入文件
-
使用步骤:
- 创建
FileWriter对象,构造方法中绑定要写入数据的目的地。 - 使用
FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)。 - 使用
FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中。 - 释放资源(会先把内存缓冲区中的数据刷新到文件中)。
import java.io.FileWriter; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("/Users/zgl/Desktop/b.txt"); fw.write(97); fw.flush(); fw.close(); } } - 创建
6. flush方法和close方法的区别
-
flush:刷新缓冲区,流对象可以继续使用。 -
close:先刷新缓冲区,然后通知系统释放资源,流对象不可以再被使用。import java.io.FileWriter; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("/Users/zgl/Desktop/c.txt"); fw.write(97); fw.flush(); //可以继续使用流对象 fw.write(98); fw.close(); //抛出异常 IOException: Stream closed fw.write(99); } }
7. 字符输出流写数据的其他方法
-
void write(char[] cbuf):写入字符数组。 -
void write(char[] cbuf, int off, int len):写入字符数组的某一部分,off为数组的开始索引,len为写的字符个数。 -
void write(String str):写入字符串。 -
void write(String str, int off, int len):写入字符串的某一部分,off为字符串的开始索引,len为写的字符个数。import java.io.FileWriter; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("/Users/zgl/Desktop/d.txt"); char[] chars = {'a','b','c'}; fw.write(chars); // abc fw.write(chars,1,2); // bc String str = "zhuguli"; fw.write(str); // zhuguli fw.write(str,3,4); // guli fw.flush(); fw.close(); } }
8. 字符输出流的续写和换行
- 追加写/续写:使用两个参数的构造方法。
FileWriter(String name, boolean append)FileWriter(File file, boolean append)- 参数:
String name、File name:写入数据的目的地。boolean append:追加写开关。true:创建对象不会覆盖源文件,继续在文件的末尾追加写数据。false:创建一个新文件,覆盖源文件。
- 参数:
- 写换行:写换行符号
- win:
\r\n - Linux:
\n - Mac:
\r
- win:
import java.io.FileWriter;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("/Users/zgl/Desktop/e.txt",true);
for (int i = 0; i < 5; i++) {
fw.write("你好");
}
for (int j = 0; j < 5; j++) {
fw.write("你好" + "\r");
}
fw.flush();
fw.close();
}
}
9. JDK7 和 JDK9 流中异常的处理
-
JDK7的新特性:-
在
try后边可以增加一个(),在括号中可以定义流对象。 -
这个流对象的作用域就在
try中有效。 -
try中的代码执行完毕,会自动把流对象释放,不用写finally。 -
格式:
try(定义流对象;定义流对象;...){ 可能会产生异常的代码 }catch(异常类变量 变量名){ 异常处理逻辑 }
-
-
JDK9的新特性:-
try的前边可以定义流对象。 -
在
try后边的()可以直接引入流对象的名称(变量名)。 -
try中的代码执行完毕,会自动把流对象释放,不用写finally。 -
格式:
A a = new A(); B b = new B(); try(a,b){ 可能会产生异常的代码 }catch(异常类变量 变量名){ 异常处理逻辑 }
-
三、属性集
1. 使用Properties集合存储数据,遍历取出Properties集合中的数据
-
java.util.Properties集合 extends Hashtable<k,v> implements Map<k,v> -
Properties类表示了一个持久的属性集,Properties可保存在流中或从流中加载。 -
Properties集合是唯一一个与IO流相结合的集合。- 可以使用
Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储。 - 可以使用
Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用。
- 可以使用
-
属性列表中每个键及其对应值都是一个字符串。
Properties集合是一个双列集合,key和value默认都是字符串。
-
Properties集合有一些操作字符串特有的方法:Object setProperty(String key, String value)调用Hashtable的方法put。String getProperty(String key)通过key找到value值,此方法相当于Map集合中的get(key)方法。set<String> stringPropertyName()返回此属性列表中的键集。
import java.util.Properties; import java.util.Set; public class Test { public static void main(String[] args) { Properties prop = new Properties(); prop.setProperty("朱古力","18"); prop.setProperty("猪猪侠","20"); prop.setProperty("猪猪猪","22"); Set<String> strings = prop.stringPropertyNames(); for (String key : strings) { String value = prop.getProperty(key); System.out.println(key + "=" + value); } } }
2. Properties集合中的方法store
-
可以使用
Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储。 -
void store(OutputStream out, String comments) -
void store(Writer writer, String comments)- 参数:
OutputStream out:字节输出流,不能写入中文。Writer writer:字符输出流,可以写中文。String comment:注释,用来解释说明保存的文件是做什么用的。- 不能使用中文,会产生乱码,默认是
Unicode编码 - 一般使用
""空字符串。
- 不能使用中文,会产生乱码,默认是
- 参数:
-
使用步骤:
- 创建
Properties集合对象,添加数据。 - 创建字节/字符输出流对象,构造方法中绑定要输出的目的地。
- 使用
Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储。 - 释放资源。
import java.io.FileWriter; import java.io.IOException; import java.util.Properties; public class Test { public static void main(String[] args) throws IOException { Properties prop = new Properties(); prop.setProperty("朱古力","18"); prop.setProperty("猪猪侠","20"); prop.setProperty("猪猪猪","22"); FileWriter fw = new FileWriter("/Users/zgl/Desktop/f.txt"); prop.store(fw,"save"); fw.close(); } } - 创建
3. Properties集合中的方法load
-
可以使用
Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用。 -
void load(InputStream inStream) -
void load(Reader reader)- 参数:
InputStream inStream:字节输入流,不能读取含有中文的键值对。Reader reader:字符输入流,能读取含有中文的键值对。
- 参数:
-
使用步骤:
- 创建
Properties集合对象。 - 使用
Properties集合对象中的方法load读取保存键值对的文件。 - 遍历
Properties集合。
- 创建
-
注意:
- 存储键值对的文件中,键与值默认的连接符号可以使用
=、空格、其他符号。 - 存储键值对的文件中,可以使用
#进行注释,被注释的键值对不会再被读取。 - 存储键值对的文件中,键与值默认都是字符串,不用再加引号。
import java.io.FileReader; import java.io.IOException; import java.util.Properties; import java.util.Set; public class Test { public static void main(String[] args) throws IOException { Properties prop = new Properties(); FileReader fw = new FileReader("/Users/zgl/Desktop/f.txt"); prop.load(fw); Set<String> keys = prop.stringPropertyNames(); for (String key : keys) { String value = prop.getProperty(key); System.out.println(key + "=" + value); } fw.close(); } } - 存储键值对的文件中,键与值默认的连接符号可以使用
转载:https://blog.csdn.net/weixin_44781238/article/details/106128592