1 流概述
2 File类
package captain;
import java.io.File;
//文件的创建和删除演示
public class FileDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
File file = new File("word.txt");//创建文件对象,并不是直接在磁盘上直接创建了一个文件
if(file.exists()){//判断上面指定路径下是否已存在同名的文件
file.delete();//若存在,则删除该文件
System.out.println("文件已删除");
}
else{
try{//捕捉异常,文件可能创建不成功,引发IOException
file.createNewFile();//在磁盘上创建文件
System.out.println("文件已创建");
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
package captain;
import java.io.File;
//获取文件信息演示
public class FileDemo2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
File file = new File("word.txt");//创建文件对象,并不是直接在磁盘上直接创建了一个文件
if(file.exists()){//判断上面指定路径下是否已存在同名的文件
String name = file.getName();//获取文件名
long length = file.length();//获取文件的字节长度
boolean hidden = file.isHidden();//判断文件是否为隐藏文件
System.out.println("文件名称:" + name);
System.out.println("文件长度:" + length);
System.out.println("该文件是否为隐藏文件:" + hidden);
}
else{
System.out.println("该文件不存在");
}
}
}
3 文件输入输出流
(1)FileInputStream类和FileOutputStream类
package captain;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//FileInputStream类和FileOutputStream类演示。
public class FileIODemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
File file = new File("word.txt");// 创建文件对象,并不是直接在磁盘上直接创建了一个文件。
// 使用FileOutputStream类创建文件输出流。
FileOutputStream fos = null;// fos流对象需要在try块外面声明里面创建。
try {// 捕捉异常,可能发生IOException。
fos = new FileOutputStream(file);
byte[] b1 = "I am a String !".getBytes();// 将字符串转化为字节数组。
fos.write(b1);// 将字节数组中的数据作为输出流的内容。
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {// 捕捉异常,关闭文件流的时候也可能发生IOException。
fos.close();// 关闭文件输出流,实际上执行这个方法时先调用了fos.flush()方法刷新缓冲(将缓冲中的数据写到文件中,再清空缓冲)。该语句需放在finally块中。
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// 使用FileInputStream类创建文件输入流。
FileInputStream fis = null;// fis流对象需要在try块外面声明里面创建。
try {// 捕捉异常,可能发生IOException
fis = new FileInputStream(file);
byte[] b2 = new byte[1024];// 创建一个字节数组
int len = fis.read(b2);// 将输入流中的内容读到字节数组中,返回读到的字节长度。
System.out.println("文件中的信息是:" + new String(b2, 0, len));// 以字符串的形式输出读到的信息。
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {// 捕捉异常,关闭文件流的时候也可能发生IOException。
fis.close();// 关闭文件输入流,输入流没有flush()方法。该语句需放在finally块中。
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
(2)FileReader类和FileWriter类
package captain;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//FileReader类和FileWriter类演示。
public class FileRWDemo {
public static void main(String[] args) throws IOException {//抛出异常。也可以直接捕捉。
// TODO Auto-generated method stub
/*这里直接使用文件名作为文件流构造函数的参数,若指定路径下没有与该文件同名的文件,
*则会自动创建一个新的该文件,若存在与该文件同名的文件,则会覆盖原有的文件。
*也可以另外使用File类来创建文件对象,再通过其方法创建文件,这样麻烦一些。
*/
FileWriter fw = new FileWriter("test.txt");
fw.write("abcdef");//直接将字符串作为输出流的内容。也可以将字符数组作为输出流的内容。
fw.close();//关闭文件输出流,实际上执行这个方法时先调用了fw.flush()方法刷新缓冲(将缓冲中的数据写到文件中,再清空缓冲)。
FileReader fr = new FileReader("test.txt");
int ch = 0;
//无参的read()方法,一次读取一个字符,返回值为读到字符对应的Unicode码值。也可以将字符数组作为read方法的参数,一次读取多个字符,返回值为读到的字符的个数。
while((ch = fr.read())!=-1){//当读到文件末尾(返回值为-1)时,停止循环读取。
System.out.println((char)ch);//将Unicode码值强制转化为字符输出。
}
fr.close();//关闭文件输入流,输入流没有flush()方法。
}
}
4 带缓存的输入输出流
(1)BufferedInputStream类和BufferedOutputStream类
(2)BufferedReader类和BufferedWriter类
package captain;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
//BufferedReader类和BufferedWriter类演示。
public class BufferedRWDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] str = { "好久不见", "最新好吗", "常联系" };// 定义字符串数组
File file = new File("bufText.txt");// 创建文件对象
FileWriter fw = null;// 声明FileWriter类流对象
BufferedWriter bw = null;// 声明BufferedWriter类对象
try {
fw = new FileWriter(file);// 创建FileWriter类流对象
bw = new BufferedWriter(fw);// 创建BufferedWriter类对象,该类其实是FileWriter类的装饰类
for (int k = 0; k < str.length; k++) {// 循环遍历数组
bw.write(str[k]);// 将字符串数组中的元素写入到磁盘文件中
bw.newLine();// 将数组中的单个元素以单行的形式写入文件
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bw != null) {
try {
/* 将BufferedWriter流关闭,实际上执行这个方法时先调用了bw.flush()方法
* 刷新缓冲(将缓冲中的数据写到文件中,再清空缓冲)。另外,装饰类BufferedWriter
* 在关闭流的时候,其内部其实调用了被装饰类FileWriter的close()方法。
* 如果习惯依次关闭各层流的话,必须按照后开的流先关闭这一顺序来依次关闭。
* */
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
FileReader fr = null;// 声明FileReader类流对象
BufferedReader br = null;// 声明BufferedReader类对象
try {
fr = new FileReader(file);// 创建FileReader类流对象
br = new BufferedReader(fr);// 创建BufferedReader类对象,该类其实是FileReader类的装饰类
String s = null;
int i = 0;
while ((s = br.readLine()) != null) {// 当readLine()方法返回null时停止循环
i++;
System.out.println("第" + i + "行:" + s);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
/* 将BufferedReader流关闭,输入流没有flush()方法。另外,装饰类BufferedReader
* 在关闭流的时候,其内部其实调用了被装饰类FileReader的close()方法。
* 如果习惯依次关闭各层流的话,必须按照后开的流先关闭这一顺序来依次关闭。
* */
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
5 转换流
package captain;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
//InputStreamReader类和OutputStreamWriter类这两个转换流作为字节流和字符流之间的桥梁演示。
public class IROWDemo {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
InputStream is = System.in;//键盘输入的流为字节流
InputStreamReader isr = new InputStreamReader(is);//将字节流转换(解码)为字符流
BufferedReader br = new BufferedReader(isr);//将字符流装饰成带缓冲区的字符流
OutputStream os = System.out;//控制台输出的流为字节流
OutputStreamWriter osw = new OutputStreamWriter(os);//将字符流转换(编码)为字节流
BufferedWriter bw = new BufferedWriter(osw);//将字符流装饰成带缓冲区的字符流
String str = null;
while((str=br.readLine())!=null){
if("over".equals(str))//键盘输入结束标志
break;
//System.out.println(str);//可直接输出
bw.write(str);//写一行
bw.newLine();//换行
bw.flush();//写一行后就刷新
}
br.close();//关闭流
bw.close();//关闭流
}
}
6 对象的序列化和反序列化
package captain;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
//对象的序列化和反序列化演示,Serializable接口、ObjectOutputStream类、ObjectInputStream类及transient关键字。
public class ObjectIODemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// TODO Auto-generated method stub
//对象的序列化
FileOutputStream fos = new FileOutputStream("obj.object");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(new Student("zhangsan", 23));//将对象写到文件中
oos.close();
//对象的反序列化
FileInputStream fis = new FileInputStream("obj.object");
ObjectInputStream ois = new ObjectInputStream(fis);
Student s = (Student)ois.readObject();//从文件中读对象,会引发ClassNotFoundException
System.out.println(s.getName()+":"+s.getAge());
ois.close();
}
}
//被序列化和被反序列化的类,必须实现java.io.Serializable接口
class Student implements Serializable{
private static final long serialVersionUID = 1L;//使用默认序列化版本号,给类加ID
private transient String name;//使用transient关键字,瞬态的成员变量不会被序列化
private int age;
Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
7 随机访问文件
8 管道输入输出流
package captain;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
//管道输入输出流演示,PipedInputStream类、PipedOutputStream类及多线程。
public class PipedIODemo {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
PipedInputStream pis = new PipedInputStream();//管道输入流
PipedOutputStream pos = new PipedOutputStream();//管道输出流
pis.connect(pos);//连接管道输入输出流,抛出IOException
new Thread(new Input(pis)).start();//启动管道输入流线程
new Thread(new Output(pos)).start();//启动管道输出流线程
}
}
//输出,实现Runnable接口
class Output implements Runnable{
private PipedOutputStream pos;//管道输出流
Output(PipedOutputStream pos){
this.pos = pos;
}
public void run() {
try {//注意run()方法内的异常不能抛出只能捕捉。
pos.write("hi,Pipe is coming !".getBytes());
pos.close();//关闭管道流
} catch (IOException e) {
e.printStackTrace();
}
}
}
//输入,实现Runnable接口
class Input implements Runnable{
private PipedInputStream pis;//管道输入流
Input(PipedInputStream pis){
this.pis = pis;
}
public void run() {
try {//注意run()方法内的异常不能抛出只能捕捉。
byte[] b = new byte[1024];
int len = pis.read(b);
String str = new String(b,0,len);
System.out.println(str);
pis.close();//关闭管道流
} catch (IOException e) {
e.printStackTrace();
}
}
}
9 数据输入输出流
数据输出流DataOutputStream允许应用程序以适当方式将基本Java数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。 数据输入流DataInputStream允许应用程序以与机器无关方式从底层输入流中读取基本Java数据类型。数据输入输出流的代码示例如下。
package captain;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//数据输入输出流演示,DataOutputStream类和DataInputStream类。
public class DataIODemo {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
FileOutputStream fos = new FileOutputStream("data.txt");
DataOutputStream dos = new DataOutputStream(fos);//数据输出流
dos.writeUTF("你好");//以UTF修改版的编码方式写
dos.close();//关闭数据输出流
FileInputStream fis = new FileInputStream("data.txt");
DataInputStream dis = new DataInputStream(fis);//数据输入流
String str = dis.readUTF();//以UTF修改版的编码方式读
System.out.println(str);
dis.close();//关闭数据输入流
}
}
10 字节数组、字符数组及字符串输入输出流
ByteArrayInputStream包含一个内部缓冲区(字节数组),该缓冲区包含从流中读取的字节,内部计数器跟踪read方法要提供的下一个字节。ByteArrayOutputStream实现了一个输出流,其中的数据被写入一个byte数组,缓冲区会随着数据的不断写入而自动增长,可使用 toByteArray() 和 toString() 获取数据。ByteArrayInputStream流和ByteArrayOutputStream流不需要被关闭,其中也不会引发IOException,因为这两个对象都不会操作类似于硬盘这样的系统底层资源,只涉及到内存。字符数组输入输出流CharArrayReader和CharArrayWriter、字符串输入输出流StringReader和StringWriter类似于字节数组输入输出流。字节数组输入输出流的代码示例如下。
package captain;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
//字节数组输入输出流演示,ByteArrayInputStream类和ByteArrayOutputStream类。
public class ByteArrayIODemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
ByteArrayInputStream bais = new ByteArrayInputStream("字节数组流".getBytes());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int ch = 0;
while((ch=bais.read())!=-1){//读字节
baos.write(ch);//写字节
}
System.out.println(baos.toString());//通过字节输出流的toString()方法获取数据
}
}
11 字符编码
除了Java I/O流中的InputStreamReader和OutputStreamWriter这两个转换流可以涉及到字符编码外,字符编码在很多地方也很常见。英文字符的编码方式通常为ASCII(1个字节的7位),欧洲国家文字字符的编码方式通常为ISO8859-1(1个字节的8位),中文简体字符的编码方式通常为GBK(2个字节)。为了统一各国文字字符的编码方式就有了Unicode(所有国家文字都以2个字节编码)编码方式,而常用的UTF-8(1-3个字节编码,其中的中文以3个字节编码)编码方式是一种针对Unicode编码方式的可变长度编码。中文简体字符编码解码的简单演示如下。
package captain;
import java.io.UnsupportedEncodingException;
//字符的编码解码简单演示。字符串转化为字节数组是一种编码,反之是一种解码。
public class EncodeDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
// TODO Auto-generated method stub
String str = "字符编码解码";
//编码,Windows系统中文简体的默认编码表为gbk,也可以使用其他编码表如utf-8
//byte[] b = str.getBytes();
byte[] b = str.getBytes("utf-8");//抛出UnsupportedEncodingException
//解码,Windows系统中文简体的默认解码方式为gbk,若编码时使用的是其他编码表,需要使用该编码表来解码
//String s = new String(b);
String s = new String(b,"utf-8");//抛出UnsupportedEncodingException
System.out.println(s);
}
}