用于硬盘和内存之间的数据交互,input
内存读取,output
内存输出
输入流 | 输出流 |
---|---|
字节输入流InputStream |
字节输出流OutputStream |
字符输入流Reader |
字节输出流Writer |
一切文件数据都是以字节的形式保存的。不管什么养的流对象都是在传输字节。
java.io.OutputStream
它是所有输出流的抽象父类,子类名称前半部分表示自己的输出类型,后半部分表示父类如:FileOutputStream
输出到文件中,ObjectOutputStream
输出对象类
方法 | 描述 |
---|---|
void close() | 关闭此输出流并释放与此流相关联的任何系统资源。 |
void flush() | 刷新此输出流并强制任何缓冲的输出字节被写出。 |
void write(byte[] b) | 将 b.length字节从指定的字节数组写入此输出流。 |
void write(byte[] b, int off, int len) | 从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。 |
abstract void write(int b) | 将指定的字节写入此输出流。 |
把内存中的数据写入到文件中。打开文件并写入文件,文件不存在则会创建该文件。
向文件中追加/续写内容
构造方法 | 功能 |
---|---|
FileOutputStream(String name,boolean append) | 创建一个向制定name文件写入数据的输出流 |
FileOutputStream(File file,boolean append) | 创建一个向指定file对象表示的文件中写入数据的输出流 |
append 是追加写开关
换行:
windows:\r\n
linux:\n
mac:\r
写入数据时,会把写入的十进制数字,转换为二进制数字写入文件,.txt文件编辑器会查询编码表,把字节流转换为字符流
File f = new File("C:/java/hello");
OutputStream os = new FileOutputStream(f);
os.write(数组);
os.close();
所有字节输入流类的超类
方法 | 功能 |
---|---|
void close() | 关闭此输入流并释放与流相关联的任何系统资源。 |
abstract int read() | 从输入流读取数据的下一个字节。 |
int read(byte[] b) | 从输入流中读取一些字节数,并将它们存储到缓冲器阵列 b 。 |
构造方法 | 功能 |
---|---|
FileInputStream(File file) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。 |
File f = new File("C:/java/hello");
FileInputStream fis = new FileInputStream(f);
(char)fis.read();
//不可以这么判断,会导致一次值没有接收
int res;
while(fis.read()!=-1)
//正确
while((res = fis.read())!=-1)
System.out.println((char)res);
fis.close()
int len=0;
byte b = new byte[1024];//通常设为1024或其整数倍
int len = fis.read(b);返回有效字符长度
while((len = fis.read(b))!= -1){
System.out.println(new String(b),0,len);
}
方法 | 功能 |
---|---|
abstract void close() | 关闭流并释放与之相关联的任何系统资源。 |
int read() | 读一个字符 |
int read(char[] cbuf) | 将字符读入数组。 |
abstract int read(char[] cbuf, int off, int len) | 将字符读入数组的一部分。 |
FileReader
继承了InputStreamReader
(实现了Reader
接口)
构造方法 | 功能 |
---|---|
FileReader(File file) | 创建一个新的 FileReader ,给出 File读取。 |
FileReader(String fileName) | 创建一个新的 FileReader ,给定要读取的文件的名称。 |
//单个字符读取文件
FileReader fr = new FileReader("day07maven/c.txt");
int len = 0;
while ((len = fr.read())!=-1){
System.out.print((char)len);
}
//字符数组读取文件
FileReader fr = new FileReader("day07maven/chai.txt");
char[] c = new char[1024];
int len = 0;
while ((len = fr.read(c))!=-1){
System.out.print(new String(c,0,len));
}
FileWriter
继承了OutputStreamWriter
类(该类实现了Writer
接口)
字节流会将字节数据直接写入文件,即使没有close
输出流,但是FileWriter
调用完writer
必须调用flush
或者close
才能把数据从内存缓冲区写入文件。
FileWriter fw = new FileWriter("day07maven/chai.txt",true);
fw.write("\rio种类可真多");
fw.flush();
fw.close();
flush和close区别:
try(对象声明){
可能产生异常代码
}catch{
处理
}
try(
FileInputStream fis = new FileInputStream("day07maven/chai.txt",true);
){
int len = 0;
while((len = fls.read())!= -1){
System.out.println(len);
}
}catch(IOException e){
System.out.println(e);
}
java.util.Properties
集合 extends Hashtable
Properties类表示了一个持久的属性集,可以保存在流中,或从流中加载。他是唯一和IO流相结合的集合,今后常用于 配置文件。
方法 | 功能 |
---|---|
void load(InputStream inStream) | 从输入字节流读取属性列表(键和元素对)。 |
void load(Reader reader) | 以简单的线性格式从输入字符流读取属性列表(关键字和元素对)。 |
void store(OutputStream out, String comments) | 将此 Properties表中的此属性列表(键和元素对)以适合于使用 load(InputStream)方法加载到 Properties表格的格式写入输出流。 |
void store(Writer writer, String comments) | 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式输出到输出字符流。 |
Object setProperty(String key, String value) | 调用 Hashtable方法 put 。 |
String getProperty(String key) | 使用此属性列表中指定的键搜索属性。 |
Set stringPropertyNames() | 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串,包括默认属性列表中的不同键,如果尚未从主属性列表中找到相同名称的键。 |
public static void main(String[] args) {
try(
FileWriter fw = new FileWriter("day07maven/test.properties");
FileReader fr = new FileReader("day07maven/test.properties");
){
//创建Properties集合并传入数据
Properties pro = new Properties();
pro.setProperty("name","c");
pro.setProperty("age","22");
//将集合中数据写入.properties文件
pro.store(fw,"save data");
//加载.properties文件,通过key值
pro.load(fr);
String name = pro.getProperty("name");
int age = Integer.parseInt(pro.getProperty("age"));
//打印
System.out.println(name+": "+age);
}catch(IOException e){
System.out.println(e);
}
}
缓冲流也称高效流,是对四个基本Filexxx
流的增强,所以也分为四个流。原本的流单个字节或字符进行传输,缓冲流增加缓冲区,同时对大量数据进行操作,提高效率。
字节缓冲流 | 字符缓冲流 |
---|---|
BufferedInputStream |
BufferedReader |
BufferedOutputStream |
BufferedWriter |
public static void main(String[] args) {
try(
FileInputStream fis = new FileInputStream("day07maven/chai.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
){
byte[] b = new byte[1024];
int len = 0;
while ((len = bis.read(b))!=-1){
System.out.println(new String(b,0,len));
bis.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
try(
FileOutputStream fos = new FileOutputStream("day07maven/chai.txt",true);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.flush();
){
bos.write(new String("--BufferedOutputStream").getBytes());
}catch(IOException e){
e.printStackTrace();
}
}
方法 | 功能 |
---|---|
void newLine() | 写一行行分隔符。 |
public static void main(String[] args) {
try (
FileWriter fw = new FileWriter("day07maven/chai.txt");
BufferedWriter bw = new BufferedWriter(fw);
) {
bw.write("缓冲字符输出流");
} catch (IOException e) {
e.printStackTrace();
}
}
方法 | 功能 |
---|---|
String readLine() | 读一行文字。 |
public static void main(String[] args) {
try(
FileReader fr = new FileReader("day07maven/chai.txt");
BufferedReader br = new BufferedReader(fr);
){
char[] b = new char[1024];
int len = 0;
while ((len = fr.read(b))!=-1){
System.out.println(new String(b,0,len));
}
}catch (IOException e){
e.printStackTrace();
}
}
FileReader
作为InputStreamReader
子类,设定了默认编码表进行读取数据,FileWriter
类似。InputStreamReader
和OutputStreamWriter
作为可以设定编码方式的流,被称为转换流
InputStreamReader是从字节流到字符流的桥梁:它读取字节,并使用指定的charset将其解码为字符。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
OutputStreamWriter是从字符流到字节流的桥梁:使用指定的charset将写入的字符编码为字节。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
方法 | 功能 |
---|---|
void writeObject(Object obj) | 将指定的对象写入ObjectOutputStream。 |
方法 | 功能 |
---|---|
Object readObject() | 从ObjectInputStream读取一个对象。 |
Serializable
接口以启用序列化功能class
文件... implements Serializable
static
关键字声明的变量,提前进入内存,被所有对象共享,不属于任何对象,所以不能序列化tranisent
关键字声明的变量不能被序列化,有静态的功能,没有静态的含义反序列化时,会给对象类生成序列号serialVersionUID
,反序列化时如果类出现修改,序列号改变,反序列化会报错
为了解决这个问题,我们可以在类中声明静态不可变的序列号,保证序列号不变
public class Person implements Serializable{
//设定序列号
private static finall long serialVersionUID = 1L;
private String name;
public Person(){}
}
当我们在文件中存储多个对象的时候,可以把多个对象存储到一个集合中,对集合序列化和反序列化
public static void main(String[] args) throws IOException, ClassNotFoundException {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("a"));
list.add(new Person("b"));
list.add(new Person("c"));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day07maven/chai.txt"));
oos.writeObject(list);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day07maven/chai.txt"));
Object o = ois.readObject();
ArrayList<Person> olist= (ArrayList<Person>)(o);
for (Person person : olist) {
System.out.println(person);
}
oos.close();
ois.close();
}
//内部Person类
static class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
public Person(String name){
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
java.io.PrintStream
打印流可以打印任何数据表示形式。
IOException
print
println
write
则查看数据时会查询编码表97->a,使用自己特有方法print
数据原样输出public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("day07maven/printstream.txt");
ps.println(97);
ps.println('a');
ps.println("string");
ps.println(true);
ps.println(8.8);
ps.close();
}
public static void main(String[] args) throws FileNotFoundException {
System.out.println("在控制台输出");
PrintStream ps = new PrintStream("day07maven/printstream.txt");
//将输出语句的目的地修改为打印流目的地
System.setOut(ps);
System.out.println("在打印流目的地输出");
ps.close();
}
next():
1、一定要读取到有效字符后才可以结束输入。
2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
next() 不能得到带有空格的字符串。nextLine():
1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
2、可以获得空白。
//scanner接收数据求平均值
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
double sum = 0;
int m = 0;
while (scan.hasNextDouble()) {
double x = scan.nextDouble();
m = m + 1;
sum = sum + x;
}
System.out.println(m + "个数的和为" + sum);
System.out.println(m + "个数的平均值是" + (sum / m));
scan.close();
}
12
23
15
21.4
end // 输入非数字结束输入
4个数的和为71.4
4个数的平均值是17.85
手写不易,点赞感谢