IO输入与输出
1.i代表的是键盘既输入,o代表的是显示器,既输出
2.file类io包中唯一代表磁盘文件本身信息的的类,而不是文件中的内容,比如说文件的创建时间,而且定义了一些与平台无关的方法来操作文件
package com.hjw;
import java.io.File;
import java.io.IOException;
public class FileTest {
/**
* 判断一个文件是否存在,如果存在就删除, 如果不存在就创建此文件
*
* @param args
*/
public static void main(String[] args) {
fileTest();
}
private static void fileTest() {
File f = new File("aa//a.txt");
if (f.exists()) {
f.delete();
} else {
try {
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("fileName:" + f.getName());
// 得到文件的相对路径
System.out.println("filepath:" + f.getPath());
// 得到绝对路径下的文件
System.out.println("AbsoluteFile:" + f.getAbsoluteFile());
// 得到文件的上一级
System.out.println("parent:" + f.getParent());
// 得到文件上一级的相对路径
System.out.println("parentFile:" + f.getParentFile());
System.out.println("AbsolutePath:" + f.getAbsolutePath());
System.out.println(f.exists() ? "exist" : "not exist");
System.out.println(f.canRead() ? "read" : "not read");
System.out.println(f.canWrite() ? "write" : "not write");
// 判断f是否是一个目录
System.out.println(f.isDirectory() ? "directory" : "not directory");
System.out.println();
}
}
3.randomAccessFile类a)提供了众多的文件访问方法,b)它支持随机访问方式,从指示器指示的当前位置开始,c)它在读写等长记录格式的文件时有很大的优势。d)仅限于操作文件,不能访问其他的io设备,
e)两种构造方法:
new RandomAccessFile("f","rw");//读写方式,在写时可以以字节、字符写入,字节写入适用于字母,字符写入适用于中文
new RandomAccessFile("f","r");//只读方式
4.a)字节写入于读取
package com.hjw;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 通过randormAccessFile类把三条数据写入到文件中,然后再把文件读出来(先读第二条数据,
* 在读第一条数据,最后读第三条数据),通过字节读取
* @author Administrator
*
*/
public class RandomFileTest {
public static void main(String[] args) {
// 定义三条记录
Employee e1 = new Employee("zhangsan", 23);
Employee e2 = new Employee("lisi", 22);
Employee e3 = new Employee("wangwu", 21);
try {
// 把内容通过randomAccessFile写入到文件中
RandomAccessFile ra = new RandomAccessFile("employee.txt", "rw");
//把数据写入到文件中
ra.write(e1.getName().getBytes());
ra.writeByte(e1.getAge());
ra.write(e2.getName().getBytes());
ra.writeByte(e2.getAge());
ra.write(e3.getName().getBytes());
ra.writeByte(e3.getAge());
ra.close();
// 把文件读出来
byte[] bt = new byte[8];
int len = 0;
String strName = null;
RandomAccessFile raf = new RandomAccessFile("employee.txt", "r");
raf.skipBytes(9);
len = raf.read(bt);
strName = new String(bt, 0, len);
System.out.println(strName.trim() + ":" + raf.read());
raf.seek(0);
len = raf.read(bt);
strName = new String(bt, 0, len);
System.out.println(strName.trim() + ":" + raf.read());
raf.skipBytes(9);
len = raf.read(bt);
strName = new String(bt, 0, len);
System.out.println(strName.trim() + ":" + raf.read());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
b)字符写入于读入
package com.hjw;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 通过randormAccessFile类把三条数据写入到文件中,然后再把文件读出来(先读第二条数据,
* 在读第一条数据,最后读第三条数据),通过字符读取,可以是中文
*
* @author Administrator
*
*/
public class RandomFileTest2 {
public static void main(String[] args) {
// 定义三条记录
Employee e1 = new Employee("zhangsan", 235);
Employee e2 = new Employee("张三", 22);
Employee e3 = new Employee("wangwu", 21);
try {
RandomAccessFile ra = new RandomAccessFile("employee.txt", "rw");
//以什么写入的就用什么读取,比如用writeInt写入就用readInt读取
ra.writeChars(e1.getName());
ra.writeInt(e1.getAge());
ra.writeChars(e2.getName());
ra.writeInt(e2.getAge());
ra.writeChars(e3.getName());
ra.writeInt(e3.getAge());
ra.close();
String strName = "";
RandomAccessFile raf = new RandomAccessFile("employee.txt", "r");
raf.skipBytes(Employee.getLen()*2 + 4);
for (int i = 0; i <Employee.getLen(); i++) {
strName += raf.readChar();
}
System.out.println(strName.trim() + ":" + raf.readInt());
raf.seek(0);
strName = "";
for (int i = 0; i < Employee.getLen(); i++) {
strName += raf.readChar();
}
System.out.println(strName.trim() + ":" + raf.readInt());
raf.skipBytes(Employee.getLen() * 2 + 4);
strName = "";
for (int i = 0; i < Employee.getLen(); i++) {
strName += raf.readChar();
}
System.out.println(strName.trim() + ":" + raf.readInt());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
四小节.
1.流是字节序列的抽象概念,通过IO设备输入输出把数据写入与读取的工具,
2.文件时数据的静态存储形式,而流是指数据传输时的形态
3.流类分为节点流类和过滤流类
4.输入流:程序可以从中连续读取字节的对象,inputStream 抽象类
inputStrean的方法:
1).int read()把读取一个字节数据,并把这个字节的内容赋值到int类型的最低字节,其他高字节设置为0, 这与byte转换为int不一样,不如byte -1转换为int,在int中任然为-1,
如果流的结束 则返回为-1 ,把read返回值设置为int,是为了区别返回的-1与255
2)int read(byte[] b)
3)int read(byte[] b,int off,int len)
4)long skip(long n)
5)int avaliable()
作用一avaliable检查是否有可读的数据,作用二如果用的是read(byte[] b,int off,int len)可以先读一部分,然后用avaliable方法检查一下是否还有可读数据,如果有继续读取
,如果没有就返回
6)void mark(int readlimit)//标记
7)void reset()//重置
8)boolean markSupported()
9)void close(),如果流读写完之后就关闭流
*垃圾回收器只负责回收java程序中产生的垃圾,close方法负责关闭系统中的资源
5.输出流:程序可以向其中连续写入字节的对象,用outputStream来描述输出流的抽象概念
1).int write(int b)
2)int write(byte[] b)
3)int write(byte[] b,int off,int len)
4)void flush() //应用程序先写到内存缓冲区,在再由内存缓冲区到IO设备
5)void close(),如果流读写完之后就关闭流
6.fileInputStream和FileOutputStream类分别用来创建磁盘文件的输入和输出流对象,通过他们的构造函数来指定文件路径和文件名。
*fileInputStream实例对象时,指定的文件应该是存在和可读的,fileOutputStream实例对象时,如果指定的文件已经存在,这个文件中的原来的内容将被覆盖清除。
7.对同一磁盘文件创建FileInputStream对象有两种方式:
a).FileInputStream fis=new FileInputStream("hello.test");
b).File f=new File("hello.test");
FileInputStream fis=new FileInputStream(f);
第二种方法可以在读出时对文件先进行判断,比如先判断文件是否存在,是否可读可写,是否是子目录等等。
8.创建FileOutputStream实例对象时,可以指定还不存在的文件名,不能指定一个已被其他程序打开了的文件,如果同时操作可能会改变彼此的设置
9.一个读写文件的例子
package com.hjw;
/**
*先给文件中写入一些东西,在把文件读出来,
*主要用FileOutputStream和FileInputStream两个流实现
* 字节读写
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileInputStream_fop {
public static void main(String[] args) {
fipTest();
}
private static void fipTest() {
// 通过fileOutputStream把文件写入
try {
FileOutputStream fo = new FileOutputStream("hello.txt");
fo.write("张三hegnlofdfd".getBytes());
fo.close();
byte[] buf = new byte[1024];
File f = new File("hello.txt");
// 把文件通过fileInputStream把文件读出来
FileInputStream fi = new FileInputStream(f);
int len = fi.read(buf);
System.out.println(new String(buf, 0, len));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
10.reader和writer是所有字符流类的抽象基类,用于简化对字符串的输入输出编程,即用于读写文本数据
11.文本文件:专用于存储文本字符,而没有包含字符之外的数据,其他的都称为二进制文件
12.reader和writer主要用于读写文本格式的内容,inputStream和outputStream是他们的子类
*写入字节数组的内部调用了flash的方法,而写入字符数组的没用调用,witrer直接就是写入一个字符
13.文件字符输入输出流的引用例子:
package com.hjw;
/**
* 文件字符输入输出流,读取或写入字符,其中写入writer只能写一个字符,
* 写的东西都在缓存中要close,才会写入到文件,字节写入内部调用了
* flesh()方法,所以会自动把缓存中的内容写入到文件中
*
*/
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Writer_Reader {
public static void main(String[] args) {
writerTest();
}
private static void writerTest() {
try {
// 通过文件字符流输出向文件中写入字符
FileWriter fw = new FileWriter("hello2.txt");
fw.write("金佛地方巨dfdf额烦人劲fdfdf儿");
fw.close();
char[] ch = new char[1024];
// 通过文件字符输入流把文件中内容读取出来
FileReader fr = new FileReader("hello2.txt");
int len = fr.read(ch);
System.out.println(new String(ch, 0, len));
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
14.PipedInputStream类和pipedOutputStream类用于在应用程序中创建管道通信。pipedInputStream可以读取从PipedOutputStream中写入的类,主要完成线程之间的通行,
15.pipedInputStream与pipedOutputStream的实例
package com.hjw.www;
/**
* 用于写入数据
*/
import java.io.IOException;
import java.io.PipedOutputStream;
public class Sender extends Thread {
private PipedOutputStream out = new PipedOutputStream();
public PipedOutputStream getout() {
// 用于得打PipedOutputStream中的数据
return out;
}
@Override
// 用于给pipedOutputStream中写数据
public void run() {
String strInfo = new String("hello,receive");
try {
out.write(strInfo.getBytes());
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.hjw.www;
/**
* 用于读取发送的数据
*/
import java.io.IOException;
import java.io.PipedInputStream;
public class Receive extends Thread {
private PipedInputStream in = new PipedInputStream();
public PipedInputStream getIn() {
return in;
}
@Override
// 用于给pipedInputStream中读数据
public void run() {
byte[] buf = new byte[1024];
try {
int len=in.read(buf);
System.out.println("the receive message :"+new String(buf,0,len));
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.hjw.www;
/**
* pipedStream的测试类
*/
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipedStreamTest {
public static void main(String[] args) {
pipedStreamTest();
}
public static void pipedStreamTest() {
Sender t1 = new Sender();
Receive t2 = new Receive();
PipedOutputStream out = t1.getout();
PipedInputStream in = t2.getIn();
try {
out.connect(in);
t1.start();
t2.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
16.pipedWriter和pipedReader类(对字符进行处理)
17.byteArrayInputStream与byteArrayOutputStream类,用于以IO流的方式来完成对字节数组内容的读写,来支持类似内存虚拟文件或者内存映像文件的功能
18.byteArrayInputStream的两个构造函数:
ByteArrayInputStream(byte[] buf)
ByteArrayInputStream(byte[] buf,int offset,int length)
byteArrayOutputStream的两个构造函数:
ByteArrayOutputStream()
ByteArrayOutputStream(int)
19.例子
package com.hjw;
/**
* 现将其字符串读出,然后转换为大写在写入
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ByteArrayStream {
public static void main(String[] args) {
String ss = "dffdfdfdfdsere";
byte[] buf = ss.getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(buf);
ByteArrayOutputStream out = new ByteArrayOutputStream();
transform(in, out);
byte[] result = out.toByteArray();
System.out.println(new String(result));
}
// 把得到的字节转换为大写
public static void transform(InputStream in, OutputStream out) {
int ch = 0;
try {
while ((ch = in.read()) != -1) {
int upperch = Character.toUpperCase(ch);
out.write(upperch);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
20.System.in连接到键盘,是inputStream类型的实例对象,System.out连接到显示器,是printStream类的实例对象,read返回-1就是读取完了
七小节
21.计算机里只有数字,计算机软件里的都是用数字来表示的,屏幕上显示的一个个字符也不例外,a--97,b--98
字符与数字对应的编码规则被称为ascii(美国标准信息交换码)
中国大陆为每个中文字符规定的编码规则称为gb2312(国标码)
对更多的中文字符(包括繁体)进行了编码,称为gbk
22.国际标准化编码Unicode编码
只占一个字节最高位为0
只占两个字节第一个字节的最高位为110,第二个字节的前两位是10
只占三个字节第一个字节最高位为1110,第二、三个字节的前两位是10
23.utf-8的优点
不出现内容为0x00字节,便于应用程序检测数据在传输过程中是否发生了错误,直接处理使用ascii码的编码文档
utf-8的缺点:
其中某些字符需要三个字节,是unicode的1.5倍
24.utf-8通常都需要EF BB BF做为文件开头的三个字节数据
utf-16编码对unicode基础上进行了一些细节上的扩充,他扩充的字符占用四个字节,可以表示各个名族所有的字符,1024*1024已经可以表示了,高位与地位不同有利于区别字节的边界
25.一个双字节数据,使用little-endian(文件以oxff oxfe 这两个字节开头)和big-endian(文件以oxfe oxff两个字节开头)两种方式在内存中存储的格式
26.联通两个字符合utf-8的编码,想不符合utf-8的编码格式
27.编码的一些引用:例子
package com.hjw;
/**
* 显示字符串的unicode码,既gb2312
*/
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class CharAt {
public static void main(String[] args) {
chatTest();
}
private static void chatTest() {
// 显示出jdk中所有的属性
System.getProperties().list(System.out);
String strChina = "中国";
// 打印出strChina的unicode的 编码
for (int i = 0; i < strChina.length(); i++) {
System.out.println(Integer.toHexString((int) (strChina.charAt(i))));
}
// 得到国标2312编码,将unicode转换为字符集
// 写入到显示器的都是gb2312
try {
byte[] buf = strChina.getBytes("gb2312");
for (int i = 0; i < buf.length; i++) {
System.out.println(Integer.toHexString(buf[i]));
}
// 把得到的字节集写入到显示器
System.out.write(buf);
// for(int j=0;j<buf.length;j++){
// System.out.write(buf[j]);
// }
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// System.out.println("中国");
}
}
28.//设置系统的文件的编码
System.setProperty("file.encoding", "iso8859-1");
// 显示出jdk中所有的属性
System.getProperties().list(System.out);
29.查看输入的编码
package com.hjw;
import java.io.IOException;
public class CharDecode {
public static void main(String[] args) {
charTest();
}
private static void charTest() {
System.out.println("please enter a chinese string:");
int ch = 0;
byte[] buf = new byte[1024];
String strInfo = null;
int pos = 0;
// 定义变量最后在外边定义(while,switch ,case外边)
while (true) {
try {
ch = System.in.read();
System.out.println(Integer.toHexString(ch));
switch (ch) {
// 如果是回车
case '/r':
System.out.println("rrrr");
break;
// 如果是换行
case '/n':
System.out.println("nnnn");
// strInfo=new String(buf,0,pos,"gb2312");
strInfo = new String(buf, 0, pos);
System.out.println("strinfo===" + strInfo);
// 读取它的unicode编码
for (int i = 0; i < strInfo.length(); i++) {
System.out.println(Integer.toHexString(strInfo
.charAt(i)));
}
break;
// 默认是把读取到的存放在一个字节数组中
default:
buf[pos++] = (byte) ch;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
30.包装类
dataOutputStream并没有对应到任何具体的流设备,一定要给他传递一个对应具体流设备的输出流对象,完成类似DataOutputStream功能的类就是一个包装类,也叫过滤流类或处理流类。
DataOutputStream包装类的构造函数语法:
public DataOutPutStream(OutputStream out);
31.缓冲流为IO流增加了内存缓冲区,增加缓冲区有两个基本目的:允许java程序一次不只操作一个字节,提高了程序的性能。有了缓冲区,使得在流上执行skip,mark和reset方法都成为可能,
bufferedInputStream和BufferedOutputStream是java提高的两个缓冲区包装类。
BufferedInputStream(inputStream in);
BufferedInputStream(inputStream in,int size);
BufferedOutputStream(OutputStream Out);
BufferedOutputStream(OutputStream Out,int size);
bufferedReader readLine(读取一行)和bufferedWriter newLine
32.包装类的例子,注:关闭流时关闭上层流也就把底层的流关了。
package com.hjw;
/**
* 包装流类的测试,向一个文件中写入一些内容,然后把这些内容读出来
*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataSteamTest {
public static void main(String[] args) {
dateStreamTest();
}
private static void dateStreamTest() {
// 通过包装流类向文件中写入数据
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();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 读取包装流类读取文件中的数据
try {
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));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
33.printStream类提供了一系列的print和println方法,可以将数据类型的数据格式化成字符串输出
34.0--9的asc码,ox30---0x39
35.printStream的3个构造函数:
printStream(outputStream out);
printStream(outputStream out,boolean autoflush);
printStream(outputStream out,boolean autoflush,String encoding);
36.printWriter的println方法能根据操作系统的不同而生成相应的文本换行标识符。
37.objectInputStream与objectOutputStream用于从底层输入流中读取对象类型的数据和将对象类型的数据写入到底层输入流
objectInputStream与objectOutputStream类所读写的对象必须实现了serializable接口,对象中的transient和static类型的成员变量不会被读取和写入,序列化能区别不同操作系统的差异
38.对象流的例子:
package com.hjw;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Serializable {
public static void main(String[] args) {
Students stu1 = new Students(20, "zhangsan", 19, "wuli");
Students stu2 = new Students(22, "lisi", 21, "huaxue");
try {
FileOutputStream fos = new FileOutputStream("student.txt");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(stu1);
os.writeObject(stu2);
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
try {
FileInputStream fis = new FileInputStream("student.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
stu1 = (Students) ois.readObject();
stu2 = (Students) ois.readObject();
ois.close();
System.out.println("id:" + stu1.id);
System.out.println("name:" + stu1.name);
System.out.println("age:" + stu1.age);
System.out.println("deparment:" + stu1.deparment);
System.out.println("id:" + stu2.id);
System.out.println("name:" + stu2.name);
System.out.println("age:" + stu2.age);
System.out.println("deparment:" + stu2.deparment);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
39.字节流与字符流的转换
inputStreamReader和outputStreamWriter是用于将字节流转换为字符流来读写的两个类,inputStreamReader可以将一个字节流总的字节解码称字符后读取,outputStreamWriter将字符编码称字节后写入到一个字节流中。
40.inputStreamReader的两个主要构造函数:
inputStreamReader(inputStream in);
inputStreamReader(inputStream in, String charsetName);
41.平时应用都是使用bufferedReader/bufferedWriter来包装inputStreamReader/outputStreamWriter读取来提高效率。
42.java中可以用process类的实例对象表示子进程,子进程的标准输入和输出不在连接到键盘和显示器,而是以管道流的形式连接到父进程的一个输出流和输入流对象上。
43.调用process类的getOutputStream和getInputStream方法可以获得连接到子进程的输出流和输入流对象。
例子:
package com.hjw;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class TestInOut implements Runnable {
// process得到子进程
Process p = null;
// 启动两个进程
public TestInOut() {
try {
// 启动子进程(getRuntime得到虚拟机当前的对象,exec执行外部命令)
p = Runtime.getRuntime().exec("java MyTest");
// 启动一个线程
new Thread(this).start();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 父进程发送数据
TestInOut tio = new TestInOut();
tio.send();
}
// 发送数据的方法
public void send() {
try {
// int count=0;
while (true) {
OutputStream os = p.getOutputStream();
// System.out.println(++count);
// System.out.println("send");
os.write("help".getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 子进程接收数据
public void run() {
try {
InputStream is = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// System.out.println("reservle");
String strLine = br.readLine();
System.out.println(strLine);
} catch (IOException e) {
e.printStackTrace();
}
}
}
44.Decorator的设计模式:在程序中用一个对象包装另外的一个对象。
如果要设计自己的IO包装类,这个类需要继承以FilterXXX命名的类。
45.execption类从Throwable类继承的三个方法
public void printStackTrace()
public void printStackTrace(PrintStream s)
public void printStackTrace(PrintWriter s)