Loading... # JavaIO流 - 用于数据的输入输出,所有输入流都是InputStream(数据输入)或Reader(文本输入)的子类,输出流都是OutputStream(数据输出)或Writer(文本输出)的子类。 ## File类 - File类处理文件的基本信息例如文件所在目录,文件长度或文件读写权限等,不进行对文件的读写。 - File类构造函数: - File(String filename); - File(String directoryPath, String filename); - File(File dir, String filename); - filename为文件名,directoryPath是文件路径,dir为一个目录。默认第一种要求该文件与当前在同一路径下。 ### 文件属性 - public String getName():获取文件名 - public boolean canRead():返回文件是否可读 - public boolean canWrite():~可写 - public boolean exists()判断文件是否存在 - public long length()获取文件长度 - public String getParent()获取文件父目录 - public boolean isFile()判断文件是否为文件(不是目录) - public boolean isDirectory()判断是否为一个目录 - public boolean isHidden()判断是否为隐藏文件 - public long lastModified()获取最后被修改的时间(时间戳) ### 目录 - 创建目录: - public boolean mkdir()创建成功返回true,失败或已存在返回false - 列出目录下文件 - public String[] list():列出目录下所有文件 - public File[] listFiles(): 用File对象返回所有文件 - 列出目录下指定类型的文件 - public String[] list(FilenameFilter obj); - public File[] listFiles(FilenameFilter obj); - 其中,FilenameFilter为一个接口,其中有一accept方法 public boolean accept(File dir, String name); 对于一个文件,File对象将调用obj的accept方法,当accept返回为True则会将该文件添加到返回的数组中。 例: ```java // Example10_2.java(Demo) import java.io.*; public class Example10_2 { public static void main(String args[]) { File dirFile = new File("."); FileAccept fileAccept = new FileAccept(); fileAccept.setExtendName("java"); String fileName[] = dirFile.list(fileAccept); for(String name:fileName) { System.out.println(name); } } } //FileAccept.java(Impl) import java.io.*; public class FileAccept implements FilenameFilter { private String extendName; public void setExtendName(String s) { extendName="."+s; } public boolean accept(File dir,String name) { //重写接口中的方法 return name.endsWith(extendName); } } ``` ### 文件的创建与删除 - 当创建一个文件对象后,若文件不存在可以使用方法创建一个文件,也可以用方法删除一个文件。 - public boolean creatNewFile():若不存在文件则将创建一个 - public boolean delete();若存在该文件将删除当前文件 ### 运行可执行文件 - 使用Runtime类声明一个对象,然后使用getRuntime得到一个对象,之后可以使用exec(String command)执行一个命令(command为命令)。 例: ```java import java.io.*; public class Example10_3 { public static void main(String args[]) { try{ Runtime ce=Runtime.getRuntime(); File file=new File("c:/windows","Notepad.exe"); ce.exec(file.getAbsolutePath()); file=new File("C:\\Program Files\\Internet Explorer","IEXPLORE www.sina.com "); ce.exec(file.getAbsolutePath()); } catch(Exception e) { System.out.println(e); } } } ``` ## 文件字节输入输出流 ### 输入 - FileInputStream - 进行文件输入的类 #### 构造方法 - FileInputStream(String name); - FileInputStream(File file); - 其打开一个指向文件的通道,创建文件流时,可能产生异常,例如文件不存在,或者IO错误,因此需要使用try-catch捕获异常 ```java try { FileInputStream in = new FileInputStream("hello.txt"); } catch(IOException e) { System.out.println("File read error:"+e); } ``` #### 使用输入流读取字节 - 可以使用read()顺序读取文件,直到达到文件尾 - int read()以字节为单位读取单个字节,返回整数(0~255),若读到文件尾,返回-1 - int read(byte[] b)尝试读取b.length个字节到数组中,返回实际读取的字节数目,如果到达文件尾返回-1 - int read(byte[] b, int off, int len)尝试读取len个字节到b中,off指定从b的某个位置开始存放读取的数据 #### 关闭流 - 使用close()方法关闭流。 ### 输出流 #### 构造方法 - 除与输入流类似的构造方法外其后可以增加一个boolean类型变量表示是否对文件追加。 - FileOutputStream(String name, boolean append):append为true则在源文件基础上追加 为false则覆盖源文件 - FileOutputStream(String name, boolean append):同理 #### 使用输出流写入字节 - void write(int n):写入单个字节 - void write(byte[] b):写入一个字节数组 - void write(byte[] b, int off, int len):给定字节数组中起始与off取len个字节写入 - void close():关闭字节流 #### 关闭流 - 在使用close()方法关闭后,可以保证缓冲区被写入目的地,若不关闭可能没有写入磁盘 ### 例 - 输出: ```java import java.io.*; public class Example10_5 { public static void main(String args[]) { byte [] a = "新年快乐".getBytes(); byte [] b = "Happy New Year".getBytes(); File file = new File("a.txt"); //输出的目的地 try{ OutputStream out=new FileOutputStream(file); //指向目的地的输出流 System.out.println(file.getName()+"的大小:"+file.length()+"字节");//a.txt的大小:0字节 out.write(a); //向目的地写数据 out.close(); out=new FileOutputStream(file,true); //准备向文件尾加内容 System.out.println(file.getName()+"的大小:"+file.length()+"字节");///a.txt的大小:8字节 out.write(b,0,b.length); System.out.println(file.getName()+"的大小:"+file.length()+"字节");///a.txt的大小:8字节 out.close(); } catch(IOException e) { System.out.println("Error "+e); } } } ``` - 输入: ```java import java.io.*; public class Example10_4 { public static void main(String args[]) { int n=-1; byte [] a=new byte[100]; try{ File f=new File("Example10_4.java"); InputStream in = new FileInputStream(f); while((n=in.read(a,0,100))!=-1) { String s=new String (a,0,n); System.out.print(s); } in.close(); } catch(IOException e) { System.out.println("File read Error"+e); } } } ``` ## 文件字符输入输出流 - 与FileInputStream和FileOutputStream对应的分别是FileReader和FileWriter,分别为Reader和Writer的子类。 - 构造方法有 - FileReader(String name); - FileReader(File file); - FileWriter(String name); - FileWriter(File file); - FileWriter(String name, boolean append); - FileWriter(File file, boolean append); - 其他方法与字节输入输出相同 - 对与FileWriter,执行flush()方法可以直接将缓冲区内容写入磁盘。 ## 缓冲流 - 比FileReader和FileWriter更加高级的流 支持更多的操作 - 构造方法 - BufferReader(Reader in); - BufferWriter(Writer out); - 常用方法 - String readLine()读取下一行 - 对与BufferWriter,newLine向文件写入一个换行符 - 示例 ```java import java.io.*; import java.util.*; public class Example10_7 { public static void main(String args[]) { File fRead = new File("english.txt"); File fWrite = new File("englishCount.txt"); try{ Writer out = new FileWriter(fWrite); BufferedWriter bufferWrite = new BufferedWriter(out); Reader in = new FileReader(fRead); BufferedReader bufferRead =new BufferedReader(in); String str = null; while((str=bufferRead.readLine())!=null) { StringTokenizer fenxi = new StringTokenizer(str); int count=fenxi.countTokens(); str = str+" 句子中单词个数:"+count; bufferWrite.write(str); bufferWrite.newLine(); } bufferWrite.close(); out.close(); in = new FileReader(fWrite); bufferRead =new BufferedReader(in); String s=null; System.out.println(fWrite.getName()+"内容:"); while((s=bufferRead.readLine())!=null) { System.out.println(s); } bufferRead.close(); in.close(); } catch(IOException e) { System.out.println(e.toString()); } } } //english.txt: /* The arrow missed the target. They rejected the union demand. Where does this road go to? Where does this road go to? */ ``` ## 随机流 - RandomAccessFile类支持读写文件, ### 构造方法 - RandomAccessFile(String name, String mode); name指定文件,mode取“r”,“rw”决定该对象对文件的操作类型。 - RandomAccessFile(File file, String mode); 注意:RandomAccessFile流指向文件的时候其不会刷新缓存区。 - 其中有一个方法用来seek(long a)用来定位RandomAccessFile流的读写位置,其中参数a确定要读写的文件光标距离文件开头的位置,使用方法getFilePointer()获取流的当前读写位置。RandomAccessFile对文件的读写更灵活。 ```java import java.io.*; public class Example10_8 { public static void main(String args[]) { RandomAccessFile inAndOut=null; int data[]={1,2,3,4,5,6,7,8,9,10}; try{ inAndOut=new RandomAccessFile("tom.dat","rw"); for(int i=0;i<data.length;i++) { inAndOut.writeInt(data[i]); } for(long i=data.length-1;i>=0;i--) { //一个int型数据占4个字节,inAndOut从 inAndOut.seek(i*4); //文件的第36个字节读取最后面的一个整数, System.out.printf("\t%d",inAndOut.readInt()); //每隔4个字节往前读取一个整数 } inAndOut.close(); } catch(IOException e){} } } ``` ## 对象流 - ObjectInputStream和ObjectOutputStream分别是InputStream和OutputStream类的子类,可以将一个对象读取或者写入到一个文件。 - 构造方法 - ObjectInputStream(InputStream in) - ObjectOutputStream(OutputStream out) 由于两个实例都属于流,应当先创建对文件的输入输出流再进行构造。 - 使用对象输入输出流对对象操作时,要保证对象是序列化的,且其中成员变量也应当是序列化的。Serializable接口中没有方法,因此不需要重写。 - 例 Demo: ```java import java.io.*; public class Example10_13 { public static void main(String args[]) { TV changhong = new TV(); changhong.setName("长虹电视"); changhong.setPrice(5678); File file=new File("television.txt"); try{ FileOutputStream fileOut=new FileOutputStream(file); ObjectOutputStream objectOut=new ObjectOutputStream(fileOut); objectOut.writeObject(changhong); objectOut.close(); FileInputStream fileIn=new FileInputStream(file); ObjectInputStream objectIn=new ObjectInputStream(fileIn); TV xinfei=(TV)objectIn.readObject(); objectIn.close(); xinfei.setName("新飞电视"); xinfei.setPrice(6666); System.out.println("changhong的名字:"+changhong.getName()); System.out.println("changhong的价格:"+changhong.getPrice()); System.out.println("xinfei的名字:"+xinfei.getName()); System.out.println("xinfei的价格:"+xinfei.getPrice()); } catch(ClassNotFoundException event) { System.out.println("不能读出对象"); } catch(IOException event) { System.out.println(event); } } } ``` TV: ```java import java.io.*; public class TV implements Serializable{ String name; int price; public void setName(String s) { name=s; } public void setPrice(int n) { price=n; } public String getName() { return name; } public int getPrice() { return price; } } ``` ### 序列化与对象克隆 - 一般两个对象如果具有相同的引用则具有相同的实体和功能。 有时候我们希望得到一个对象的拷贝,很明显通过上述方法从文件中读入一个对象就是源对象的拷贝。 - 若希望快速得到一个拷贝可以写入时写入内存而不是硬盘。 - 可以将 ```java FileInputStream fileIn = new FileInputStream(file); ObjectInputStream objectIn = new ObjectInputStream(fileIn); FileOutputStream fileOut = new FileOutputStream(file); ObjectOutputStream objectOut = new ObjectOutputStream(fileOut); ``` 改为 ```java ByteArrayInputStream inByte = new ByteArrayInputStream(file); ObjectInputStream objectIn = new ObjectInputStream(inByte); ByteArrayOutputStream outByte = new ByteArrayOutputStream(file); ObjectOutputStream objectOut = new ObjectOutputStream(outByte); ``` 即可 ## 使用Scanner解析文件 - 对于Scanner,先把整个文件读入内存,再进行处理,优点是速度快,但是耗空间。 - 创建Scanner对象 ```java File file = new File("hello.java"); Scanner input = new Scanner(file); ``` input以空格、回车作为标记,调用next()返回下一个元素,hasNext()返回是否还存在下一个元素…… - 使用正则表达式创建Scanner对象 ```java File file = new File("Hello.txt"); Scanner input = new Scanner(file); input.useDelimiter(正则表达式); ``` 例: ```java //student.txt //张三的成绩是72分,李四成绩是69分,刘小林的成绩是95分。 //Java import java.io.*; import java.util.*; public class Example10_16 { public static void main(String args[]) { File file = new File("student.txt"); Scanner sc=null; int count=0; double sum=0; try { double score=0; sc = new Scanner(file); sc.useDelimiter("[^0123456789.]+"); while(sc.hasNextDouble()){ score=sc.nextDouble(); count++; sum=sum+score; System.out.println(score); } double aver=sum/count; System.out.println("平均成绩:"+aver); } catch(Exception exp){ System.out.println(exp); } } } ``` Last modification:April 4, 2022 © Allow specification reprint Like 如果觉得我的文章对你有用,请随意赞赏