Java的输入/输出流
对于任何编程语言,除了数据的输入输出操作都是极其重要的,而在Java语言中是以输入输出流的形式进行数据的输入输出处理。
数据的输入:程序从数据源读取数据的过程;
数据的输出:程序将数据写入目标设备。
文件:输入输出经常处理的设备之一
I/O流它是用于设备之间的数据传输用的,它按照数据流向分为输入流,输出流。
按照操作类型分为俩种:
字节流,以字节形式进行数据传输;
字符流,以字符形式进行数据传输。
IO流常用父类:
字节流的抽象父类:InputStream、OutputStream
字符流的抽象父类:Reader、Writer
IO使用程序前,要导入IO包中的类,使用时,进行IO异常处理,使用后关闭,关闭流
常用方法:InputSteam:ready()读取一个节;
read(byte[])读取若干(数组长度)字节;
available()获取可读的字节数
close()关闭流,释放资源
OutputStream:
write(int) 写出一个字节
write(byte[])写出数组中所有字节
write(byte[],start,len)
close()
关闭流,释放资源
转换流 :InputStreamReader
键盘录入 :BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
写入转换流 : OutPutStreamWriter
控制台输出 :BufferedWriter buwr=new BufferedWriter(new OutputStreamWriter(System.out));
上面可以通过 System.setIn 和 System.setOut 来设置对应的源和目的 。
转换流什么时候用 :
字符和字节之间的桥梁 , 通常波及到编码转换时要用到转换流 。
流操作的基本规律 :
1、明确源和目的;
2、操作的数据是否是纯文本 ;
3、当体系明确后 , 在明确要使用哪个具体对象 . 是否要提高效率 . 来加入转换流 .;
I/O 包 File 类是文件和目录路径名的抽象表示形式。
用来将文件或者文件夹封闭成对象 ,
方便对文件与文件夹的属性信息进行操作 。
File 对象可以作为参数传递给流的构造函数 。
separator 字段是目录分隔符 。
File f=new File(“aa.txt”);// 将 aa.txt 封闭成 file 对象 ,可以将已有的和末出现的文件夹封装成对象 。
File f2=new File(“c:\\ab”,”bc.txt”);//”bc.txt” 可以传一个可变的参数 。
syso(f);// 打印文件的路径 ,,按封装时的格式打印出来 。
- InputStream:
/* 线程间通讯: 其实就是多个线程在操作同一个资源, 但是操作的动作不同。 */ class Res { String name; String sex; boolean flag = false; } class Input implements Runnable { private Res r ; Input(Res r) { this.r = r; } public void run() { int x = 0; while(true) { synchronized(r) { if(r.flag) try{r.wait();}catch(Exception e){} if(x==0) { r.name="mike"; r.sex="man"; } else { r.name="丽丽"; r.sex = "女女女女女"; } x = (x+1)%2; r.flag = true; r.notify(); } } } } class Output implements Runnable { private Res r ; Output(Res r) { this.r = r; } public void run() { while(true) { synchronized(r) { if(!r.flag) try{r.wait();}catch(Exception e){} System.out.println(r.name+"...."+r.sex); r.flag = false; r.notify(); } } } } class InputOutputDemo { public static void main(String[] args) { Res r = new Res(); Input in = new Input(r); Output out = new Output(r); Thread t1 = new Thread(in); Thread t2 = new Thread(out); t1.start(); t2.start(); } } //notifyAll(); /* wait: notify(); notifyAll(); 都使用在同步中,因为要对持有监视器(锁)的线程操作。 所以要使用在同步中,因为只有同步才具有锁。 为什么这些操作线程的方法要定义Object类中呢? 因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁, 只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。 不可以对不同锁中的线程进行唤醒。 也就是说,等待和唤醒必须是同一个锁。 而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。 */
- OutputStream
/* 线程间通讯: 其实就是多个线程在操作同一个资源, 但是操作的动作不同。 */ class Res { private String name; private String sex; private boolean flag = false; public synchronized void set(String name,String sex) { if(flag) try{this.wait();}catch(Exception e){} this.name = name; this.sex = sex; flag = true; this.notify(); } public synchronized void out() { if(!flag) try{this.wait();}catch(Exception e){} System.out.println(name+"........"+sex); flag = false; this.notify(); } } class Input implements Runnable { private Res r ; Input(Res r) { this.r = r; } public void run() { int x = 0; while(true) { if(x==0) r.set("mike","man"); else r.set("丽丽","女女女女女"); x = (x+1)%2; } } } class Output implements Runnable { private Res r ; Output(Res r) { this.r = r; } public void run() { while(true) { r.out(); } } } class InputOutputDemo2 { public static void main(String[] args) { Res r = new Res(); new Thread(new Input(r)).start(); new Thread(new Output(r)).start(); /* Input in = new Input(r); Output out = new Output(r); Thread t1 = new Thread(in); Thread t2 = new Thread(out); t1.start(); t2.start(); */ } }
File 常见方法 .
1、 创建 boolean createNewFile();
2、 删除 boolean delete(); void deleteOnExit(); mkdir(); new File(“abc\\kk”).mkdir();
mkdirs(); 创建多级文件夹 。
3、判断 Boolean exists(); 文件是否存在 。
isDirectory();isFile(); 通过这两方法可以判断封装完的对象是什么 ?
4、获取信息 .getXXX();
拷贝文件有4种方式,
逐个字节拷贝
不建议使用效率太低,
自定义数组拷贝
建议使用,不大不小的数组效率高。
定义一个大数组拷贝,数组和文件的字节个数一样大
不建议使用,可能会造成内存溢出,
带缓冲区的拷贝
建议使用 带缓冲区, 一次读取多个字节装入缓冲区。效率高 。
finally嵌套:
1.6版本及以前的标准的异常处理代
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("aaa.txt");
fos = new FileOutputStream("bbb.txt");
int b;
while((b = fis.read()) != -1) {
fos.write(b);
}
}finally {
try {
if(fis != null)
fis.close();
} finally {
if(fos != null)
fos.close();
}
}
try close
1.7版本的标准的异常处理代码:
try(
FileInputStream fis = new FileInputStream("aaa.txt");
FileOutputStream fos = new FileOutputStream("bbb.txt");
MyClose mc = new MyClose();
){
int b;
while((b = fis.read()) != -1) {
fos.write(b);
}
}
- StringBuffer是字符串缓冲区:
/* StringBuffer是字符串缓冲区。是一个容器。 特点: 1,长度是可变化的。 2,可以字节操作多个数据类型。 3,最终会通过toString方法变成字符串。 C create U update R read D delete 1,存储。 StringBuffer append():将指定数据作为参数添加到已有数据结尾处。 StringBuffer insert(index,数据):可以将数据插入到指定index位置。 2,删除。 StringBuffer delete(start,end):删除缓冲区中的数据,包含start,不包含end。 StringBuffer deleteCharAt(index):删除指定位置的字符。 3,获取。 char charAt(int index) int indexOf(String str) int lastIndexOf(String str) int length() String substring(int start, int end) 4,修改。 StringBuffer replace(start,end,string); void setCharAt(int index, char ch) ; 5,反转。 StringBuffer reverse(); 6,将缓冲区中指定数据存储到指定字符数组中。 void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) JDK1.5 版本之后出现了StringBuilder. StringBuffer是线程同步。 StringBuilder是线程不同步。 以后开发,建议使用StringBuilder 升级三个因素: 1,提高效率。 2,简化书写。 3,提高安全性。 */ class Demo{} class StringBufferDemo { public static void main(String[] args) { //method_update(); StringBuilder sb = new StringBuilder("abcdef"); char[] chs = new char[6]; sb.getChars(1,4,chs,1);//将 for(int x=0; x<chs.length; x++) { sop("chs["+x+"]="+chs[x]+";"); } draw(3,6); draw(8,9); // StringBuilder sb1 = new StringBuilder(); // sb1.append(new Demo()).append(new Demo()); // sop("sb1="+sb1); } public static void method_update() { StringBuffer sb = new StringBuffer("abcde"); // sb.replace(1,4,"java"); sb.setCharAt(2,'k'); sop(sb.toString()); } public static void method_del() { StringBuffer sb = new StringBuffer("abcde"); // sb.delete(1,3); //清空缓冲区。 //sb.delete(0,sb.length()); //sb.delete(2,3); sb.deleteCharAt(2); sop(sb.toString()); } public static void method_add() { StringBuffer sb = new StringBuffer(); //sb.append("abc").append(true).append(34); // StringBuffer sb1 = sb.append(34); // sop("sb==sb1:"+(sb==sb1)); sb.insert(1,"qq"); sop(sb.toString());//abctrue34 //sop(sb1.toString()); } public static void sop(String str) { System.out.println(str); } public static void draw(int row,int col) { StringBuilder sb = new StringBuilder(); for(int x=0; x<row; x++) { for(int y=0; y<col; y++) { sb.append("*"); } sb.append("\r\n"); } sop(sb.toString()); } }
- ArrayListTest:
import java.util.*; /* 去除ArrayList集合中的重复元素。 */ class ArrayListTest { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { ArrayList al = new ArrayList(); al.add("java01"); al.add("java02"); al.add("java01"); al.add("java02"); al.add("java01"); // al.add("java03"); /* 在迭代时循环中next调用一次,就要hasNext判断一次。 Iterator it = al.iterator(); while(it.hasNext()) { sop(it.next()+"...."+it.next()); } */ /**/ sop(al); al = singleElement(al); sop(al); } public static ArrayList singleElement(ArrayList al) { //定义一个临时容器。 ArrayList newAl = new ArrayList(); Iterator it = al.iterator(); while(it.hasNext()) { Object obj = it.next(); if(!newAl.contains(obj)) newAl.add(obj); } return newAl; } }
- Collection:
import java.util.*; /* Collection定义了集合框架的共性功能。 1,添加 add(e); addAll(collection); 2,删除 remove(e); removeAll(collection); clear(); 3,判断。 contains(e); isEmpty(); 4,获取 iterator(); size(); 5,获取交集。 retainAll(); 6,集合变数组。 toArray(); 1,add方法的参数类型是Object。以便于接收任意类型对象。 2,集合中存储的都是对象的引用(地址) 什么是迭代器呢? 其实就是集合的取出元素的方式。 如同抓娃娃游戏机中的夹子。 迭代器是取出方式,会直接访问集合中的元素。 所以将迭代器通过内部类的形式来进行描述。 通过容器的iterator()方法获取该内部类的对象。 */ class CollectionDemo { public static void main(String[] args) { method_get(); } public static void method_get() { ArrayList al = new ArrayList(); //1,添加元素。 al.add("java01");//add(Object obj); al.add("java02"); al.add("java03"); al.add("java04"); /* Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。 while(it.hasNext()) { sop(it.next()); } */ for(Iterator it = al.iterator(); it.hasNext() ; ) { sop(it.next()); } } public static void method_2() { ArrayList al1 = new ArrayList(); al1.add("java01"); al1.add("java02"); al1.add("java03"); al1.add("java04"); ArrayList al2 = new ArrayList(); al2.add("java03"); al2.add("java04"); al2.add("java05"); al2.add("java06"); //al1.retainAll(al2);//去交集,al1中只会保留和al2中相同的元素。 al1.removeAll(al2); sop("al1:"+al1); sop("al2:"+al2); } public static void base_method() { //创建一个集合容器。使用Collection接口的子类。ArrayList ArrayList al = new ArrayList(); //1,添加元素。 al.add("java01");//add(Object obj); al.add("java02"); al.add("java03"); al.add("java04"); //打印原集合。 sop("原集合:"+al); //3,删除元素。 //al.remove("java02"); //al.clear();//清空集合。 //4,判断元素。 sop("java03是否存在:"+al.contains("java03")); sop("集合是否为空?"+al.isEmpty()); //2,获取个数。集合长度。 sop("size:"+al.size()); //打印改变后的集合。 sop(al); } public static void sop(Object obj) { System.out.println(obj); } }