File类
File类是IO包中唯一代表磁盘文件本事信息的类,而不是文件中的内容。定义了与平台无关的方法来操作文件。
Java中的目录被当作一种特殊的文件使用,list方法可以返回目录中的所有子目录和文件名。
在Unix下的路径分隔符(/),在Dos下的路径分隔符(/),Java可以正确处理。
/**
* 判断某个文件是否存在,存在则删除,不存在则创建。
*/
import java.io.*;
import java.util.Date;
public class FileTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
File f = new File(".//1.txt");
if(f.exists())
{
f.delete();
System.out.println("delete");
}
else
{
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("File name:"+f.getName());
System.out.println("File path:"+f.getPath());
System.out.println("File abs path:"+f.getAbsolutePath());
System.out.println("File Parent:"+f.getParent());
System.out.println(f.exists()?"exists":"not exist");
System.out.println(f.canRead()?"read":"not read");
System.out.println(f.isDirectory()?"directory":"not d");
System.out.println("File last modified:"+new Date(f.lastModified()));
}
}
}
************************************************************************************************
RandomAccessFile类
提供了众多文件访问方法,支持“随机访问”方式,在随机(相对顺序而言)读写等长记录格式的文件时有很大的优势。
仅限于操作文件,不能访问其他的IO设备,如网络,内存映像等。
两种构造方法:
new RandomAccessFile(f,"rw");//读写方式
new RandomAccessFile(f,"r");//只读方式
/**
* 写入员工信息,含有姓名和年龄两个字段,然后按照213的先后顺序读取员工信息。
*/
//Employee
public class Employee {
public String name = null;
public int age = 0;
public static final int LEN = 8;
public Employee(String name, int age) {
// TODO Auto-generated constructor stub
if(name.length() > LEN)
{
name = name.substring(0,LEN);
}
else
{
while(name.length() < LEN)
{
name +="/u0000";
}
}
this.name = name;
this.age = age;
}
}
//RandomFileTest
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomFileTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Employee e1 = new Employee("zhangsan",23);
Employee e2 = new Employee("lisi",24);
Employee e3 = new Employee("王五",285);
RandomAccessFile ra;
ra = new RandomAccessFile("employee.txt", "rw");
//ra.write(e1.name.getBytes());
ra.writeChars(e1.name);
ra.write(e1.age);
//ra.write(e2.name.getBytes());
ra.writeChars(e2.name);
ra.write(e2.age);
//ra.write(e3.name.getBytes());
ra.writeChars(e3.name);
ra.writeInt(e3.age);
ra.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
//int len = 0;
//byte[] buf = new byte[Employee.LEN];
String strName = "";
RandomAccessFile raf = new RandomAccessFile("employee.txt", "r");
raf.skipBytes(Employee.LEN*2+1);
//len = raf.read(buf);
//strName = new String(buf,0,len);
strName = "";
for (int i = 0; i < Employee.LEN; i++) {
strName += raf.readChar();
}
System.out.println(strName+":"+raf.read());
raf.seek(0);
//len = raf.read(buf);
//strName = new String(buf,0,len);
strName = "";
for (int i = 0; i < Employee.LEN; i++) {
strName += raf.readChar();
}
System.out.println(strName+":"+raf.read());
raf.skipBytes(Employee.LEN*2+1);
//len = raf.read(buf);
//strName = new String(buf,0,len);
strName = "";
for (int i = 0; i < Employee.LEN; i++) {
strName += raf.readChar();
}
System.out.println(strName.trim()+":"+raf.readInt());
raf.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
********************************************************************************
各种节点流类
理解流的概念
流是字节序列的抽象概念
文件是数据的静态存储形式,而流是指数据传输时的形态。
流类分为两大类:节点流类和过滤流类(也叫处理流类)。
InputStream与OutputStream类
InputStream类
程序可以从中连续读取字节的对象叫输入流,在Java中,用InputStream类来描述所有输入流的抽象概念。
int read()读不到会阻塞,只有有数据时开始读取,读取的值返回到int类型(int的最低8位<0-255>),读取结束时返回-1
int read(byte[] b)返回值是实际读取到的字节数,读取的值存储到b内。
int read(byte[] b,int off开始,int len长度)返回值是实际读取到的字节数,读取len长度的值从off开始存储到b内。
long skip(long n)跳过几个n去读取
int available()检查流中是否有数据可读
void mark(int readlimit)从建立标记的位置开始,最多还可以读取多少的字节的内容
void reset()回到标记处
boolean markSupported()是否支持mark方法
void close()关闭
OutputStream类
程序可以向其中连续写入字节的对象叫输出流,在Java中,用OutputStream类来描述所有输出流的抽象概念。
void write(int b)
void write(byte[] b)
void write(byte[] b,int off,int len)
void flush()刷新内存缓冲区中的内容
void close()关闭
FileInputStream与FileOutputStream类
分别用来创建磁盘文件的输入流和输出流对象,通过它们的构造函数来指定文件路径和文件名。
创建FileInputStream时,指定的文件应当是存在和刻度的。创建FileOutputStream时,如果存在,源文件内容将被覆盖清楚。
对同一磁盘文件创建FileInputStream对象的两种方式:
(1)FileInputStream inOne = new FileInputStream("hello.test");
(2)File f = new File("hello.test");//先对文件进行分析
FileInputStream inTwo = new FileInputStream(f);
创建FileOutputStream实例对象时,可以指定还不存在的文件名,不能指定一个已被其他程序打开了的文件。
/**
* 用FileOutputStream类向文件中写入一个串字符,然后用FileInputStream类读出写入的内容。
*/
import java.io.*;
public class FileSream {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
FileOutputStream out = new FileOutputStream("hello.txt");
out.write("www.it315.org".getBytes());
out.close();
byte[] buf = new byte[1024];
File f = new File("hello.txt");
FileInputStream in = new FileInputStream(f);
int len = in.read(buf);
System.out.println(new String(buf,0,len));
in.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Reader与Writer类 (所有字符流类的抽象基类,用于简化对字符串的输入输出编程,即用于读写文本数据。)
/**
* 用FileWriter类向文件中写入一个串字符,然后用FileReader读出写入的内容。
*/
import java.io.*;
public class FileSream2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
FileWriter out = new FileWriter("hello2.txt");
out.write("www.it315.org");
out.close();
char[] buf = new char[1024];
FileReader in = new FileReader("hello2.txt");
int len = in.read(buf);
System.out.println(new String(buf,0,len));
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
PipedInputStream与PipedOutputStream类 (用于在应用程序中的创建管道通信)
/**
* 线程间通信
*/
//Sender.java
import java.io.*;
public class Sender extends Thread {
private PipedOutputStream out = new PipedOutputStream();
public PipedOutputStream getOutputStream()
{
return out;
}
public void run()
{
String strInfo = new String("hello,receiver");
try {
out.write(strInfo.getBytes());
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//Receiver.java
import java.io.*;
public class Receiver extends Thread {
private PipedInputStream in = new PipedInputStream();
public PipedInputStream getInputStream()
{
return in;
}
public void run()
{
byte[] buf = new byte[1024];
try {
int len = in.read(buf);
System.out.println("the following message comes from sender:/n"+
new String(buf,0,len));
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//PipedStreamTest.java
import java.io.*;
public class PipedStreamTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Sender t1 = new Sender();//发送
Receiver t2 = new Receiver();//接收
PipedOutputStream out = t1.getOutputStream();//读out
PipedInputStream in = t2.getInputStream();//写in
try {
out.connect(in);//连通输入输出管道
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t1.start();
t2.start();
}
}
PipedWriter和PipedReader类(用于处理字符文本的管道通信)
使用管道流类,可以实现各个程序模块之间的松耦合通信。(强内聚弱耦合)
ByteArrayInputStream与ByteArrayOutputStream类
用于以IO流的方式来完成对字节数组内容的读写,来支持类似内存虚拟文件或者内存映像文件的功能。
ByteArrayInputStream两个构造函数:读
ByteArrayInputStream(byte[] buf)字节数组buf
ByteArrayInputStream(byte[] buf,int offset,int length)
ByteArrayOutputStream两个构造函数:写
ByteArrayOutputStream() 会使用32个字节的缓冲区,会自动增长
ByteArrayOutputStream(int) 会根据int创建缓冲区,会自动增长
/**
* 将一个字符串中的所有字符转换成大写
*/
import java.io.*;
public class ByteArrayTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
String tmp = "qwertyuiopasdfghjklzxcvbnm";
byte[] src = tmp.getBytes();
ByteArrayInputStream input = new ByteArrayInputStream(src);
ByteArrayOutputStream output = new ByteArrayOutputStream();
transform(input,output);
byte[] result = output.toByteArray();
System.out.println(new String(result));
}
public static void transform(InputStream in,OutputStream out)
{
int ch;
try {
while((ch = in.read()) != -1)
{
int upperCh = Character.toUpperCase((char)ch);
out.write(upperCh);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
StringReader类和StringWriter类来以字符IO流的方式处理字符串
重视IO程序代码的复用性
System.in连接到键盘,是InputStream类型的实例对象
System.out连接到显示器,是PrintStream类的实例对象
不管各种底层物理设备用什么方式实现数据的终止点,InputStream的read方法总是返回-1来表示输入流结束。
在Windows下,按下Ctrl+Z组合键可以产生键盘输入流的结束标记,在linux下,则是按下Ctrl+D组合键来产生键盘输入流的结束标记。
/**
* 改写上一个函数,键盘输入的内容转换成大写,输出到屏幕上
*/
transform(System.in,System.out);
********************************************************************************
字符编码
中文字符的GB2312码、UTF-8码、Unicode码 ,在记事本程序中用不同的编码
********************************************************************************
各种过滤流与包装类
包装类的概念与作用
程序→包装流类(方法ABC)→节点流类(方法1)→目录
BufferedInputStream与BufferedOutputStream类
缓冲区为I/O流增加了内存缓冲区,增加缓冲区有两个基本目的:
-允许Java程序一次不只操作一个字节,提高程序性能。
-由于有了缓冲区,使得在流上执行skip、mark和reset方法都成为可能。
BufferedInputStream两个构造函数:
-BufferedInputStream(InputStream in) 32个字节缓冲区
-BufferedInputStream(InputStream in,int size) size字节缓冲区(处理器处理位数的倍数)
BufferedOutputStream两个构造函数:
-BufferedOutputStream(OutputStream out)
-BufferedOutputStream(OutputStream out,int size)
BufferedReader和BufferedWriter类(字符缓冲)
.readLine可以一次读取一行文本,newLine可以向字符流中写入不同操作系统下的换行符
DataInputStream与DataOutputStream类
DataOutputStream类提供了三个写入字符串的方法:
-public final void writeBytes(String s) s的低字节写入到目标
-public final void writeChars(String s) s的两个字节写入到目标
-public final void writeUTF(String str) str按照UTF编码写入到目标
DataInputStream类中有一个readUTF方法,没有readBytes和readChars方法
/**
* 程序使用的流栈:程序→FileOutputStream→BufferedOutputStream→DataOutputStream↘
* ↖DataInputStream←BufferedInputStream←FileInputStream←文件
*/
import java.io.*;
public class DatastreamTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
FileOutputStream fos = new FileOutputStream("count.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
DataOutputStream dos = new DataOutputStream(bos);
dos.writeUTF("ab中国");
dos.writeBytes("ab中国");
dos.writeChars("ab中国");
dos.close();
FileInputStream fis = new FileInputStream("count.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
System.out.println(dis.readUTF());
byte[] buf = new byte[1024];
int len = dis.read(buf);
System.out.println(new String(buf,0,len));
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
PrintStream类
提供了一系列的print和println方法,可以将基本数据类型的数据格式化成字符串输出。
PrintStream三个构造函数:
-PrintStream(OutputStream out)
-PrintStream(OutputStream out,boolean autoflush) 是否自动刷新缓冲区
-PrintStream(OutputStream out,boolean autoflush,String encoding) 指定字符集编码
与PrintStream对应的PrintWriter类,即使遇到了文本换行标识符(/n),PrintWriter类也不会自动清空缓冲区。
PrintWriter的println方法能根据操作系统的不同而生产相应的文本换行符。(Windows:“/r/n”;Linux:“/n”)
ObjectInputStream与ObjectOutputStream类
这两个包装类用于从底层输入流中读取对象类型的数据和将对象类型的数据写入到底层输入流。
读写对象必须实现Serializable接口。对象中的transient和static类型的成员变量不会被读取和写入。
/**
* 创建了一个可序列化的学生对象,并用ObjectOutputStream类把它存储到一个文件中,然后再用ObjectInputStream类把存储的数据读取到一个学生对象中,即恢复保存的学生对象。
*/
//Student
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
int id;
String name;
int age;
String department;
public Student(int id,String name,int age,String department)
{
this.id = id;
this.name = name;
this.age = age;
this.department = department;
}
}
//Serialization
import java.io.*;
public class Serialization {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student stu1 = new Student(19,"zhangsan",25,"huaxue");
Student stu2 = new Student(20,"lisi",23,"wuli");
try {
FileOutputStream fos = new FileOutputStream("student.txt");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(stu1);
os.writeObject(stu2);
os.close();
FileInputStream fis = new FileInputStream("student.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
Student stu3 =(Student)ois.readObject();
Student stu4 =(Student)ois.readObject();
ois.close();
System.out.println("sru1ID:"+stu3.id);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
字节流与字符流的转换
InputStreamReader可以将一个字节流中的字节解码成字符后读取;
OutputStreamWriter将字符编码成字节后写入到一个字节流中。
InputStreamReader的两个主要的构造函数:
-InputStreamReader(InputStream in)
-InputStreamReader(InputStream in,String CharsetName)
OutputStreamWriter的两个主要的构造函数:
-OutputStreamWriter(OutputStream out)
-OutputStreamWriter(OutputStream out,String CharsetName)
避免频繁地在字符与字节间进行转换,最好不要直接使用InputStreamReader和OutputStreamWriter,应尽量使用BufferedWriter类包装OutputStreamWriter类,用BufferedReader类包装WriterStreamReader。
*********************************************************************************************
IO的应用
Java程序与其它进程的数据通信
在java程序中可以用Process类的实例对象来表示子进程,子进程的标准输入和输出不再连接到键盘和显示器,而是以管道流的形式连接到父进程的一个输出流和输入流对象上。
调用Process类的getOutputStream和getInputStream方法可以获得连接到子进程的输出流和输入流对象。
/**
* 在TestInOut类中启动java.exe命令执行另外一个MyTest类。TestInOut和MyTest通过进程间的管道相互传递数据。
*/
//TestInOut.java
import java.io.*;
public class TestInOut implements Runnable {
Process p = null;
public TestInOut(){
try {
p = Runtime.getRuntime().exec("java MyTest");
new Thread(this).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
TestInOut tio = new TestInOut();
tio.send();
}
public void run() {
// TODO Auto-generated method stub
try {
int count = 0;
InputStream in = p.getInputStream();
BufferedReader bfr = new BufferedReader(new InputStreamReader(in));
while(true)
{
//System.out.println("run:"+ ++count);
String strLine = bfr.readLine();
if(strLine == null)
{
return;
}
else
{
System.out.println(strLine);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void send(){
try {
int count = 0;
OutputStream ops = p.getOutputStream();
while(true)
{
//System.out.println("send:"+ ++count);
ops.write("help/r/n".getBytes());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//MyTest.java
import java.io.*;
public class MyTest {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
int mytestcount = 0;
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
//System.out.println("MyTest:" + ++mytestcount);
String strLine = bfr.readLine();
if(strLine == null)
{
return;
}
else
{
System.out.println("hi:"+strLine);
}
}
}
}
字节输入流类
字节输出流类
字符输入流类
字符输出流类
Decorator设计模式
在程序中用一个对象(the Decorators)包装另外的一个对象,这是一种被称为
Decorator的设计模式。
如果要设计自己的IO包装类,这个类需要继承以FilterXXX命名的类,例如,设计一对
输入输出包装类:RecordInputStream和RecordOutputStream,来完成从数据库文件中读取记录
和往数据库文件中写入记录。
Exception类从Throwable类继承的三个printStackTrace方法的定义如下:
-public void printStackTrace() //异常详细信息打印到屏幕
-public void printStackTrace(PrintStream s) //异常详细信息打印到s
-public void printStackTrace(PrintWriter s) //异常详细信息打印到s
/**
* 该如何把printStackTrace方法打出的详细异常信息存储到一个字符串中?
*/
import java.io.*;
public class TestPrintWriter {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
throw new Exception("test");
} catch (Exception e) {
// TODO Auto-generated catch block
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
System.out.println(sw.toString());
System.out.println(e.getMessage());
}
}
}