一、概述
1、定义
在变量数组中和对象中存放的数据是暂时的,程序结束后就会丢失。为了能够永久的保存数据,需要将其存储在磁盘中。
java中的I/O技术可以将数据保存到本地,以达到永久保存的要求。
2、流
流是一组有序的序列,根据操作的类型,可分为输入流和输出流。
3、IO.体系
字节流的两个顶层父类:
1,InputStream 2,OutputStream.
字符流的两个顶层父类:
1,Reader 2,Writer
这些体系的子类都以父类名作为后缀。
而且子类名的前缀就是该对象的功能。
如图:
二、字符流
1、字符流的由来:
其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表。获取对应的文字。
在对这个文字进行操作。简单说:字节流+编码表
2、FileReader与FileWriter
a、FileWirter写入文本
- <span style="font-size:14px;">FileWriter fw = new FileWriter("d:\\jinfulin.txt");
- w.write("dfs");
- fw.close();</span>
b、FileReader读取文本
- <span style="font-size:14px;">FileReader fr = new FileReader("d:\\jinfulin.txt");
- int num1 = fr.read();//读取第一个字符
- int num2 = fr.read();//再次调用读取第二个字符(流特性嘛)
- System.out.println((char)num1);//打印,将数字转成字符
- System.out.println((char)num2);</span>
c、字符缓冲区
- <span style="font-size:14px;"> FileReader fr = new FileReader("demo.txt");
- /*
- * 使用read(char[])读取文本文件数据。
- *
- * 先创建字符数组。
- */
- char[] buf = new char[1024];
- int len = 0;
- while((len=fr.read(buf))!=-1){//没有字符了读到数据位-1
- System.out.println(new String(buf,0,len));
- }
- <span style="white-space:pre"> </span>fr.close();</span>
d、如何将一些文字存储到硬盘一个文件中?
3、字符流缓冲区对象--BufferedReader与BufferedWriter
三、字节流
- <span style="font-size:14px;"> private static void myStreamCopy() throws IOException {
- //定义输入输出流并加缓冲区
- BufferedOutputStream buffo = new BufferedOutputStream(new FileOutputStream("f:\\copy.mp3"));
- BufferedInputStream buffi = new BufferedInputStream(new FileInputStream("f:\\风吹麦浪.mp3"));
- //开始复制
- int ch = 0;
- while((ch = buffi.read()) != -1)
- {
- buffo.write(ch);
- }
- //关闭流
- buffo.close();
- buffi.close();
- }</span>
四、转换流
1、 转换流的由来:
2、转换流的应用:
InputStreamReader :字节到字符的桥梁。解码。OutputStreamWriter:字符到字节的桥梁。编码。
3、举例:将控制台上的文字存储到文件中
- <span style="font-size:14px;"><span style="white-space:pre"> </span>/*
- * 将控制台输入的文字存储到文件中。
- */
- public static void main(String[] args) throws IOException {
- BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
- BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("F:\\jinfulin.txt")));
- String line = null;
- while((line = bufr.readLine()) != null)
- {
- if("over".equals(line))
- break;
- bufw.write(line);
- System.out.println(line);
- }
- bufr.close();
- bufw.close();
- }
- </span>
源:InputStream Reader
目的:OutputStream Writer
源:是纯文本:Reader
---------否:InputStream
目的:是纯文本 Writer
------否:OutputStream
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socket流
1,是否需要高效(缓冲区);
2,转换。
六、File类
1、定义:
2、特点:
1)用来将文件或文件夹封装成对象2)方便于对文件与文件夹的属性信息进行操作
3)File类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变
4)File对象可以作为参数传递给流的构造函数
3、初始化:
- <span style="font-size:14px;">//可以将一个已存在的,或者不存在的文件或者目录封装成file对象。
- File f1 = new File("c:\\a.txt");
- File f2 = new File("c:\\","a.txt");
- File f = new File("c:\\");
- File f3 = new File(f,"a.txt");
- File f4 = new File("c:"+File.separator+"abc"+File.separator+"a.txt");</span>
4、 File对象的常见方法。
- <span style="font-size:14px;"><span style="white-space:pre"> </span>File file = new File("a.txt");
- String name = file.getName();//获取文件名(a.txt)
- String absPath = file.getAbsolutePath();//绝对路径。
- String path = file.getPath();//相对路径
- long len = file.length();//文件长度(大小)
- long time = file.lastModified();//最后修改时间</span>
b、创建于删除
- <span style="font-size:14px;">File dir = new File("f:\\a1\\22\\jin.txt");
- boolean b = dir.mkdir();//创建文件
- dir.mkdirs();//创建多级目录
- System.out.println(dir.delete());
- boolean b = file.createNewFile();//如果不存在就创建 </span>
- <span style="font-size:14px;"> boolean b = f.exists(); // 判断是否存在。
- System.out.println(f.isFile());//是否是文件
- System.out.println(f.isDirectory());//是否是一个目录</span>
d、重命名
- <span style="font-size:14px;"><span style="white-space:pre"> </span>File f1 = new File("c:\\kkk.mp3");
- File f2 = new File("d:\\ccc.mp3");
- boolean b = f1.renameTo(f2);
- System.out.println("ccc="+b);</span>
5、 拓展应用
- <span style="font-size:14px;"> String[] names = file.list();
- <span style="white-space:pre"> </span>if(names == null)//如果为空就返回,避免出现空指针异常
- <span style="white-space:pre"> </span>return;
- System.out.println(names.length);
- for(String name : names){
- System.out.println(name);
- }</span>
- <span style="font-size:14px;">public class DeleteAll {
- public static void main(String[] args) {
- File dir = new File("f:\\1234");
- // dir.delete();//直接删是删不掉的
- dirdelete(dir);
- }
- private static void dirdelete(File dir) {
- File[] files = dir.listFiles();
- if (files == null)
- return;
- for (File file : files) {
- if(file.isDirectory()){//如果是目录就递归
- dirdelete(file);
- }
- //不是目录就删掉
- System.out.println(file.getAbsolutePath() + "----"+ file.delete());
- }
- //最后再删掉根目录的文件夹(此时已经空了)
- System.out.println(dir.getAbsolutePath() + "----"+ dir.delete());
- }
- }</span>
七、Properties类
1、概述
Properties类并不属于IO包中的类,而是属于map集合,在前面map集合章节也有提到,不过由于该集合中数据用到流,在这里说更合适。
2、特点:
1,该集合中的键和值都是字符串类型。
2,集合中的数据可以保存到流中,或者从流获取。 通常该集合用于操作以键值对形式存在的配置文件。
3、举例
定义功能,获取一个应用程序运行的次数,如果超过5次,给出使用次数已到请注册的提示。并不要在运行程序。
- <span style="font-size:14px;">public static void getAppCount() throws IOException{
- //将配置文件封装成File对象。
- File confile = new File("count.properties");
- if(!confile.exists()){//健壮性判断
- confile.createNewFile();
- }
- //集合中的数据来自于一个文件。
- //注意;必须要保证该文件中的数据是键值对。
- //需要使用到读取流。
- FileInputStream fis = new FileInputStream(confile);
- Properties prop = new Properties();
- prop.load(fis);//集合中加载一个文件输入流
- //从集合中通过键获取次数。
- String value = prop.getProperty("time");
- //定义计数器。记录获取到的次数。
- int count =0;
- if(value!=null){
- count = Integer.parseInt(value);
- if(count>=5){
- throw new RuntimeException("使用次数已到,请注册,给钱!");
- }
- }
- count++;
- //将改变后的次数重新存储到集合中。
- //将集合中数据存储到文件中,使用store方法。
- prop.setProperty("time", count+"");
- FileOutputStream fos = new FileOutputStream(confile);
- prop.store(fos, "注释.....");
- fos.close();
- fis.close();
- }</span>
I
O也写作”I/O”,可理解为In和Out,即输入与输出,所以,IO体系的基本功能就是:读与写。
1.作用:读写设备上的数据,硬盘文件、内存、键盘、网络...
根据数据的走向,可分为:输入流、输出流
根据处理的数据类型,可分为:字节流、字符流
2.字节流与字符流
字节流可以处理所有类型的数据,如MP3、图片、文字、视频等。在读取时,读到一个字节就返回一个字节。在Java中对应的类都是”Stream”结尾。
字符流仅能够处理纯文本数据,如txt文本等。在读取时,读到一个或者多个字节,先查找指定的编码表,然后将查到的字符返回。在Java中对应的类都是”Reader”或者”Writer”结尾。
1.java.io包
Java.io包几乎包含了所有操作输入、输出需要的类。所有的这些流类代表了输入源和输出目标。
Java.io包流支持很多种格式,比如:基本类型、对象、本地化字符集等等。
一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。
Java 为I/O提供了强大而灵活的支持,使其更广泛的应用到文件传输和网络编程中。
2.读取控制台输出
Java控制台输出由System.in完成。
为了获得一个绑定到控制台的字符流,你可以把System.in包装在一个BufferedReader 对象中来创建一个字符流。
下面是创建BufferedReader的基本语法:
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
BufferedReader对象创建后,我们便可以使用read()方法从控制台读取一个字符,或者用readLine()方法读取一个字符串。
3.从控制台读取多字符输出
从BufferedReader对象读取一个字符要使用read()方法,它的语法如下:
int read( ) throws IOException
每次调用read()方法,它从输入流读取一个字符并把该字符作为整数值返回。 当流结束的时候返回-1。该方法抛出IOException。
3.从控制台读取字符串
从标准输入读取一个字符串需要使用BufferedReader的readLine()方法。
它的一般格式是:
String readLine( ) throws IOException
4.控制台输出
在此前已经介绍过,控制台的输出由 print( ) 和println( )完成。这些方法都由类PrintStream 定义,System.out是该类对象的一个引用。
PrintStream 继承了OutputStream类,并且实现了方法write()。这样,write()也可以用来往控制台写操作。
PrintStream 定义write()的最简单格式如下所示:
void write(int byteval)
该方法将byteval的低八位字节写到流中。
5.FileInputStream
该流用于从文件读取数据,它的对象可以用关键字new来创建。
有多种构造方法可用来创建对象。
可以使用字符串类型的文件名来创建一个输入流对象来读取文件:
InputStream f = new FileInputStream("C:/java/hello");
也可以使用一个文件对象来创建一个输入流对象来读取文件。我们首先得使用File()方法来创建一个文件对象:
File f = new File("C:/java/hello");
InputStream f = new FileInputStream(f);
创建了InputStream对象,就可以使用下面的方法来读取流或者进行其他的流操作。
序号 | 方法及描述 |
1 | public void close() throws IOException{} |
2 | protected void finalize()throws IOException {} |
3 | public int read(int r)throws IOException{} |
4 | public int read(byte[] r) throws IOException{} |
5 | public int available() throws IOException{} |
6.FileOutputStream
该类用来创建一个文件并向文件中写数据。
如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。
有两个构造方法可以用来创建FileOutputStream 对象。
使用字符串类型的文件名来创建一个输出流对象:
OutputStream f = new FileOutputStream("C:/java/hello")
也可以使用一个文件对象来创建一个输出流来写文件。我们首先得使用File()方法来创建一个文件对象:
File f = new File("C:/java/hello");
OutputStream f = new FileOutputStream(f);
创建OutputStream 对象完成后,就可以使用下面的方法来写入流或者进行其他的流操作。
序号 | 方法及描述 |
1 | public void close() throws IOException{} |
2 | protected void finalize()throws IOException {} |
3 | public void write(int w)throws IOException{} |
| public void write(byte[] w) 把指定数组中w.length长度的字节写到OutputStream中。
下面是一个演示InputStream和OutputStream用法的例子: import java.io.*;
public class fileStreamTest{
public static void main(String args[]){
try{ byte bWrite [] = {11,21,3,40,5}; OutputStream os = new FileOutputStream("test.txt"); for(int x=0; x < bWrite.length ; x++){ os.write( bWrite[x] ); // writes the bytes } os.close();
InputStream is = new FileInputStream("test.txt"); int size = is.available();
for(int i=0; i< size; i++){ System.out.print((char)is.read() + " "); } is.close(); }catch(IOException e){ System.out.print("Exception"); } } } 上面的程序首先创建文件test.txt,并把给定的数字以二进制形式写进该文件,同时输出到控制台上。 以上代码由于是二进制写入,可能存在乱码,你可以使用以下代码实例来解决乱码问题: //文件名 :fileStreamTest2.java import java.io.*;
public class fileStreamTest2{ public static void main(String[] args) throws IOException {
File f = new File("a.txt"); FileOutputStream fop = new FileOutputStream(f); // 构建FileOutputStream对象,文件不存在会自动新建
OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8"); // 构建OutputStreamWriter对象,参数可以指定编码,默认为操作系统默认编码,windows上是gbk
writer.append("中文输入"); // 写入到缓冲区
writer.append("\r\n"); //换行
writer.append("English"); // 刷新缓存冲,写入到文件,如果下面已经没有写入的内容了,直接close也会写入
writer.close(); //关闭写入流,同时会把缓冲区内容写入文件,所以上面的注释掉
fop.close(); // 关闭输出流,释放系统资源
FileInputStream fip = new FileInputStream(f); // 构建FileInputStream对象
InputStreamReader reader = new InputStreamReader(fip, "UTF-8"); // 构建InputStreamReader对象,编码与写入相同
StringBuffer sb = new StringBuffer(); while (reader.ready()) { sb.append((char) reader.read()); // 转成char加到StringBuffer对象中 } System.out.println(sb.toString()); reader.close(); // 关闭读取流
fip.close(); // 关闭输入流,释放系统资源
} }
|
7.Java中目录
1)创建目录
File类中有两个方法可以用来创建文件夹:
- mkdir( )方法创建一个文件夹,成功则返回true,失败则返回false。失败表明File对象指定的路径已经存在,或者由于整个路径还不存在,该文件夹不能被创建。
- mkdirs()方法创建一个文件夹和它的所有父文件夹。
下面的例子创建 "/tmp/user/java/bin"文件夹:
import java.io.File;
public class CreateDir {
public static void main(String args[]) {
String dirname = "/tmp/user/java/bin";
File d = new File(dirname);
// 现在创建目录
d.mkdirs();
}
}
编译并执行上面代码来创建目录"/tmp/user/java/bin"。
注意:Java在UNIX和Windows自动按约定分辨文件路径分隔符。如果你在Windows版本的Java中使用分隔符(/) ,路径依然能够被正确解析。
2)读取目录
一个目录其实就是一个File对象,它包含其他文件和文件夹。
如果创建一个File对象并且它是一个目录,那么调用isDirectory( )方法会返回true。
可以通过调用该对象上的list()方法,来提取它包含的文件和文件夹的列表。
下面展示的例子说明如何使用list()方法来检查一个文件夹中包含的内容:
import java.io.File;
public class DirList {
public static void main(String args[]) {
String dirname = "/tmp";
File f1 = new File(dirname);
if (f1.isDirectory()) {
System.out.println( "Directory of " + dirname);
String s[] = f1.list();
for (int i=0; i < s.length; i++) {
File f = new File(dirname + "/" + s[i]);
if (f.isDirectory()) {
System.out.println(s[i] + " is a directory");
} else {
System.out.println(s[i] + " is a file");
}
}
} else {
System.out.println(dirname + " is not a directory");
}
}
}
8.File类的使用
I/O包中的其他类
一、对象流(ObjectInputStream/ObjectOutputStream)
1、概述
将堆内存中的对象存入硬盘,保留对象中的数据,称之为对象的持久化(或序列化)。使用到的两个类:ObjectInputStream和ObjectOutputStream
被操作对象需要实现Serializable
2、特点
对象的序列化和反序列化。-----------writeObject readObject
Serializable标记接口--------------------用于给被序列化的类家里ID号
关键字:transient------------------------短暂的,static和transient的对象都不写入
transient:非静态数据不想被序列化可以使用这个关键字修饰。
3、举例:
- public static void readObj() throws IOException, ClassNotFoundException {
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object"));
- //对象的反序列化。
- Person p = (Person)ois.readObject();
- System.out.println(p.getName()+":"+p.getAge());
- ois.close();
- }
- public static void writeObj() throws IOException, IOException {
- ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
- //对象序列化。 被序列化的对象必须实现Serializable接口。
- oos.writeObject(new Person("小强",30));
- oos.close();
- }
二、RandomAccessFile随机访问文件:
一、概述
RandomAccessFile此类的实例支持对随机访问文件的读取和写入,自身具备读写方法。
2、特点:
**既可读取,又可以写入。
**内部维护了一个大型的byte数组,通过对数组的操作完成读取和写入。
**通过getFilePointer方法获取指针的位置,还可以通过seek方法设置指针的位置。
**该对象的内容应该封装了字节输入流和字节输出流。
**该对象只能操作文件。
通过seek方法操作指针,可以从这个数组中的任意位置上进行读和写
可以完成对数据的修改。
但是要注意:数据必须有规律。
3、举例:
- //定义一个随机访问文件,可读可写
- RandomAccessFile raf = new RandomAccessFile("ranacc.txt","rw");
- raf.write("张三".getBytes());//写入内容
- raf.writeInt(97);
- <span style="white-space:pre"> </span>//通过seek设置指针的位置。
- <span style="white-space:pre"> </span>RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "r");
- raf.seek(1*8);//随机的读取。只要指定指针的位置即可。
- byte[] buf = new byte[4];
- raf.read(buf);
三、管道流:
1、概述
管道流包括PipedOutputStream和PipedInputStream ,且需要和多线程技术相结合,不知道多线程的知识大家是否还记得。看例子来回忆。
2、举例
四、DataInputStream与ByteArrayInputStream
1、用操作基本数据类型值的对象。
DataInputStream
DataOutputStream
这两个读写对象,可用于操作基本数据类型的流对象,包含读写各种基本数据类型的方法。
2、设备是内存的流对象。
ByteArrayInputStream ByteArrayOutputStream
CharArrayReader CharArrayWriter
a、这个对象并没有调用底层资源,所以不用关闭流资源,即使关闭后,仍可调用。
b、内部包含缓冲区,相当于以内存作为流操作源和目的,不会产生任何IO异常。
c、将一个数字写入另一个数组(都是在内存中操作的)