概述
概述
I/O流称为输入/输出流,是指数据在程序跟另一端进行流向的一个过程,另一端可以是硬盘上的文件,也可以是网络或者其它。
这里的入跟出都是相对程序而已的,输入流是指数据源流向程序,输出是指从程序将数据写出到数据源中。
IO的分类
根据数据的流向分为:输入流和输出流。
-
输入流 :把数据从数据源上读取到程序中的流。
-
输出流 :把数据从程序中写出到数据源上的流。
根据数据的类型分为:字节流和字符流。
-
字节流 :以字节为单位,读写数据的流。
-
字符流 :以字符为单位,读写数据的流。
输入流 | 输出流 | |
字节流 | 字节输入流InputStream | 字节输出流OutputStream |
字符流 | 字符输入流Reader | 字符输出流Writer |
File类
由于经常需要使用IO流来操作硬盘上的文件,JDK将硬盘上的文件映射为java.io.File
类,所以我们先要学习如何使用这个类。
File类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。
File对象代表磁盘中实际存在的文件和目录。通过以下构造方法创建一个File对象。
-
常用构造方法
new File(File parent,String child ); new File(String parent,String child); new File(String pathName);
-
常用方法
方法名 | 描述 |
---|---|
String getName() | 获取文件(夹)名 |
String getPath() | 获取文件(夹)路径 |
boolean exists() | 文件(夹)是否存在 |
boolean isFile() | 是否是一个文件 |
boolean isDirectory() | 是否是一个目录(文件夹) |
boolean createNewFile() | 创建一个文件 |
boolean mkdir() | 创建一个具体的文件夹 |
boolean mkdirs() | 创建多级文件夹 |
boolean delete() | 删除某个文件(夹) |
String [] list() | 返回某个文件夹下的所有文件(夹)名 |
File [] listFiles() | 获取某个文件夹下所有的文件(夹) |
代码演示
public class Demo06File {
public static void main(String[] args) throws IOException {
File file = new File("D:/a.txt");
//
输出个文件是否存在
System.out.println(file.exists());
if(!file.exists()){
//
创建这个文件
file.createNewFile();
}
//
判断这个文件是否是文件
System.out.println(file.isFile());
//
判断这个文件是否是目录
System.out.println(file.isDirectory());
//
输出文件的名字
System.out.println(file.getName());
//
输出文件的路径
System.out.println(file.getPath());
//
输出文件的绝对路径
System.out.println(file.getAbsolutePath());
//
删除此文件
file.delete();
File dir = new File("d:/blb");
//
创建这个目录,前提是所有父级目录都存在
dir.mkdir();
//
创建这个目录,父级目录不存在,则把所有父级目录都创建
dir.mkdirs();
//
返回dir目录中的所有文件,以String [] 的形式保存
String[] list = dir.list();
System.out.println(Arrays.toString(list));
//
返回dir目录中的所有文件,以File [] 的形式保存
File[] files = dir.listFiles();
for (File f:files) {
System.out.println(f.getName());
}
//
删除此目录,前提是这是一个空目录
dir.delete();
}
}
字节流
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,传输时只需要传输对应的二进制数据即可。流的传输底层就是这些二进制的数据的流动。
-
java.io.OutputStream
抽象类是表示字节输出流的超类,将指定的字节信息写出到目的地。常用API有:-
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.InputStream
抽象类是表示字节输入流的超类,可以读取字节信息到内存中。常用API有:-
public void close()
:关闭此输入流并释放与此流相关联的任何系统资源。 -
public abstract int read()
: 从输入流读取数据的下一个字节。 -
public int read(byte[] b)
: 从输入流中读取一些字节数,并将它们存储到字节数组 b
-
最常用的实现类是java.io.FileInputStream
跟java.io.FileOutputStream
,用来将数据读取/写出到文件中。
代码演示
要求:将盘中的一张图片(D:aphoto.jpg)通过程序复制到另一个路径下(D:bphoto.jpg)。
public class Demo07IO {
public static void main(String[] args) {
// 把一个图片的数据读取到程序中,把程序中的数据写到另一个文件(图片)中。
InputStream input = null ;
OutputStream output = null ;
try {
File f1 = new File("D:\a\photo.jpg");
File f2 = new File("D:\b\photo.jpg");
// 创建目标文件
if (!f2.exists()) {
f2.createNewFile();
}
// 把f1读取到程序中
input = new FileInputStream(f1);
output = new FileOutputStream(f2);
byte b[] = new byte[1024];
int i = 0;
while ((i = input.read(b)) != -1) {
output.write(b, 0, i);
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(input != null ){
input.close();
}
if(output != null ){
output.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符流
有时候我们需要通过程序去操作文本文件,这时使用字节流可能会出现字符显示不完整的问题因为一个中文字符可能占据多个字节。所以JAVA专门提供一类字符流,以字符为单位操作,使用这类流来操作字符类型的数据更加契合。
java.io.Reader
抽象类是表示用于读取字符流的超类,它定义了字符输入流的基本共性功能方法。
-
public void close()
:关闭此流并释放与此流相关联的任何系统资源。 -
public int read()
: 从输入流读取一个字符。 -
public int read(char[] cbuf)
: 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。
代码演示
要求:将文本文件中的内容读取到控制台中显示。
public class Demo08IO {
public static void main(String[] args) {
FileReader fileReader = null;
try {
//
读取D盘中a.txt文件的内容
File f = new File("D:\a.txt");
//
创建对应的输入流
fileReader = new FileReader(f);
int c ;
while((c = fileReader.read())!=-1){
System.out.println( (char)c);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//
关闭流
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
java.io.FileWriter
抽象类是表示用于写出字符流的超类。构造时使用系统默认的字符编码和默认字节缓冲区。
-
void write(int c)
写入单个字符。 -
void write(char[] cbuf)
写入字符数组。 -
abstract 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()
关闭此流,但要先刷新它。
代码演示
要求:将下面的一段话输入到D盘的文本文件中。
我和我的祖国,一刻也不能分割,无论我走到哪里,都流出一首赞歌。
public class Demo09IO {
public static void main(String[] args) {
File f = new File("D:\China.txt");
FileWriter fileWriter = null;
try {
//
创建文件输出流
fileWriter = new FileWriter(f,true);// 第2个参数表示是追加还是覆盖
fileWriter.write("我和我的祖国,一刻也不能分割,无论我走到哪里,都流出一首赞歌。");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fileWriter!=null){
fileWriter.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
缓冲流
概述
JAVA的IO体系中有些流不能独立使用,必须套在其它流的上面才能使用,称为包装流。JAVA的IO体系就是通过装饰模式来实现。需要什么流的功能就在外面套一个对应的流即可。
而缓冲流就是常用的一个包装流,也叫高效流,是对4个基本的File
流的增强,所以也是4个流,按照数据类型分类:
-
字节缓冲流:
BufferedInputStream
,BufferedOutputStream
-
字符缓冲流:
BufferedReader
,BufferedWriter
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
字符缓冲流
构造方法
-
public BufferedReader(Reader in)
:创建一个 新的缓冲输入流。 -
public BufferedWriter(Writer out)
: 创建一个新的缓冲输出流。
构造举例
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
特有方法
字符缓冲流的基本方法与普通字符流调用方式一致。
-
BufferedReader:
public String readLine()
: 读一行文字。 -
BufferedWriter:
public void newLine()
: 写一行行分隔符,由系统属性定义符号。
输入缓冲流代码示例
public class Demo10IO {
public static void main(String[] args) throws IOException {
FileReader fileReader = null;
BufferedReader bufferdReader = null;
bufferdReader = new BufferedReader(fileReader);
//
读取D盘中a.txt文件的内容
File f = new File("D:\China.txt");
//
创建对应的输入流
fileReader = new FileReader(f);
String s = null;
while((s = bufferdReader.readLine())!=null){
System.out.println(s);
}
//
关闭流
fileReader.close();
}
}
输出缓冲流代码示例
public class Demo11IO {
public static void main(String[] args) throws IOException {
File f = new File("D:\blb.txt");
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;
fileWriter = new FileWriter(f,true);// 第2个参数表示是追加还是覆盖
bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.newLine();
bufferedWriter.write("床前明月光");
bufferedWriter.newLine();
bufferedWriter.write("疑是地上霜");
bufferedWriter.newLine();
bufferedWriter.write("举头望明月");
bufferedWriter.newLine();
bufferedWriter.write("低头思故乡");
bufferedWriter.flush();
bufferedWriter.close();
fileWriter.close();
}
}
对象流
概述
Java 提供了一种对象序列化的机制。用来将某个对象保存到磁盘上或者在网络上传输。可以理解为将内存中的对象进行持久化保存下来。反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。
JAVA中是通过对象流来实现对象的序列化跟反序列化的,对象流也是一种包装流。
序列化
java.io.ObjectOutputStream
类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。
被序列化的对象需要实现java.io.Serializable
接口。Serializable
是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException
。
如果有不需要序列化的字段使用transient关键字修饰即可。
代码示例
//实体类
class Person implements Serializable {
//
序列化版本号,必须保证序列化跟反序列化的版本号一致
private static final long serialVersionUID = -1213754818242979380L;
public String name
;
//设置age字段为transient,表示此字段不需要序列化
public
transient int age = 1 ;
public String sex ;
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
", sex='" + sex + ''' +
'}';
}
}
序列化代码示例
public class Demo12Serializable {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//
saveObject();// 序列化
readObject();// 反序列化
}
//
序列化
public static void saveObject() throws IOException{
//
准备要序列化的对象
Person person = new Person();
person.name = "张三";
person.age = 18 ;
person.sex = "男";
//
准备对象流
FileOutputStream fos = new FileOutputStream("d:/China.txt");
ObjectOutputStream out = new ObjectOutputStream(fos);
//
序列化对象
out.writeObject(person);
//
关闭流
out.close();
fos.close();
}
//
反序列化
public
static void readObject() throws IOException, ClassNotFoundException {
//
准备对象流
FileInputStream fis = new FileInputStream("d:/China.txt");
ObjectInputStream in = new ObjectInputStream(fis);
//
反序列化对象
Person person = (Person) in.readObject();
System.out.println(person);
//
关闭流
in.close();
fis.close();
}
}
重点
序列化的重点在于序列化跟反序列化的的版本号要一致,通常可以设置成固定值或者有IDE自动生成,这个版本号定义在实体类的属性private static final long serialVersionUID
。如果版本号信息不一致会抛出InvalidClassException
异常。
最后
以上就是活泼戒指为你收集整理的JAVA基础--I0流的全部内容,希望文章能够帮你解决JAVA基础--I0流所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复