输入/输出处理是程序设计中非常重要的环节, 如从键盘或传感器读入数据、 从文件中读取数据或向文件中写入数据、 从网络中读取或写入数据等。 Java 把这些不同类型的输入、 输出抽象为 “流” , 所有的输入/输出以流的形式进行处理。I表示Input,O表示Output,通过IO可以完成硬盘文件的读和写。
在java中只要“类名”以Stream结尾的都是字节流。以“Reader/Writer”结尾的都是字符流
文件专属:
java.io.FileInputStream
java.io.FileOutputStream
java.io.FileReader
java.io.FileWriter
转换流:(将字节流转换成字符流)
java.io.InputStreamReader
java.io.OutputStreamWriter
缓冲流专属:
java.io.BufferedReader
java.io.BufferedWriter
java.io.BufferedInputStream
java.io.BufferedOutputStream
数据流专属:
java.io.DataInputStream
java.io.DataOutputStream
标准输出流:
java.io.PrintWriter
java.io.PrintStream
对象专属流:
java.io.ObjectInputStream
java.io.ObjectOutputStream
InputStream 和 OutputStream 继承结构图:
返回值类型 | 方法名 | 描述 |
---|---|---|
void | close() | 关闭此流并释放与该流关联的所有系统资源 |
abstract int | read() | 从输入流读取下一个数据字节.再读的时候读取不到任何数据返回-1 |
int | read(byte[] b) | 从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中 |
int | read(byte[] b, int off, int len) | 将输入流中最多 len 个数据字节读入字节数组 |
void | flush() | 刷新此输出流并强制写出所有缓冲的输出字节 |
void | write(byte[] b) | 将 b.length 个字节从指定的字节数组写入此输出流 |
void | write(byte[] b, int off, int len) | 将指定字节数组中从偏移量 off 开始的 len 个字节写入此输出流 |
abstract void | write(int b) | 将指定的字节写入此输出流 |
Reader 和 Writer 继承结构图:
返回值类型 | 方法名 | 描述 |
---|---|---|
abstract void | close() | 关闭该流 |
int | read() | 读取单个字符 |
int | read(char[] cbuf) | 将字符读入数组 |
abstract int | read(char[] cbuf, int off, int len) | 将字符读入数组的某一部分 |
Writer | append(char c) | 将指定字符追加到此 writer |
abstract | void flush() | 刷新此流 |
void | write(char[] cbuf) | 写入字符数组 |
abstract void | write(char[] cbuf, int off, int len) | 写入字符数组的某一部分 |
void | write(int c) | 写入单个字符 |
void | write(String str) | 写入字符串 |
void | write(String str, int off, int len) | 写入字符串的某一部分 |
File 类是 java.io 包中唯一代表磁盘文件和目录的类。 File类和四大家族没有关系,所以File类不能完成文件的读和写。
File dir = new File("D:/java/tt/");//创建目录
File file = new File("D:/java/tt/file.txt");//创建文件
File file = new File(dir,"file1.txt");//在dir目录下创建文件
File file = new File("D:/java/tt/","file2.txt");//在tt目录下创建文件
返回类型 | 方法名 | 描述 |
---|---|---|
boolean | exits( ) | 判断文件是否存在 |
boolean | createNewFile() | 以文件形式新建 |
boolean | mkdir() | 以目录的形式新建 |
boolean | mkdirs() | 多重目录的形式新建 |
boolean | delete( ) | 删除 File 对象对应的文件或目录 |
boolean | isFile( ) | 判断文件是否是文件 |
boolean | isDirectory( ) | 判断文件是否是目录 |
boolean | canRead( ) | 判断文件是否可读 |
boolean | canWrite( ) | 判断文件是否可写 |
long | length( ) | 获取文件的长度 (单位时字节) |
long | lastModified() | 获取文件最后一次修改时间,返回从1970年到现在的总毫秒数 |
String | getName( ) | 获取文件的名字 |
String | getPath( ) | 返回 File 对象对应的路径 |
String | getAbsolutePath( ) | 获取文件的绝对路径 |
String | getParent( ) | 获取文件的父目录 |
String[] | list( ) | 列出指定目录的全部内容,只列出名称 |
File[ ] | listFiles( ) | 返回包含 File 对象所有子文件和子目录的 File 数组 |
文件流主要分为
FileInputStream
1、文件字节输入流,万能的,任何类型的文件都可以采用这个流来读。
2、字节的方式,完成输入的操作,完成读的操作(硬盘 → 内存)
public class FileInputStreamTest {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("chapter23/src/tempfile3");
// 准备一个byte数组,一次最多读取4个字节
byte[] bytes = new byte[4];
int readCount = 0;
//is.read(bytes)的返回值是:读取到的字节数量,不是字节本身
while((readCount = fis.read(bytes)) != -1) {
//将字节数组全部转换成字符串
System.out.print(new String(bytes, 0, readCount));
}
} catch (IOException e) {
e.printStackTrace();
} finally { //在finally语句块当中确保流一定关闭
if (fis != null) {
try {
fis.close();//关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FileInputStream类的其它常用方法:
FileOutputStream
字节的方式,完成输出的操作,完成写的操作(内存 → 硬盘)
public class FileOutputStreamTest {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
//文件不存在的时候会自动新建!
// 这种方式谨慎使用,这种方式会先将原文件清空,然后重新写入。
//fos = new FileOutputStream("D:\\IO\\why\\b.txt");
// 以追加的方式在文件末尾写入。不会清空原文件内容。
fos = new FileOutputStream("D:\\IO\\why\\b.txt", true);
byte[] bytes = {97, 98, 99, 100};
// 将byte数组全部写出
fos.write(bytes); // abcd
// 将byte数组的一部分写出
fos.write(bytes, 0, 2); // 再写出ab
String s = "我是输出流";
// 将字符串转换成byte数组。
byte[] bs = s.getBytes();
fos.write(bs);
fos.flush();// 写完之后,最后一定要刷新
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流(代码省略)
}
}
}
FileReader
文件字符输入流,只能读取普通文本。读取文本内容时,比较方便快捷。
public class FileReaderTest {
public static void main(String[] args) {
FileReader reader = null;
try {
//创建文件字符输入流
reader = new FileReader("D:\\IO\\why\\b.txt");
//开始读
char[] chars = new char[4]; // 一次读取4个字符
int readCount = 0;
while((readCount = reader.read(chars)) != -1) {
System.out.print(new String(chars,0,readCount));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流(代码省略)
}
}
}
FileWriter
文件字符输出流,负责写。只能输出普通文本
public class FileWriterTest {
public static void main(String[] args) {
FileWriter out = null;
try {
out = new FileWriter("D:\\IO\\why\\c.txt", true);
char[] chars = {'我','是','中','国','人'};
out.write(chars); //将我是中国人写入到文件
out.write(chars, 2, 3);//将中国人写入到文件
out.write("我是一名java软件工程师!");
out.write("\n");// 写出一个换行符。
out.write("hello world!");
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流(代码省略)
}
}
}
缓冲流主要是为了提高效率而存在的,减少物理读取次数,缓冲流主要有:
BufferedReader
带有缓冲区的字符输入流。 使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组,自带缓冲。
public class BufferedReaderTest {
public static void main(String[] args) throws Exception{
FileReader reader = new FileReader("D:\\IO\\why\\a.txt");
// 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流
// 外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流
// FileReader就是一个节点流BufferedReader就是包装流/处理流。
BufferedReader br = new BufferedReader(reader);
// 读一行但不带换行符
//String firstLine = br.readLine();
String s = null;
while((s = br.readLine()) != null){
System.out.print(s);
}
// 对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭
br.close();
}
}
BufferedWriter
带有缓冲的字符输出流
public class BufferedWriterTest {
public static void main(String[] args) throws Exception{
// 带有缓冲区的字符输出流
BufferedWriter out = new BufferedWriter(new FileWriter("copy"));
// 开始写
out.write("hello world!");
out.write("\n");
out.write("hello kitty!");
// 刷新
out.flush();
// 关闭最外层
out.close();
}
}
转换流主要有两个 InputStreamReader 和 OutputStreamWriter
//字节输入流
FileInputStream in = new FileInputStream("Copy02.java");
//通过转换流转换(InputStreamReader将字节流转换成字符流)
InputStreamReader reader = new InputStreamReader(in);
//字节输出流
FileOutputStream out = new FileOutputStream("copy", true);
//通过转换流转换(OutputStreamWriter将字节流转换成字符流)
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(out);
标准输出流主要包含两个:
PrintStream
System.out 其实对应的就是 PrintStream,默认输出到控制台,我们可以重定向它的输出,可以定向到文件,也就是执行 System.out.println(“hello”)不输出到屏幕,而输出到文件
public class PrintStreamTest {
public static void main(String[] args) throws Exception{
//默认输出到控制台
System.out.println("hello world!");
//标准输出流不再指向控制台,指向“log”文件。
PrintStream printStream = new PrintStream(new FileOutputStream("log"));
//修改输出方向,将输出方向修改到"log"文件。
System.setOut(printStream);
//再输出
System.out.println("hello world");
System.out.println("hello kitty");
System.out.println("hello zhangsan");
//标准输出流不需要手动close()关闭
}
}
PrintWriter
PrintWriter printWriter = new PrintWriter(new FileWriter("D:\\IO\\why\\f.txt"));
printWriter.print("我是printWriter");
printWriter.flush();
printWriter.close();
数据流包含两个:
DataOutputStream
这个流可以将数据连同数据的类型一并写入文件
注意:这个文件不是普通文本文档
public class DataOutputStreamTest {
public static void main(String[] args) throws Exception{
// 创建数据专属的字节输出流
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data"));
byte b = 100;
short s = 200;
int i = 300;
long l = 400L;
float f = 3.0F;
double d = 3.14;
boolean sex = false;
char c = 'a';
// 把数据以及数据的类型一并写入到文件当中
dos.writeByte(b);
dos.writeShort(s);
dos.writeInt(i);
dos.writeLong(l);
dos.writeFloat(f);
dos.writeDouble(d);
dos.writeBoolean(sex);
dos.writeChar(c);
dos.flush();//刷新
dos.close();//关闭最外层流
}
}
DataInputStream
DataOutputStream写的文件,只能使用DataInputStream去读。并且读的时候你需要提前知道写入的顺序。读的顺序需要和写的顺序一致。才可以正常取出数据
public class DataInputStreamTest01 {
public static void main(String[] args) throws Exception{
//创建数据输入流
DataInputStream dis = new DataInputStream(new FileInputStream("data"));
// 开始读,读的顺序需要和写的顺序一致
byte b = dis.readByte();
short s = dis.readShort();
int i = dis.readInt();
long l = dis.readLong();
float f = dis.readFloat();
double d = dis.readDouble();
boolean sex = dis.readBoolean();
char c = dis.readChar();
System.out.println(b);
System.out.println(s);
System.out.println(i + 1000);
System.out.println(l);
System.out.println(f);
System.out.println(d);
System.out.println(sex);
System.out.println(c);
dis.close();
}
}
对象流可以将 Java 对象转换成二进制写入磁盘,这个过程通常叫做序列化,并且还可以从磁盘读出完整的 Java 对象,而这个过程叫做反序列化。对象流主要包括ObjectInputStream 和 ObjectOutputStream
ObjectOutputStream
public class Student implements Serializable {
// IDEA工具自动生成序列化版本号。
//private static final long serialVersionUID = -7998917368642754840L;
// 建议将序列化版本号手动的写出来。不建议自动生成
private static final long serialVersionUID = 1L; // java虚拟机识别一个类的时候先通过类名,如果类名一致,再通过序列化版本号。
private int no;
private String name;
public Student(int no, String name) {
this.no = no;
this.name = name;
}
/*setter and getter 方法*/
/*toString()方法*/
}
序列化对象
public class ObjectOutputStreamTest {
public static void main(String[] args) throws Exception{
// 创建java对象
Student s = new Student(1111, "张三");
// 创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("students"));
// 序列化对象
oos.writeObject(s);
// 刷新
oos.flush();
// 关闭
oos.close();
}
}
ObjectInputStream
反序列化对象
public class ObjectInputStreamTest {
public static void main(String[] args) throws Exception{
//创建对象输入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("students"));
// 开始反序列化,读
Object obj = ois.readObject();
// 反序列化回来是一个学生对象,所以会调用学生对象的toString方法。
System.out.println(obj);
ois.close();
}
}
经常改变的数据,可以单独写到一个文件中,使用程序动态读取。将来只需要修改这个文件的内容,java代码不需要改动,不需要重新编译,服务器也不需要重启。就可以拿到动态的信息。
类似于以上机制的这种文件被称为配置文件。
并且当配置文件中的内容格式是:
key1=value
key2=value
public class IoPropertiesTest {
public static void main(String[] args) throws Exception{
/*
Properties是一个Map集合,key和value都是String类型。
想将userinfo文件中的数据加载到Properties对象当中。
*/
// 新建一个输入流对象
FileReader reader = new FileReader("chapter23/userinfo.properties");
// 新建一个Map集合
Properties pro = new Properties();
// 调用Properties对象的load方法将文件中的数据加载到Map集合中
// 文件中的数据顺着管道加载到Map集合中,其中等号=左边做key,右边做value
pro.load(reader);
// 通过key来获取value呢?
String username = pro.getProperty("username");
System.out.println(username);
String password = pro.getProperty("password");
System.out.println(password);
String data = pro.getProperty("data");
System.out.println(data);
String usernamex = pro.getProperty("usernamex");
System.out.println(usernamex);
}
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/m0_60117382/article/details/123771667
内容来源于网络,如有侵权,请联系作者删除!