1 File类
是IO包中唯一代表磁盘文件本身信息的类,而不是文件的内容
File类定义了一些与平台无关的方法来操纵文件(创建,删除,重命名文件)
Java目录被当做一种特殊的文件使用,list方法可以返回目录中所有的子目录和文件名
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class FileTest {
public static void main(String args[]){
File f = new File("C://Users//姜康 //Desktop//java//2.txt");
if(f.exists()){
f.delete();
}
else{
try {
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("name:"+f.getName());
System.out.println("parent name:"+f.getParent());
System.out.println("path:"+f.getPath());
System.out.println("");
Date dt;
dt = new Date(f.lastModified());
System.out.println(dt);
}
}
2 . RandomAccessFile类
支持随机访问方式
支持众多的文件访问方法
在随机读写等长记录格式的文件时有很大的优势
仅限于操作文件,不能访问其他的IO设备
New RandomAccessFile(f,"rw");
New RandwomAccessFile(f,"r");
读写共享文件指示器
import java.io.RandomAccessFile;
public class TestRandomFile {
public static void main(String args[])throws Exception{
Employee e1 = new Employee("zhangsan",25);
Employee e2 = new Employee("lisi",15);
Employee e3 = new Employee("wangwu",20);
RandomAccessFile ra = null;
ra = new RandomAccessFile
( "C://Users//姜康//Desktop//java//2.txt","rw");
ra.write(e1.name.getBytes());
//ra.write(e1.age);只读取一个字节
ra.writeInt(e1.age);
ra.write(e2.name.getBytes());
ra.writeInt(e2.age);
ra.write(e3.name.getBytes());
ra.writeInt(e3.age);
ra.close();
RandomAccessFile raf = null;
raf = new RandomAccessFile("C://Users//姜康 //Desktop//java//2.txt","r");
//byte[] buf = new byte[8];
raf.skipBytes(12);//跳过第一个员工的信息
System.out.println("第二个员工的信息是:");
int len = 8;
String str = "";
for(int i=0;i<len;i++){
str = str + (char)raf.readByte();
}
System.out.println("name:"+str);
System.out.println("age:"+raf.readInt());
raf.seek(0);
str = "";
System.out.println("第 一个员工的信息是:");
for(int i=0;i<len;i++){
str = str+(char)raf.readByte();
}
System.out.println("name:"+str);
System.out.println("age:"+raf.readInt());
raf.skipBytes(12);
System.out.println("第 三个员工的信息是:");
str = "";
for(int i=0;i<len;i++){
str = str+(char)raf.readByte();
}
System.out.println("name:"+str);
System.out.println("age:"+raf.readInt());
raf.close();
}
}
class Employee{
public final static int LEN = 8;
String name = null;
int age = 0;
Employee(String name,int age){
if(name.length() > LEN){
name = name.substring(0, 8);
}
else{
///u0000表示空字符
while(name.length() < LEN){
name += "/u0000";
}
}
this.name = name;
this.age = age;
}
}
处理中文使用Unicode编码:
import java.io.RandomAccessFile;
public class TestRandomFile {
public static void main(String args[])throws Exception{
Employee e1 = new Employee("张三",25);
Employee e2 = new Employee("李四",15);
Employee e3 = new Employee("王五",20);
RandomAccessFile ra = null;
ra = new RandomAccessFile( "C://Users//姜康 //Desktop//java//2.txt","rw");
ra.writeChars(e1.name);
//ra.write(e1.age);只读取一个字节
ra.writeInt(e1.age);
ra.writeChars(e2.name);
ra.writeInt(e2.age);
ra.writeChars(e3.name);
ra.writeInt(e3.age);
ra.close();
RandomAccessFile raf = null;
raf = new RandomAccessFile("C://Users//姜康 //Desktop//java//2.txt","r");
//byte[] buf = new byte[8];
System.out.println("第二个员工的信息是:");
int len = 8;
String str = "";
raf.skipBytes(len*2+4);//跳过第一个员工的信息
for(int i=0;i<len;i++){
str = str + (char)raf.readChar();
}
//注意Unicode编码,每次占用两个字节
System.out.println("name:"+str);
System.out.println("age:"+raf.readInt());
raf.seek(0);
str = "";
System.out.println("第 一个员工的信息是:");
for(int i=0;i<len;i++){
str = str+(char)raf.readChar();
}
//System.out.println("changdu:"+str.length());
System.out.println("name:"+str);
System.out.println("age:"+raf.readInt());
System.out.println("第 三个员工的信息是:");
str = "";
raf.skipBytes(len*2+4);
for(int i=0;i<len;i++){
str = str+(char)raf.readChar();
}
System.out.println("name:"+str);
System.out.println("age:"+raf.readInt());
raf.close();
}
}
class Employee{
public final static int LEN = 8;
String name = null;
int age = 0;
Employee(String name,int age){
if(name.length() > LEN){
name = name.substring(0, 8);
}
else{
///u0000表示空字符
while(name.length() < LEN){
name += "/u0000";
}
}
this.name = name;
this.age = age;
}
}
3. 节点流
流是字节序列的抽象概念(数据传输)
文件时数据的静态存储形式,而流是知识传输时的形态
流分为:节点流类和过滤流类
InputStream与OutputStream类
InputStream可以连续输入字节
有了垃圾回收期为什么还会有close方法?
除了对象外还有各种资源,比如流,close来
FileInputStream与FileOutputStream类
分别用来创建磁盘文件的输入输出流对象,通过他们构造函数来制定文件路径名和文件 名,创建FileOutStream实例对象时,如果制定文件存在,将会覆盖源文件。
FileInputStream inOne = new FileInputStream("hello.test");
File f = new File("test.test");
FileInputStream inTwo = new FileInputStream(f);
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class TestFileIO {
public static void main(String args[]) throws Exception{
FileInputStream in = new FileInputStream("C://Users// 姜康 //Desktop//java//1.txt");
FileOutputStream out = new FileOutputStream("C://Users//姜康//Desktop//java//1.txt");
//会把源文件覆盖掉
out.write("www.baidu.com".getBytes());
out.close();
byte [] buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String(buf,0,len));
in.close();
}
}
Reader与Write类
Reader和Writer简化对字符串的输入输出编程,即用于读写文本数据
二进制文本和文本文件的区别
文件系统中每个文件都是二进制文件
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileStream1 {
public static void main(String args[]) throws IOException{
FileWriter out = new FileWriter("C://Users//姜康 //Desktop//java//1.txt");
out.write("www.google.com");
out.flush();
out.close();
//一定要关闭或者是刷新缓冲区
//否则最后一行数据不会输入到文件中
FileReader in = new FileReader("C://Users//姜康 //Desktop//java//1.txt");
char [] buf = new char[1024];
int len = in.read(buf);
System.out.println(new String(buf,0,len));
}
}
PipedInputStream与PipedOutputStream类
他们应用在应用程序中的创建管道通信(线程通信)
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipedStreamTest {
public static void main(String args[]){
Sender t1 = new Sender();
Riceiver t2 = new Riceiver();
PipedOutputStream out1 = t1.getOutputStream();
PipedInputStream in1 = t2.getInputStream();
try {
out1.connect(in1);
} catch (IOException e) {
e.printStackTrace();
}
t1.start();
t2.start();
}
}
import java.io.IOException;
import java.io.PipedOutputStream;
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) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.io.PipedInputStream;
public class Riceiver 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 comes from sender:/n"+new String(buf,0,len));
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
PipedWriter和PipedReader类
使用管道流类,可以实现各个程序模块之间的松耦合通信
ByteArrayInputStream和ByteArrayOutputStream
用于以IO流的方式来完成对字节数组内容的读写
支持类似内存虚拟文件或者内存映像文件的功能
public class ByteArrayTest {
public static void main(String[] args) {
String tmp = "abcdefghijkmlnopqrstuvwxyz";
byte [] src = tmp.getBytes();
ByteArrayInputStream input = new ByteArrayInputStream(src);
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
transform(input,output);
} catch (IOException e) {
e.printStackTrace();
}
byte [] result = output.toByteArray();
System.out.println(new String(result));
}
public static void transform(InputStream in,OutputStream out) throws IOException{
int ch;
while((ch = in.read()) != -1){
int upperCh = (int)Character.toUpperCase((char)ch);
out.write(upperCh);
}
}
}
4 重视IO程序代码的复用
System.in连接连接到键盘,InputStream类型的实例对象,System,out是PrintStream的 实例对象,连接到显示器
无论各种底层物理设备用什么样的方式实现数据的终止点,InputStream总是返回-1表 示输入流的结束
transform(System.in,System.out);
5 字符编码
中国每个字符都用连个字节的数字来表示,GB2312 后来扩展了繁体称为GBK
ISO制定了Unicode编码标准
Java中的字符使用的都是Unicode编码
UTF-8编码中ASCii码只占用一个字节,其他国家的字符,使用两个或三个字节表示
UTF-16 big-Endian与little-Endian以0xFE 0xFF开头表明是big-Endian,反过来为 little-Endian
动手体验字符编码:
public class CharCode {
public static void main(String args[]){
System.setProperty("find-encoding","GBK");
System.getProperties().list(System.out);
String strChina = "中国";
for(int i=0;i<strChina.length();i++){
System.out.println(Integer.toHexString
((int)strChina.charAt(i)));
}
byte []buf = null;
buf = strChina.getBytes();
for(int i=0;i<buf.length;i++){
System.out.println(Integer.toHexString(buf[i]));
}
for(int i=0;i<buf.length;i++){
System.out.write(buf[i]);
}
System.out.println();
//PrintStream会自动把字符集转换为机器中装入的字符集(GB2312)
}
}
6 过滤流与包装类
InputOutStream处理的是字节,需要先把数据转换到字节数组中再做处理
DateOutputStream类提供了往各种输入流对象中写入各种类型的数据的方法,现在只需要传递一个FileOutputStream输入流对象给DateOutputStream实例对象和调用实例对象
一定要指定到任何具体的流设备
DateOutputStream包装类
Public DateOutputStream(OutputStream out)
包装流类通过节点流类传送数据给目标
BufferedInputStream与BufferedOutputStream类
缓冲流增加了内存缓冲区:
允许java程序一次不止操作一个字节(提高了程序的性能)
有了缓冲区,skip,mark,reset方法可以使用了
不管地磁是否使用了缓冲区,这两个类在自己的实例对象中创建缓冲区
它有两个构造函数:
BufferedInputStream(InputStream in)//一次创建32个字节的缓冲区
BufferedInputStream(InputStream in,int size)//可以指定大小
Mark方法是建立在缓冲区内部的(同样有BufferedOutputStream)
BufferedReader和BufferedWriter类
BufferedReader有一个readLine方法可以一次读取一行文本
BufferedWriter 可以写入不同操作系统下的换行符
DateInputSteam类和DateOutputStream类
public final void writeByte(String s)//每次只是将字符串中的低字节写入到目标设备
public final void writeChars(String s)//每次写入两个字节
Public final void writeUTF(String str)//按照UTF格式写入,前两个是编码后的长度
UTF规则:
如果字符c范围在/u0001和/u007f之间,则占一个字节,内容为(byte)c
如果在/u0080或其范围在/u07ffh之间则两个字节
如果在/u0800和/uffff之间,则占三个字节
如果关闭流栈中最上层的流对象,底层的流对象将全会被关闭
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DateStreamTest {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("C://Users//姜康//Desktop//java//xx.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("C://Users//姜康//Desktop//java//xx.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));*/
//用writechars和writebytes写入文件后读出来就不容易了
//所以java提供了一些专用类来处理字符串
}
}
7 PrintStream类
PrintStream提供了一系列的print和println方法,可以将基本数据类型的数据格式 化成字符串输出(println可以自动调用flush方法来刷新缓冲区)
格式化输出就是将数据用字符串的形式输出
三个构造函数:
PrintStream(OutputStream out)
PrintStream(OutputStream out, boolean autoflush)//设置是否自动清空缓冲区
PrintStream(OutputStream out boolean autoflush,String encoding)
//可以指定字符编码
PrintWriter类,计时遇到了文本换行标识符(/n)也不会自动清空缓冲区
println()在windows生成的文本换行标识符为:"/r/n;"Linux下为:"/n"
8 ObjectInputStream和ObjectOutputStream类
可以完成保存和读取对象成员变量取值的过程
所读取的对象必须实现了Serializable接口,对象中的transient(表示变量是临时的, 不能被用作对象的表示)和static类型的成员 变量不会被读取和写入
序列化可以屏蔽操作系统的差异
import java.io.*;
@SuppressWarnings("serial")
class Student implements Serializable {
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;
}
}
class Serialization {
public static void main(String args[]) throws IOException, ClassNotFoundException{
Student stu1 = new Student(19,"zhangsan",25,"jsj");
Student stu2 = new Student(20,"lisi",18,"yingyu");
FileOutputStream out = new FileOutputStream("C://Users//姜康//Desktop//java//student.txt");
ObjectOutputStream os = new ObjectOutputStream(out);
os.writeObject(stu1);
os.writeObject(stu2);
os.close();
FileInputStream in = new FileInputStream("C://Users//姜康//Desktop//java//student.txt");
ObjectInputStream is = new ObjectInputStream(in);
stu1= (Student) is.readObject();
stu2= (Student) is.readObject();
is.close();
System.out.println("id:"+stu1.id);
System.out.println("name:"+stu1.name);
System.out.println("age:"+stu1.age);
System.out.println("department:"+stu1.department);
System.out.println();
System.out.println("id:"+stu2.id);
System.out.println("name:"+stu2.name);
System.out.println("age:"+stu2.age);
System.out.println("department:"+stu2.department);
}
}
9 字节流与字符流的转换
BufferedReader类的两个构造方法:
BufferedReader(Reader in)
创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz)
创建一个使用指定大小输入缓冲区的缓冲字符输入流。
需要用包装类来转换输入的数据
InputStreamReader(Reader类的子类)和OutputStreamWriter两个类分别来把字节流 转换成字符流后读取和把字符编码为字节后写入到一个字节流中
InputStreamReader构造函数:
InputStreamReader(InputStream in) |
InputStreamReader(InputStream in, Charset cs) |
InputStreamReader(InputStream in, CharsetDecoder dec) |
InputStreamReader(InputStream in, String charsetName) |
OutputStreamRead构造函数:
OutputStreamWriter(OutputStream out) |
OutputStreamWriter(OutputStream out, Charset cs) |
OutputStreamWriter(OutputStream out, CharsetEncoder enc) |
OutputStreamWriter(OutputStream out, String charsetName) |
10 java虚拟机读写其他进程的数据
我们在java虚拟机中可以产生其他应用程序的进程,在java程序中启动的进程成 为子进程,子进程的标准输入输出不再连接到键盘和显示器,而是以管道流的形式 连接到父进程的一个输入流和输出流对象上
调用Process类的getOutputStream和getInputStream方法可以获得连接到子进程的 输出流和输入流对象
import java.io.*;
public class TestInout implements Runnable{
Process p = null;
public TestInout() throws IOException{
p = Runtime.getRuntime().exec("java MyTest");
new Thread(this).start();
//用this表示send和run方法调用的是一个对象
}
public static void main(String[] args) throws IOException {
TestInout t = new TestInout();
t.send();
}
public void send() throws IOException{//向子进程发送数据
OutputStream ops = p.getOutputStream();
while(true){
ops.write("help/r/n".getBytes());
}
}
public void run(){//接收数据
InputStream ips = p.getInputStream();
BufferedReader bfr = new BufferedReader(
new InputStreamReader(ips));
String strLine = "";
try {
strLine = bfr.readLine();
while(true){
System.out.println(strLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.*;
public class MyTest {
public static void main(String args[]) throws IOException{
String strLine = "";
BufferedReader bft = new BufferedReader(
new InputStreamReader(System.in));
while(true){
strLine = bft.readLine();
if(strLine != null){
System.out.println("hi"+strLine);
}
else{
return;
}
}
}
}
要用destroy方法结束Process子进程的运行
11 字节输入流类
字节输出流类
字符输入流类
字符输出流类
12 Decorator设计模式
在程序中用一个对象(the Decorator) 包装另外一个对象
如果设计字节的IO包装类,这个类需要继承FilterXXX命名的类
import java.io.*;
public class TestPrintWriter {
public static void main(String args[]){
try{
throw new Exception("test");
}catch(Exception e){
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
System.out.println(sw.toString());
}
}
}