1.输入(Input)&输出流(Output)
a.概述:
Java对数据的操作是通过流的方式进行的;
IO流用于处理设备之间的数据传输,根据流向可分为 输入流(将外设中的数据读到内存中)、输出流(将内存中的数读到外设中)。
2.字节流&字符流
a.概述:
根据流的数据类型可以分为字符流、字节流
字节流:字节流主操作byte类型数据
字符流:字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字,再对这个文字进行操作。
b.分类:
字节流的抽象基类: InputStream OutputStream
字符流的抽象基类: Reader Writer
注意:由这四个类派生出的子类名称都是其父类名作为子类名的后缀名。
FileWriter代码示例:
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterDemo {
private static final String LINE_SEPARATOR=System.getProperty("line.separator");//调用系统的换行符
public static void main(String[] args) throws IOException {
//创建一个往文件中写入字符数据的字符输出流对象并明确文件目的地为 F://demo.txt
//如果文件不存在则自动创建,如果文件存在则会被覆盖
//如果构造函数中加入 true,可对文件实现续写
FileWriter fw=new FileWriter("f://demo.txt",true);
//调用Writer对象中的write(string)方法 将数据写入 字节流中
fw.write("abc"+LINE_SEPARATOR+"de");
fw.write("hehehehe");
//调用 flush方法 刷新缓冲中,关闭流关闭资源
fw.close();
}
}
FileReader代码示例:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
// 创建读取字符数据的流对象
// 注意:在创建读取流时必须关联文件
FileReader fr = new FileReader("F:\\demo.txt");
// 读取方式一:调用Reader中的read方法读取字符
int ch=0;
while((ch=fr.read())!=-1){
System.out.println((char)ch);
}
// 读取方式二:使用read(char[]) 读取文本文件数据
char[] buf = new char[256];
// 将读到的字符存储到数组中
int len = 0;
while ((len = fr.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}
fr.close();
}
}
3.缓冲区
a.概述:缓冲区就是内存里的一块区域,把数据先存内存里,然后一次性写入,从而提高里对数据的读写效率。
b.对应类:BufferedWriter BufferedReader
c.BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
代码示例:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
FileWriter fw=new FileWriter("F://demo.txt");
//为提高写入效率,使用字符流的缓冲区
//创建一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联
BufferedWriter bufw=new BufferedWriter(fw);
//使用缓冲区的写入方法将数据先写到缓冲区中
bufw.write("abcdef");
//使用缓冲区的刷新方法将数据刷到目的地中
bufw.flush();
//关闭缓冲区。其实就是关闭被缓冲的流对象
bufw.close();
}
}
d.BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
代码示例:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("F:\\demo.txt");
BufferedReader bufr=new BufferedReader(fr);
String line=null;
while((line=bufr.readLine())!=null){//readLine(); 读取一个文本行过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。
System.out.println(line);
}
}
}
4.转换流
a.InputStreamReader 字节流转换为字符流的桥梁
代码示例:
// 字节流
InputStream in = System.in;
// 将字节转换成字符的桥梁 转换流
InputStreamReader isr = new InputStreamReader(in);
// 字符流
BufferedReader bufr = new BufferedReader(isr);
String line = null;
while ((line = bufr.readLine()) != null) {
if ("over".equals(line))
break;
System.out.println(line.toUpperCase());
}
bufr.readLine();
b.OutputStreamWriter 字符流转换为字节流的桥梁
代码示例:
// 字节流
InputStream in = System.in;
// 将字节转换成字符的桥梁,转换流
InputStreamReader isr = new InputStreamReader(in);
// 字符流
BufferedReader bufr = new BufferedReader(isr);
// 字节流
OutputStream out = System.out;
// 将字符转换成字节的桥梁,转换流
OutputStreamWriter osw = new OutputStreamWriter(out);
BufferedWriter bufw = new BufferedWriter(osw);
String line = null;
while ((line = bufr.readLine()) != null) {
if ("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
什么时候使用转换流?
a.源或者目的对应的设备是字节流,但操作的是文本数据,可以使用转换流作为桥梁。
b.一旦操作文本涉及到具体的指定编码表时,必须使用转换流。
5.流的基本操作规律
a.明确源和汇
源:InputStream Reader
汇:OutputStream Writer
b.明确是否为纯文本
是:Reader(源) Writer(汇)
不是:InputStream(源) OutputStream(汇)
c.明确具体设备
源:File(硬盘) System.in(键盘) 数组(内存) Socket(网络)
汇:File(硬盘) System.out(控制台) 数组(内存) Socket(网络)
d.其他需求
是否需要转换 是:加转换流 InputStreamReader OutputStreamWriter
是否需要高效 是:加Buffer
代码示例:
//需求1:复制一个文本文件
//1.明确源和目的 源: InputStream Reader 汇: OutputStream Writer
//2.是否是纯文本 是 源:Reader 汇:Writer
//3.明确具体设备 源: 硬盘:File 汇:File
//4.需要高效吗 需要 加 buffer
BufferedReader bufr=new BufferedReader(new FileReader("F:\\a.txt"));
BufferedWriter bufw=new BufferedWriter(new FileWriter("F:\\a_copy.txt"));
//需求2:读取键盘录入信息,并写入到一个文件中
//是否为存文本 是 Reader Writer
//明确具体设备 源:键盘 System.in 汇:硬盘 File
//需要额外功能吗 需要 转换 将字节流转换成字符流 因为明确的源是 Reader 这样操作文本数据更便捷
//所以将已有字节流转换成字符流 使用字节-->字符 InputStreamReader
//还需要功能吗? 需要:想高效
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw=new BufferedWriter(new FileWriter("b.txt"));
//需求3:将一个文本文件数据显示在控制台上
//1.明确源和目的 源: InputStream Reader 汇:OutputStream Writer
//2.是否是纯文本文件 是 源:Reader 汇:Writer
//3.明确具体设备 源:File 汇:System.out
FileReader fr=new FileReader("c.txt");
OutputStream out=System.out;//PrintStream
//4.需要额外功能吗 需要 转换
FileReader fr=new FileReader("c.txt");
OutputStreamWriter osw=new OutputStreamWriter(System.out);
//5.需要其他功能吗 需要高效
BufferedReader bufr=new BufferedReader(new FileReader("c.txt"));
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));
//需求4:读取键盘录入数据,显示在控制台上
//1.明确源和目的 源:InputStream Reader 汇:OutputStream Writer
//2.是否为纯文本 是 源:Reader 汇:Writer
//3.明确设备 源:键盘 System.in 汇:控制台 System.out
//4.明确额外功能 需要转换,因为都是字节流,但操作的都是文本数据 所以使用字符流操作更便捷
InputStreamReader isr=new InputStreamReader(System.in);
OutputStreamWriter osw=new OutputStreamWriter(System.out);
//5.其他需求 高效
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));
6.File类
a.概述:该类将文件或文件夹封装成对象,方便文件与文件夹的属性信息进行操作。
代码示例:
//可以将一个已存在的,或不存在的文件或目录封装成file对象
File f1 = new File("F:\\a.txt");
File f2 = new File("F:\\","a.txt");
File f = new File("F:\\");
File f3 = new File(f,"a.txt");
File f4 = new File("F:"+System.getProperty("file.separator")+"a.txt");
b.常见功能:
代码示例:
获取:
File file = new File("F:\\1.mp3");
//获取文件名称
String name = file.getName();
//获取文件路径
String absPath = file.getAbsolutePath();//绝对路径
String path = file.getPath();//相对路径
//获取文件大小
long len = file.length();
//获取文件修改时间
long time = file.lastModified();
Date date = new Date(time);
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
String str_time = dateFormat.format(date);
创建和删除:
File file = new File("F:\\50.mp3");
//创建文件 如果文件不存在,则创建;如果文件存在,则不创建
boolean b = file.createNewFile();
//删除文件
boolean d = file.delete();
File dir = new File("F:\\folder");
//创建文件夹 如果文件夹不存在,则创建;如果文件夹存在,则不创建
boolean b1 = dir.mkdir();
//删除文件夹
boolean d1 = dir.delete();
File dirs = new File("F:\\1\\1.1\\1.1.1");
//创建多级文件夹
boolean b2 = dirs.mkdirs();
判断:
File f = new File("F:\\a.txt");
//判断文件是否存在
boolean b1 = f.exists();
//判断是否是文件
boolean b2 = f.isFile();
//判断是否是目录
boolean b3 = f.isDirectory();
重命名:
File f1 = new File("F:\\1.mp3");
File f2 = new File("F:\\1_rename.mp3");
//对文件重命名
f1.renameTo(f2);
系统根目录和容量获取:
//获取系统根目录
File[] files = File.listRoots();
for(File file : files){
System.out.println(file);
}
//容量获取
File file = new File("F:\\");
System.out.println("getFreeSpace:"+file.getFreeSpace());//空闲空间
System.out.println("getTotalSpace:"+file.getTotalSpace());//空间容量
System.out.println("getUsableSpace:"+file.getUsableSpace());//虚拟机可用空间
获取目录内容:
File file = new File("F:\\");
//获取文件目录下的文件和文件夹的名称
String[] names = file.list();
for(String name : names){
System.out.println(name);
}
过滤器:
class FilterByMp3 implements FilenameFilter{//实现FilenameFilter接口 按照文件名过滤
@Override
public boolean accept(File dir, String name) {
//按照 .MP3 后缀 进行文件过滤
return name.endsWith(".mp3");
}
}
File dir = new File("F:\\");
//将过滤后的文件添加到数组
String[] names = dir.list(new FilterByMp3());
for(String name : names){
System.out.println(name);
}
class FilterByHidden implements FileFilter {// 实现FileFilter接口 过滤隐藏文件
@Override
public boolean accept(File pathname) {
// 过滤隐藏文件
return pathname.isHidden();
}
}
File dir = new File("F:\\");
File[] files = dir.listFiles(new FilterByHidden());for(
File file:files)
{
System.out.println(file);
}
7.Properties集合
a.概述:表示属性集的集合
b.特点:集合中的键和值都是字符串类型;集合中的数据可以保存到流中,或从流中获取。
c.应用:该集合常用于操作以键值对形式存在的配置文件
d.常用功能:
代码示例:
//创建一个Properties集合
Properties prop = new Properties();
//存储元素
prop.setProperty("zhangsan", "30");
prop.setProperty("lisi", "18");
prop.setProperty("wangwu", "51");
prop.setProperty("zhaoliu", "26");
//修改元素
prop.setProperty("wangwu", "99");
//取出所有元素
Set<String> names = prop.stringPropertyNames();
for(String name : names){
String value = prop.getProperty(name);
System.out.println(name+":"+value);
}
e.list方法
代码示例:
// 创建一个Properties集合
Properties prop = new Properties();
// 存储元素
prop.setProperty("zhangsan", "30");
prop.setProperty("lisi", "18");
prop.setProperty("wangwu", "51");
prop.setProperty("zhaoliu", "26");
//list方法 将属性列表输出到指定的输出流
prop.list(System.out);
f.store方法
代码示例:
// 创建一个Properties集合
Properties prop = new Properties();
// 存储元素
prop.setProperty("zhangsan", "30");
prop.setProperty("lisi", "18");
prop.setProperty("wangwu", "51");
prop.setProperty("zhaoliu", "26");
//将这些集合中的字符串键值信息持久化存储到文件中,需要关联输出流
FileOutputStream fos = new FileOutputStream("F:\\info.txt");
//将集合数据存储到文件中,使用store 方法
prop.store(fos, "name");
g.load方法
代码示例:
Properties prop = new Properties();
// 集合中的数据来自于一个文件,必须保证该文件中的数据是键值对
// 使用读取流
FileReader fr = new FileReader("F:\\info.txt");
// 使用load方法 从输入流中读取属性列表
prop.load(fr);
// list方法 将属性列表输出到指定的输出流
prop.list(System.out);
h.修改配置信息
代码示例:
//读取这个文件
File file = new File("F:\\info.txt");
if(!file.exists()){
file.createNewFile();//如果文件不存在,则创建
}
//输入流关联文件
FileReader fr = new FileReader(file);
//创建集合,存储配置信息
Properties prop = new Properties();
//将流中的信息存储到集合中
prop.load(fr);
//修改配置信息
prop.setProperty("wangwu", "100");
//输出流关联文件
FileWriter fw = new FileWriter(file);
//将集合数据存储到文件中,使用store 方法
prop.store(fw, "");
fw.close();
fr.close();
8.打印流&序列流
a.打印流 PrintStream 和 PrintWriter:可以直接操作输入流和文件
代码示例:
/*
* PrintStream
* 1.提供了打印方法可以对多种数据类型值进行打印,并保持数据的表现形式
* 2.不抛出IOException
*
* 构造函数,接受三种类型的值
* 1.字符串路径
* 2.File对象
* 3.字节输出流
*/
PrintStream out = new PrintStream("F:\\print.txt");
out.write(97);//只写最低8位
out.print(97);//将97变成字符保持原样将数据打印到目的地
out.close();
/*
* PrintWriter:字符打印流
* 构造函数参数:
* 1.字符串路径
* 2.File对象
* 3.字节输出流
* 4.字符输出流
*/
BufferedReader bufr =new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out,true);
String line = null;
while((line=bufr.readLine())!=null) {
if("over".equals(line))
break;
out.println(line.toUpperCase());
// out.flush();
}
out.close();
bufr.close();
b.序列流:SequenceInputStream:对多个流进行合并
代码示例:
/*
* 需求:将 1.txt 2.txt 3.txt 文件中的数据合并到一个文件中
*/
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("F:\\1.txt"));
v.add(new FileInputStream("F:\\2.txt"));
v.add(new FileInputStream("F:\\3.txt"));
Enumeration<FileInputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("F:\\4.txt");
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1) {
fos.write(buf,0,len);
}
fos.close();
sis.close();
9.对象的序列化&对象的反序列化
a.ObjectOutputStream 对象序列化,将对象从堆内存存储到硬盘上。被序列化的对象必须实现Serializable接口
代码示例:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\obj.object"));
oos.writeObject(new Person("小强",30));
oos.close();
b.ObjectInputStream 对象反序列化,对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化
代码示例:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\obj.object"));
Person p = (Person)ois.readObject();
System.out.println(p.getName()+":"+p.getAge());
ois.close();
10.写入&读取
a.写入 RandomAccessFile
代码示例:
/*
* RandomAccessFile
* 特点:
* 该对象既能读,又能写
* 该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素
* 可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置
* 其实该对象就是将字节输入流和输出流进行封装
* 该对象的源或者目的只能是文件
*/
//如果文件不存在,则创建;如果文件存在,则不创建。
RandomAccessFile raf = new RandomAccessFile("F:\\ranacc.txt","rw");
raf.write("张三".getBytes());
raf.write(97);
raf.close();
11.管道流
a.概述:管道流是用来在多个线程之间进行信息传递的Java流
b.特点:
第一,管道流仅用于多个线程之间传递信息,若用在同一个线程中可能会造成死锁;
第二,管道流的输入输出是成对的,一个输出流只能对应一个输入流,使用构造函数或者connect函数进行连接;
第三,一对管道流包含一个缓冲区,其默认值为1024个字节,若要改变缓冲区大小,可以使用带有参数的构造函数;
第四,管道的读写操作是互相阻塞的,当缓冲区为空时,读操作阻塞;当缓冲区满时,写操作阻塞;
第五,管道依附于线程,因此若线程结束,则虽然管道流对象还在,仍然会报错“read dead end”;
第六,管道流的读取方法与普通流不同,只有输出流正确close时,输出流才能读到-1值。
代码示例:
public class PipedStream {
public static void main(String[] args) throws IOException {
PipedInputStream input = new PipedInputStream();
PipedOutputStream output = new PipedOutputStream();
input.connect(output);
new Thread(new Input(input)).start();
new Thread(new Output(output)).start();
}
}
class Input implements Runnable {
private PipedInputStream in;
Input(PipedInputStream in) {
this.in = in;
}
public void run() {
try {
byte[] buf = new byte[1024];
int len = in.read(buf);
String s = new String(buf, 0, len);
System.out.println("s=" + s);
in.close();
} catch (Exception e) {
}
}
}
class Output implements Runnable {
private PipedOutputStream out;
Output(PipedOutputStream out) {
this.out = out;
}
public void run() {
try {
Thread.sleep(5000);
out.write("pipe is coming..".getBytes());
} catch (Exception e) {
}
}
}
12.操作基本类型数据的流对象
a.概述:DataInputStream 和 DataOutputStream
代码示例:
private static void readData() throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("F:\\data.txt"));
String str = dis.readUTF();//以UTF-8修改版格式读取
System.out.println(str);
dis.close();
}
private static void writeData() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("F:\\data.txt"));
dos.writeUTF("你好");//以UTF-8修改版格式写入
dos.close();
}
13.操作数组的流
a.概述:ByteArrayInputStream 和 ByteArrayArrayOutputStream
代码示例:
ByteArrayInputStream bis = new ByteArrayInputStream("abcdef".getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int ch = 0;
while((ch=bis.read())!=-1){
bos.write(ch);
}
System.out.println(bos.toString());
}