IO操作三大类:1、File类,文件操作 2、字节操作 3、字符操作
File类:是IO包中唯一代表磁盘文件本身的对象,File类定义了一些与平台无关的方法来操纵文件,通过调用File类提供的各种方法,能够创建、删除、重命名文件,判断文件的读写权限及是否存在,设置和查询文件最近的修改时间。
在D:盘根目录下创建一个demo.ext文件:
import java.io.*; public class JavaDemo148{ public static void main(String args[]){ File f = new File("d:\\demo.txt");//构造方法中给一个路径作为参数 try{ f.createNewFile() ;//创建文件 }catch (Exception e){} } } |
通过程序判断文件是否存在:
import java.io.*; public class JavaDemo149{ public static void main(String args[]){ File f = new File("d:\\demo.txt");//构造方法中给一个路径作为参数 if (f.exists()){//exists()判断文件是否存在 System.out.println("文件存在"); }else{ System.out.println("文件不存在"); } } } |
如果文件在删除,如果文件不存在创建:
import java.io.*; public class JavaDemo151{ public static void main(String args[]){ File f = new File("d:\\demo.txt"); if (f.exists()){ f.delete(); }else{ try { f.createNewFile(); } catch (Exception e){} } } } |
import java.io.*; public class J121{ public static void main(String args[]){ File f = new File("D:/demo.txt"); if (f.exists()){ f.delete(); }else{ try{ f.createNewFile(); }catch (Exception e){} } System.out.println("文件名:"+f.getName()); System.out.println("文件路径:"+f.getPath()); System.out.println("绝对路径:"+f.getAbsolutePath()); System.out.println("父文件夹名称呢过:"+f.getParent()); System.out.println(f.exists()?"文件存在":"文件不存在"); System.out.println(f.canRead()?"文件可读":"文件不可读"); System.out.println(f.isDirectory()?"是目录":"不是目录"); System.out.println(f.isFile()?"是文件":"不是文件"); System.out.println(f.isAbsolute()?"是绝对路径":"不是绝对路径"); System.out.println("文件最后的修改时间:"+f.lastModified()); System.out.println("文件的大小:"+f.length()+"Bytes"); } } |
取出D:\\JaTest\\JavaDemo中的文件。
import java.io.*; public class JavaDemo152{ public static void main(String args[]){ File f = new File("D:\\JaTest\\JavaDemo"); if (f.isDirectory()){//判断目录是否正确 String str[] = f.list();//列出此目录下的全部文件此方法返回的是String数组 for (int i = 0;i<str.length ;i++ ){ System.out.println(str[i]); } }else{ System.out.println("不是一个目录"); } } } |
取出D:盘下的全部文件。递归:一个方法自己调用自己。
import java.io.* ; public class JavaDemo153{ public static void main(String args[]){ loop("d:\\") ; } public static void loop(String dir){ File f = new File(dir) ; String str[] = null ; if(f.isDirectory()){ str = f.list() ; if(str != null){ for(int i=0;i<str.length;i++){ loop(dir+"\"+str[i]) ; } } } System.out.println(dir) ; } }; |
import java.io.*; public class J{ public static void main(String args[]) { File f = new File("D:\\"); loop(f); } public static void loop(File file){ if (file.isDirectory()){ File lis[] = file.listFiles(); if (lis != null){ for (int i=0;i<lis.length ;i++ ) { loop(lis[i]); } } System.out.println(file); } } } |
出于安全考虑小程序不能实现文件I/O流。
File类:与文件操作有关;
RandomAccessFile类:随即访问类,与文件内容有关,但此类有一个缺点,如果要实现随机访问,则需要数据长度一致。
import java.io.*; public class JavaDemo154{ public static void main(String args[]) throws Exception{ RandomAccessFile raf1 = new RandomAccessFile("D:\\demo.txt","rw"); // 随机读取有一个限制,就是说如果要进行操作,则必须指定好数据的存储长度 // 保存姓名(8位字符串)和年龄(int 4): String name = "liyan "; int age = 22; raf1.write(name.getBytes()); raf1.writeInt(age); name = "lisi " ; age = 30 ; raf1.write(name.getBytes()) ; raf1.writeInt(age) ; name = "wangwu " ; age = 33 ; raf1.write(name.getBytes()) ; raf1.writeInt(age) ; raf1.close() ; RandomAccessFile raf2 = new RandomAccessFile("D:\\demo.txt","r"); raf2.skipBytes(12) ;//跳过12位,读取第二个人的姓名和年龄 byte b[] = new byte[8]; raf2.read(b); int rage = raf2.readInt(); System.out.println(new String(b)+"----->"+rage); } } |
public class RandomAccessFileDemo02 { public static void main(String[] args) throws Exception{ File file = new File("D:"+File.separator+"demo.txt"); RandomAccessFile raf = new RandomAccessFile(file, "r"); byte bname[] =new byte[8]; int age = 0; raf.skipBytes(12);//跳过12字节 System.out.println("第二个人信息:"); for (int i = 0;i<bname.length;i++){ bname[i] = raf.readByte(); } age = raf.readInt(); System.out.println("姓名:"+new String(bname)); System.out.println("年龄:"+age); raf.seek(0);//回到开始位置 System.out.println("第一个人信息:"); for(int i =0;i<8;i++){ bname[i] = raf.readByte(); } age = raf.readInt(); System.out.println("姓名:"+new String(bname)); System.out.println("年龄:"+age); raf.skipBytes(12);//跳过12字节 System.out.println("第三个人信息:"); for (int i = 0;i<8;i++){ bname[i] = raf.readByte(); } age = raf.readInt(); raf.close(); System.out.println("姓名:"+new String(bname)); System.out.println("年龄:"+age); } } |
| 字节流 | 字符流 |
输入 | InputStream | Reader |
输出 | OutputSteam | Writer |
在Java中上述四种类都是抽象类,必须通过子类实例化。向文件中打印一句话:
import java.io.*; public class JavaDemo155{ public static void main(String args[]){ File f = new File("D:\\demo.txt");//1、用File找到要操作的文件 OutputStream out = null; try{ out = new FileOutputStream(f);//2、通过子类实例化,传入File类对象 }catch (Exception e){} String str = "Hello World...."; byte bstr[] = str.getBytes();//3、将字符转化为byte数组 try{ out.write(bstr);//4、将bytes数组写入到文件之中str中的内容 //out.write(str.getBytes());也可直接转换为Byte数组 }catch (Exception e){} try{ out.close();//5、一定要关闭操作 }catch (Exception e){} } } |
InputStream、OutputStream所操作的都是字节,所有数据都要通过byte数组操作。
import java.io.*; public class JavaDemo156{ public static void main(String args[]){ File f = new File("D:\\demo.txt");//1、用File找到要操作的文件 InputStream in = null; try{ in = new FileInputStream(f); }catch (Exception e){} byte b[] =new byte[500]; int len = 0; try{ len = in.read(b); }catch (Exception e){} try{ in.close(); }catch (Exception e){} System.out.println(new String(b,0,len));//从0——len的长度 } } |
java提供了另外两套类,Reader、Writer操作字符。
import java.io.*; public class JavaDemo157{ public static void main(String args[]){ File f = new File("D:\\demo.txt"); Writer out = null; try{ out = new FileWriter(f); }catch (Exception e){} String str = "Hello World....."; try{ out.write(str); out.flush();// 表示清空缓存 }catch (Exception e){} /*try{ out.close(); }catch (Exception e) {}*/ } } |
字符流输出时如果不关闭则无法将内容写入到文件,原因是如果字符流不关闭则内存中的数据不会强制性的输出到文件,字符流操作使用了缓存,在关闭时会强制性的清空缓存,也可以使用flush()方法手工清空。字符流用到了缓存,字节流没有,不关闭也能写入。
import java.io.*; public class JavaDemo158{ public static void main(String args[]){ File f = new File("D:\\demo.txt");//1、用File找到要操作的文件 Reader in = null; try{ in = new FileReader(f); }catch (Exception e){} char c[] = new char[500];//Reader读取的时char数组 int len = 0; try{ len = in.read(c); }catch (Exception e){} try{ in.close(); }catch (Exception e){} System.out.println(new String(c,0,len));//从0——len的长度 } } |
管道流处理两个线程之间的通信
import java.io.* ; class SendDemo implements Runnable{// 定义一个发送者 private PipedOutputStream out ; public SendDemo(){ out = new PipedOutputStream() ; } public PipedOutputStream getOut(){ return this.out ; } public void run(){ String str = "Hello MLDN" ; try{ out.write(str.getBytes()) ; out.close() ; }catch (Exception e){} System.out.println("SendDemo --> 发送的内容:"+str) ; } }; class ReceDemo implements Runnable{ private PipedInputStream in = null ; public ReceDemo(){ in = new PipedInputStream() ; } public PipedInputStream getIn(){ return this.in ; } public void run(){ byte b[] = new byte[1024] ; int len = 0 ; try{ len = in.read(b) ; in.close() ; }catch (Exception e){ System.out.println(e) ; } System.out.println("ReceDemo --> 收到的内容是:"+new String(b,0,len)) ; } }; public class JavaDemo159{ public static void main(String args[]){ SendDemo sd = new SendDemo() ; ReceDemo rd = new ReceDemo() ; Thread send = new Thread(sd) ; Thread rece = new Thread(rd) ; PipedOutputStream out = sd.getOut() ; // 将两个线程进行连接 PipedInputStream in = rd.getIn() ;//得到自己的实例 try{// 将输出连接到输入 out.connect(in) ; }catch (Exception e){} send.start() ; rece.start() ; } }; |
JDK中提供了ByteArrayInputStream和ByteArrayOuptStream两个类可以是实现类似内存虚拟文件的功能,全部在内存中完成。
import java.io.*; public class JavaDemo160{ public static void main(String args[]){ String str = "LXHMLDN" ;// 字符串都是大写的,现在要求可以将字符串变位小写 byte[] b = str.getBytes() ; ByteArrayInputStream in = new ByteArrayInputStream(b) ; ByteArrayOutputStream out = new ByteArrayOutputStream() ; // 程序中现在要求是将大写变为小写 // 只能一个一个字节的读 int c = 0 ; while((c=in.read())!=-1) {// 如果没有读到低,则不会是-1 int ch = (int)Character.toLowerCase((char)c) ; out.write(ch) ;// 向输出流中写 } b = out.toByteArray() ; System.out.println("内容为:"+new String(b)) ; } } |
System类管理标准输入\输出流和错误流,System.out把输出送到缺省的现实(显示器),System.in从标准输入获取输入(键盘),System.err把错误送到缺省显示,每当main方法被执行时,就会自动生成上述对象。
import java.io.*; public class JavaDemo161{ public static void main(String args[]) throws Exception { OutputStream out = System.out;//System.out是PrintStream类型,是OutputStream的子类 String str = "Rock---->Lee"; out.write(str.getBytes()); //out对象具备了向屏幕输出打印的功能,通过子类实例化完成不同的功能 out.close(); } } |
PrintStream/PrintWriter实际上是打印流,比普通的OutputStream/Writer提供了更多打印数据的方法。OutputStreamàStringàbyte[]
import java.io.*; public class JavaDemo162 { public static void main(String args[])throws Exception{ File f = new File("D:\\demo.txt"); //PrintWriter out = new PrintWriter(new FileWriter(f)); PrintWriter out = new PrintWriter(System.out);//向屏幕打印 out.println(true); out.println(30); out.println("Rock Lee"); out.close(); } } |
使用System.in为InputStream实例化后,内容可以输入,但程序有两个问题:1、输入长度受限制 2、输入中文超过了长度,可能出现乱码
import java.io.*; public class JavaDemo163{ public static void main(String args[])throws Exception{ System.out.print("请用户输入内容:"); InputStream in = System.in;//数据等待键盘的输入 byte b[] = new byte[1024]; int len = in.read(b);//读的内容为用户输入的 in.close(); System.out.println("用户输入的内容:"+new String(b,0,len)); } } |
如果一次性读取,则不会出现乱码问题,需要将输入的数据放入到一个缓存之中
import java.io.*; public class JavaDemo165{ public static void main(String args[]) throws Exception{ //准备从键盘输入中读取数据 BufferedReader buf = new BufferedReader(new InputStreamReader(System.in)); String str = buf.readLine(); System.out.println("输入的内容:"+str); } } |
BufferedReader操作的是字符,System.in是InputStream类型,要通过转换,转换过程在内存中完成,在文件中所有数据最后都要保存为字节。
System.inàInputStream(字节)àWriter(字符)使用以下两套类完成转换:
InputStreamReader:将输入的内容由字节变成字符
OutputStreamWriter:将输出的内容由字符变成字节
文件(字节)à内存à字符
import java.io.*; public class JavaDemo166{ public static void main(String args[])throws Exception{ //准备从键盘输入中读取数据 BufferedReader buf = new BufferedReader(new InputStreamReader(System.in)); for( int i=0;i<2;i++){ System.out.println("输入数据:"); String str = buf.readLine(); System.out.println("输入的内容:"+str); System.out.println("-----------------------------------------------"); } } } |
输入两个数字,进行两个数字相加,Stringàint
import java.io.*; public class JavaDemo167{ public static void main(String args[]){ String str = "2";//如果不是数字会有问题 int i = Integer.parseInt(str); System.out.println(i+2); } } |
import java.io.*; public class JavaDemo168{ public static void main(String args[])throws Exception{ BufferedReader buf = new BufferedReader(new InputStreamReader(System.in)); int i1=0; int i2=0; String str = null; try{ System.out.println("输入第一个数字:"); str = buf.readLine(); i1 = Integer.parseInt(str); System.out.println("输入第二个数字:"); str = buf.readLine(); i2 = Integer.parseInt(str); System.out.println("两数和:"+(i1+i2)); }catch (Exception e){ System.out.println("输入格式错误"); } } } |
GBK:繁体和简体的字符集;
GB2312:主要是简体中文;
ISO8859-1:国际通用编码。
import java.io.*; public class JavaDemo169{ public static void main(String args[]){ System.getProperties().list(System.out); //查看JVM当前设置的属性 } } |
file.encoding=GBK:JVM中默认的文件编码。
不过两个编码不匹配,则在保存时会出现乱码。
import java.io.*; public class JavaDemo170{ public static void main(String args[]) throws Exception{ OutputStream out = new FileOutputStream(new File("D:\\JaTest\\IOTestDemo.txt")); String str = "中文"; out.write(str.getBytes("ISO8859-1"));//中文会有问题,英文不会 out.close(); } } |
乱码产生的根本原因:两个操作间的字符集没有统一。
SequenceInputStream:用于合并两个文件,接收的参数为InputStream类型
import java.io.*; public class JavaDemo171{ public static void main(String args[])throws Exception{ InputStream in1 = new FileInputStream(new File("D:\\JaTest\\IOTest1.txt")); InputStream in2 = new FileInputStream(new File("D:\\JaTest\\IOTest2.txt")); OutputStream out = new FileOutputStream(new File("D:\\JaTest\\IOTestDemo.txt")); SequenceInputStream seq = new SequenceInputStream(in1,in2);//将两个文件合并 int c = 0; while ((c=seq.read())!=-1) { out.write(c); } in1.close(); in2.close(); out.close(); } } |
对象的序列化:把对象写入到流中;对象的反序列化:从流中恢复对象。
序列化优点在于即使程序运行结束,对象仍然可以被保存下来,对象所在的类必须实现Serializable接口,才能被序列化。
import java.io.*; class Person implements Serializable{ private int age;//private int transient age;transient表示不希望被序列化 private String name; public Person(String name,int age){ this.name = name; this.age = age; } public String toString(){ return "Name is "+this.name+",Age is "+this.age; } } public class JavaDemo172{ public static void main(String args[])throws Exception{ //Person per = new Person("Rock",30); //ser(per); System.out.println(dser()); } public static void ser(Person per)throws Exception{//建立一个方法用于完成对象序列化 ObjectOutputStream oos = null; oos = new ObjectOutputStream(new FileOutputStream(new File("D:\\Jatest\\IOTestDemo.txt"))); oos.writeObject(per); oos.close(); } public static Person dser()throws Exception{ ObjectInputStream ois = null; ois = new ObjectInputStream(new FileInputStream(new File("D:\\Jatest\\IOTestDemo.txt"))); Object obj = ois.readObject(); ois.close(); return (Person)obj; } } |
Serializable只是一个声明接口,没有覆写任何一个方法,表示此类可以被序列化。