Java开发综合实战 教案 项目七 IO操作_第1页
Java开发综合实战 教案 项目七 IO操作_第2页
Java开发综合实战 教案 项目七 IO操作_第3页
Java开发综合实战 教案 项目七 IO操作_第4页
Java开发综合实战 教案 项目七 IO操作_第5页
已阅读5页,还剩21页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java开发综合实战STYLEREFbt1a项目七STYLEREFbt1bI/O操作项目七I/O操作思政目标学会理论联系实际,注意读写文件的安全性。学以致用,注重培养灵活运用所学解决问题的能力。技能目标能够创建、删除、遍历文件和目录能够使用字节流和字符流读写文件能够使用缓冲流和随机流读写文件项目导读Java的I/O操作主要是指使用java.io包的操作类进行输入、输出操作。java.io包提供了全面的I/O接口,其中最重要的是5个类(File、InputStream、OutputStream、Reader、Writer)和一个接口(Serializable),这是掌握I/O操作的核心。本项目将介绍使用File类操作文件和目录,以及读写文件内容的常用方法。任务1使用File类操作文件任务引入在编写进销存管理系统时,小白希望入库和出库商品时,对应的商品信息能自动写入一个指定的文件,用于检查程序是否正常运行。在查看Java的标准库java.io时,小白得知使用其中的File类可以操作文件和目录。那么,使用File对象如何操作文件和目录呢?能否查看文件和目录的属性,并筛选特定的文件呢?知识准备文件是计算机系统中一种非常重要的数据存储形式。Java的标准库java.io提供了File类来操作文件本身,例如,创建、删除、重命名文件,也可获取文件的基本信息,如文件所在的路径、文件名称、大小和修改时间等。一、创建File对象使用File类的构造方法可以创建一个文件对象,File对象既可以表示文件,也可以表示目录。要构造一个File对象,需要传入文件路径,可以是绝对路径,也可以是相对路径。语法格式有如下3种:(1)File(Stringpathname)这种构造方法使用参数pathname指定包含文件名的路径。Windows平台使用\作为路径分隔符,在Java字符串中需要用转义字符\\表示\,也可以直接使用/进行路径分隔。Linux平台使用/作为路径分隔符。例如,下面的代码在D盘指定路径D:/workspace下创建一个名为stars.txt的文本文件://使用绝对路径传入文件路径Filefile1=newFile("D:/workspace/stars.txt");Filefile1=newFile("D:\\workspace\\stars.txt");//使用相对路径传入文件路径Filefile1=newFile("/workspace/stars.txt");Filefile1=newFile("\\workspace\\stars.txt");传入相对路径时,相对路径前面加上当前目录就是绝对路径。上面的示例假设当前目录是D:\。传入相对路径时,可以用.表示当前目录,..表示上级目录。例如,假设当前目录是D:\Demos,下面的代码访问不同路径下的Hello.java。Filefile2=newFile(".\\sub\\Hello.java");//绝对路径是D:\Demos\sub\Hello.javaFilefile3=newFile("..\\sub\\Hello.java");//绝对路径是D:\sub\Hello.java注意:构造一个File对象,即使传入的文件或目录不存在,代码也不会出错,因为构造一个File对象,并不会导致任何磁盘操作。只有在调用File对象的某些方法的时候,才真正进行磁盘操作。(2)File(Stringparent,Stringchild)这种构造方法通过指定父路径parent和子路径child传入文件路径。父路径是磁盘根目录或磁盘中的某个文件夹,如D:/或D:/workspace/。子路径是包含文件类型后缀的文件名称,例如stars.txt。因此,上面的示例代码也可以写成如下形式:Filefile1=newFile("D:/workspace/","stars.txt");Filefile1=newFile("D:\\workspace\\","stars.txt");(3)File(Filef,Stringchild)这种构造方法根据磁盘中的某个文件夹f(称为父文件对象)和要创建的文件名child(称为子文件对象)创建文件对象。例如,上面的示例代码也可以写成如下形式:Filef1=newFile("D:/workspace/");//创建父文件对象Filefile1=newFile(f1,"stars.txt");//绝对路径是D:\workspace\stars.txt二、获取文件属性创建文件对象后,可以调用File类的方法获取文件本身的一些属性,如表10-1所示:表7-1File类的常用方法方法名称说明booleancanRead()判断指定的文件是否能读取booleancanWrite()判断指定的文件可否被写入booleanexists()判断当前File对象是否存在Longlength()返回文件以字节为单位的长度StringgetPath()获取当前File对象的路径字符串StringgetAbsolutePath()获取当前File对象的绝对路径名StringgetName()获取当前File对象的文件名或路径名。如果是路径,则返回最后一级子路径名StringgetParent()获取当前File对象所对应路径(最后一级子路径)的父路径

续表方法名称说明booleanisAbsolute()判断当前File对象表示的文件是否为绝对路径。该方法消除了不同平台的差异,在Windows等系统中,如果路径开头是盘符,则说明它是一个绝对路径;在UNIX/Linux/BSD等系统中,如果路径名以斜线/开头,则表明该对象对应一个绝对路径。booleanisDirectory()判断当前File对象表示的文件是否为一个路径booleanisFile()判断当前File对象是否为文件longlastModified()返回当前File对象的最后修改时间longlength()返回当前File对象表示的文件长度String[]list()返回当前File对象指定的路径文件列表在这里要提请读者注意,File对象有3种形式表示的路径,一种是getPath(),返回构造方法传入的路径;一种是getAbsolutePath(),返回绝对路径;还有一种是getCanonicalPath(),与绝对路径类似,但是返回的是规范路径。提示:由于Windows和Linux的路径分隔符不同,File对象提供了一个静态常量separator表示当前平台的系统分隔符。例如,下面的语句根据当前平台打印路径分隔符。System.out.println(File.separator);如果要分隔连续多个路径字符串,使用静态常量pathSeparator,在Windows系统下,该常量的值是分号。案例——获取文件基本信息本案例利用路径和文件名称构造一个File对象,通过调用File类的方法获取该文件对象的文件名称、路径、长度、最后修改日期等属性信息,并判断该文件对象是否为文件或目录、是否可读取或可写入,以及是否处于隐藏状态。(1)新建一个Java项目FileDemo,在其中添加一个名为FileInfo的类。(2)引入操作文件和日期需要的包java.io.File、java.util.Date,在类中添加主方法,编写代码获取文件信息。具体代码如下所示:importjava.io.File;importjava.util.Date;publicclassFileInfo{publicstaticvoidmain(String[]args){ Stringpath="D:"+File.separator+"workspace"+File.separator; //文件路径 Stringname="shici.txt"; //指定文件名称Filef=newFile(path,name); //使用文件路径和名称构造File对象System.out.println(path+name+"的文件信息如下:");System.out.println("============================================");//调用File类的方法获取文件属性并输出System.out.println("文件名称:"+f.getName());System.out.println("文件路径:"+f.getPath());System.out.println("绝对路径:"+f.getAbsolutePath());System.out.println("文件长度:"+f.length()+"字节");System.out.println("是否文件:"+f.isFile());System.out.println("是否目录:"+(f.isDirectory()?"是目录":"不是目录"));System.out.println("是否可读:"+(f.canRead()?"可读取":"不可读取"));System.out.println("是否可写:"+(f.canWrite()?"可写入":"不可写入"));System.out.println("是否隐藏:"+(f.isHidden()?"是隐藏文件":"不是隐藏文件"));System.out.println("最后修改日期:"+newDate(f.lastModified()));}}(3)运行程序,在控制台窗格中可以看到指定文件的相关信息,如图7-1所示。图7-1运行结果三、创建和删除文件在程序设计中,有时需要读写一些临时文件,可以先创建一个临时文件,然后在不需要时删除该文件。读者要注意的是,无论是创建还是删除文件,通常都先调用exists()方法判断文件是否存在。1.创建文件使用File类创建文件对象后,如果文件对象指向的文件不存在,可以调用createNewFile()方法创建文件,语法格式如下:booleancreateNewFile()该方法在指定目录下创建文件,如果该文件已存在,则不创建。由于该方法使用了关键字throws声明,因此在使用中必须使用try…catch结构捕获异常并处理。例如:Filefile=newFile("D:"+File.separator,"stars.txt");if(!file.exists()){try{file.createNewFile();}Catch(Exceptione){e.printStackTrace();}}上面的代码先创建一个File对象,指定文件的路径和名称。然后调用exists()方法判断文件是否存在,如果不存在,则在指定目录下创建指定的文件。创建文件后,调用File类的renameTo(File)方法,可以将当前File对象指定的文件重命名为给定参数File指定的文件名。调用setReadOnly()方法,可以将文件或文件夹设置为只读。这两个方法的返回值类型均为boolean型。2.删除文件使用File类的delete()方法可以删除指定的文件,语法格式如下:booleandelete()例如:下面的代码先判断指定的文件是否存在,如果存在,则删除文件。Filefile=newFile("D:"+File.separator,"stars.txt");if(file.exists()){file.delete();}如果要在JVM退出时自动删除指定的文件,可以使用deleteOnExit()方法。案例——创建临时文件本案例首先检测指定路径是否存在指定名称的文件,如果有,则删除同名文件后,再创建一个新文件,否则创建该文件。(1)新建一个Java项目FileCreate,在其中添加一个同名的类。(2)引入操作文件需要的包,在类中添加主方法main(),编写实现代码。具体代码如下所示:importjava.io.File;importjava.io.IOException;publicclassFileCreate{ publicstaticvoidmain(String[]args){ Stringdisk="D:"; //定义要创建文件的盘符 Stringchildpath="workspace"; //定义要创建文件的路径段 Stringname="temp.txt"; //定义文件名称 //组合成适应操作系统的路径 Stringpath=disk+File.separator+childpath+File.separator; Stringfilepath=path+name; Filef=newFile(filepath); //创建指向特定文件的文件对象 if(f.exists()){ //判断文件是否存在 System.out.println("该文件已存在,将删除该文件。"); f.delete();//如果存在则先删除 } else{//如果不存在,就创建文件 try{ f.createNewFile(); }catch(IOExceptione){ e.printStackTrace(); } } System.out.println("在路径"+path+"已创建文件"+name); }}上面的代码在操作文件时使用常量File.separator表示分隔符,可以根据程序所在的操作系统自动使用符合本地操作系统要求的分隔符,从而程序可以在任意的操作系统中使用。(3)运行程序,如果在指定位置没有同名的文件,则创建文件,并在控制台窗格中输出相应的提示信息,如图7-2所示。(4)再次运行程序,由于文件已存在,将删除指定位置同名的文件,在控制台窗格中输出相应信息,然后重新创建一个文件,并输出相应信息,如图7-3所示。图7-2指定文件不存在的运行结果图7-3指定文件存在的运行结果四、创建和删除文件夹使用File对象可以指向一个文件夹,然后调用mkdir()方法创建文件夹。如果要创建多级目录,则调用mkdirs()方法。booleanmkdir():创建一个文件夹,路径名由当前File对象指定。创建成功返回true,否则返回false。booleanmkdirs():创建多级目录,路径名由当前File对象指定。与文件操作类似,无论是创建还是删除文件夹都需要调用exists()方法判断文件夹是否存在。如果要删除文件夹,可以调用File类的delete()方法。注意:在删除文件夹时,必须保证指定的文件夹中没有任何内容,才可以用delete()方法成功删除,而且一旦删除,无法恢复。案例——创建多级目录本案例首先判断指定目录下是否存在demo文件夹,如果存在,则进一步判断文件夹是否为空,为空则删除,否则输出提示信息;如果文件夹不存在,则创建该文件夹,并在该文件夹下创建3个子文件夹。(1)新建一个Java项目FolderDemo,在其中添加一个名为FolderCreate的类。(2)引入操作文件需要的包java.io.File,在类中添加主方法,编写代码创建多级目录。具体代码如下所示:importjava.io.File;publicclassFolderCreate{ publicstaticvoidmain(String[]args){ Stringdisk="D:";//定义要创建文件的盘符 Stringchildpath="workspace"+File.separator+"demo"; //文件路径 //使用静态变量separator根据操作系统输出路径分隔符组合成适应操作系统的路径 Stringpath=disk+File.separator+childpath; //创建文件对象,指向path表示的目录 Filef=newFile(path); //调用File对象的exists()方法,判断指定目录是否存在 if(f.exists()){ System.out.println("该文件夹已存在。"); //如果存在,且文件夹内容为空,则删除文件夹 if(f.list().length==0){ System.out.println("该文件夹不包含内容,将删除文件夹"); f.delete();} else System.out.println("该文件夹中包含内容,不能清除,将创建子文件夹"); } System.out.println("创建文件夹……"); //创建文件对象数组,用于存放子文件夹的文件对象 File[]folder=newFile[3]; //使用for循环在指定目录下创建文件夹 for(inti=0;i<3;i++){ //指定目录创建子目录 folder[i]=newFile(path+File.separator+"folder"+(i+1)); if(!folder[i].exists()){ //如果指定文件夹不存在 folder[i].mkdirs();//创建文件夹,包括不存在的父文件夹demo //获取子文件夹的绝对路径并输出 System.out.println("创建文件夹"+folder[i].getAbsolutePath()); } } }}(3)运行程序。如果指定的文件夹不存在,则创建文件夹及其子文件夹,如图7-4所示。此时再次运行程序,在控制台窗格中可以看到程序执行的过程,如图7-5所示。图7-4创建的目录图7-5运行结果从运行结果可以看到,由于指定的demo文件夹已存在且包含内容,因此不能调用delete()方法删除文件夹。在demo文件夹中创建子文件夹时,由于文件夹中包含的子文件夹与要创建的子文件夹同名,因此不再重复创建。五、遍历目录所谓遍历目录,是指访问指定目录中的每一个文件和文件夹,用于查找指定的文件,或列示其中的所有文件。Java在File类中提供了两个列出文件夹内容的方法:list()和listFiles()方法。1.list()方法该方法使用字符串数组返回当前File对象表示的目录中所有的文件和文件夹名称。如果当前File对象不是目录,则返回null。语法格式如下:publicString[]list()提示:list()方法返回的数组中仅包含文件名称,而不包含路径。如果目录中包含同名的文件或文件夹,则返回相同的字符串,这些字符串在数组中不一定按字母顺序出现。例如,以下代码用于列出给定目录D:\test\下的所有文件和文件夹名称:Filefile=newFile("D:"+File.separator+"test"+File.separator);String[]files=file.list();2.listFiles()方法该方法的功能与list()方法相同,不同的是,该方法会列出文件的完整路径,返回值为一个File对象数组。此外,该方法还提供了两种重载方法,可以过滤不想要的文件和目录,语法格式如下://仅列出过滤器指定的文件和子目录publicFile[]listFiles(FilenameFilterfilter)publicFile[]listFiles(FileFilterfilter)使用这两种重载方法时,如果filter为null,则返回所有的文件和子目录。案例——筛选.zip压缩文件本案例构造文件筛选器对象,调用listFiles()方法筛选指定目录下的.zip压缩文件。(1)新建一个Java项目ListFiles,在其中添加一个名为ListFilesDemo的类。(2)引入操作文件需要的包java.io.File和java.io.FilenameFilter,在类中添加主方法,编写代码筛选文件并输出。具体代码如下所示:importjava.io.File;importjava.io.FilenameFilter;publicclassListFilesDemo{ publicstaticvoidmain(String[]args){ Stringdisk="D:"; //定义要创建文件的盘符 Stringchildpath="软件"; //定义要创建文件的路径段 //使用静态变量separator根据操作系统输出路径分隔符组合成适应操作系统的路径 Stringpath=disk+File.separator+childpath; try{ Filef=newFile(path);//创建文件对象,指向path表示的目录 //使用匿名内部类构造文件筛选器对象,筛选以字符串“.zip”结尾的文件 FilenameFilterfilter=newFilenameFilter(){ publicbooleanaccept(Filef,Stringname){ returnname.endsWith(".zip"); } }; //调用listFiles()方法筛选文件对象f,定义File数组存放筛选结果 File[]files=f.listFiles(filter); //遍历数组,输出筛选结果 System.out.println("目录"+path+"下的.zip压缩包有:"); for(Filefile:files) System.out.println(file.getName()); }catch(Exceptione){//捕获异常 System.err.println(e.getMessage()); } }}在调用listFiles()方法时,可能访问不允许读取的文件,从而引发SecurityException,因此在上面的代码中编写了代码捕获异常并处理。(3)运行程序,在控制台窗格中可以输出指定目录下所有的.zip文件,如图7-6所示。图7-6运行结果任务2读写文件内容任务引入小白使用File对象成功地在指定路径创建了一个文本文件,接下来就需要实现数据的读写操作。小白得知Java在java.io包中提供了I/O流相关的类用于读写数据。那么,什么是I/O流呢?在Java中,怎样使用I/O流的类读写数据呢?考虑到执行效率,读写少量的字符和大篇幅的字符内容的方法是否一样呢?知识准备一、流的概念Java以数据流的形式处理输入和输出。流是一组有序的字节或字符集合,根据流的运动方向,可以分为输入流和输出流两种。以计算机内存为参照物,输入流是指从计算机外设读入到内存的数据序列;输出流是指从内存输出到外设的数据序列。根据流中元素的基本单元是一个字节还是一个字符(两个字节),可以将流分为字节流和字符流。例如,从磁盘上读入一个文件中的字符,就是输入字节流;将内存中的字节写入磁盘文件,就是输出字节流。在Java中,所有与输入流有关的类都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类;所有与输出流有关的类都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。这四个类都是抽象类,其子类都有一个共性特点:子类名后缀都是父类名,前缀名都是这个子类的功能名称。二、文件字节流字节流是指处理字节数据的流对象。计算机中的最小数据单元为字节,所以设备上的数据无论是图片、文字还是音视频,都是以二进制方式存储的,以一个byte(字节)为数据单元进行体现。也就是说,字节流可以处理设备上的所有数据。1.文件字节输入流FileInputStreamJava提供了InputStream类创建字节输入流,InputStream类的常用方法如表7-2所示。表7-2InputStream类的常用方法方法说明intread()读取输入流的下一个字节,并返回字节表示的int值(0~255)。如果已读到末尾,返回-1表示不能继续读取可用的字节。intread(byte[]b)读取输入流中b.length长度的字节存放到数组b中,返回实际读取的字节数。如果到达文件末尾,则返回-1intread(byte[]b,intoff,intlen)在输入流中从指定位置读取指定长度的字节,并返回实际读取的字节数。如果到达文件末尾,则返回-1voidmark(intreadlimit)在输入流的当前位置放置一个标记,使用参数readlimit指定输入流在标记位置失效前允许读取的字节数voidreset()将输入指针返回到当前标记处longskip(longarg)在输入流中跳过arg个字节,返回实际跳过的字节数booleanmarkSupported()判断当前流是否支持mark()或reset()方法voidclose()关闭输入流,释放与该流关联的系统资源FileInputStream类是字节输入流InputStream的一个常用子类,用于从文件系统中读取诸如图像数据之类的原始字节流,实现文件流输入。该子类的实例方法都继承自InputStream类,有以下两种格式的构造方法创建指向文件的输入流:FileInputStream(Stringname):创建源为name指定的文件的文件字节输入流。FileInputStream(Filefile):创建源为file指定的文件的文件字节输入流。创建FileInputStream对象后,可以调用从其父类继承的read方法顺序地读取文件,直到文件字节输入流被关闭或到达文件的末尾。在读写I/O流的过程中,可能会发生错误,例如,文件不存在导致无法读取,没有写权限导致写入失败,等等,这些底层错误都会引发IOException异常并抛出。因此,所有与I/O操作相关的代码都必须捕获并处理IOException异常,如下所示。publicabstractintread()throwsIOException完成读取操作后,应调用close()方法显式地关闭输入流。2.文件字节输出流FileOutputStreamJava提供了OutputStream类创建字节输入流,OutputStream类的常用方法如表7-3所示。表7-3OutputStream类的常用方法方法说明voidwrite(intb)将int型参数b最低8位表示的字节写入输出流指向的文件voidwrite(byte[]b)将byte数组中的字节写入输出流指向的文件voidwrite(byte[]b,intoff,intlen)将数组b中从索引off开始的len个字节写入输出流指向的文件voidflush()将缓冲区的内容完全输出并清空缓冲区voidclose()关闭输出流,释放与该流关联的系统资源对应于FileInputStream类输入文件流,字节输出流OuputStream提供了一个常用的子类FileOutputStream,用于实现文件流输出。该子类的实例方法都继承自OutputStream类,有以下两种格式的构造方法创建指向目的地的输出流。FileOutputStream(Stringname):创建目的地为name指定的文件的文件字节输出流。FileOutputStream(Filefile):创建目的地为file指定的文件的文件字节输出流。使用上面两种构造方法创建的文件字节输出流指向目的地文件,如果这个文件已存在,则输出流将刷新该文件;如果文件不存在,Java则自动创建该文件。如果要设置输出流是否自动刷新文件,可以在构造方法中添加一个布尔类型的参数,如下所示:FileOutputStream(Stringname,booleanappend)FileOutputStream(Filefile,booleanappend)当参数append的值为true时,输出流不刷新指向的已存在文件,而是在写入输出流时在文件末尾追加输出流中的数据。如果append的值为false,则自动刷新(即清空)所指向的已存在文件。创建文件字节输出流后,就可以调用其从父类继承的write方法将输出流中的数据顺序地写入文件,直到文件字节输出流被关闭。这里要提请读者注意的是,在向磁盘、网络写入数据时,出于效率的考虑,操作系统并不是输出一个字节就写入一个字节,而是把输出的字节先放到内存的一个缓冲区,等缓冲区写满了,再一次性写入文件或者网络。缓冲区实质上就是一个byte[]数组,写满数据时,OutputStream会自动调用flush()方法强制输出缓冲区内容。如果希望能实时输出内容,就需要手动调用flush()方法。提示:应用程序在运行过程中,如果打开了一个文件进行读写,完成后要及时关闭,释放资源,否则,可能会影响其他应用程序运行。调用close()方法关闭OutputStream及其子类对象之前,程序会自动调用flush()方法输出缓冲区内容。案例——读取文本文件本案例创建一个字节输入流对象,读取一个文本文件中的所有字节并输出,演示InputStream类的使用方法,以及I/O流异常处理的方式。(1)新建一个Java项目ReadFile,在其中添加一个同名的类。(2)引入使用输入流和异常处理需要的包,在类中添加主方法main(),编写实现代码。具体代码如下所示:importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStream;publicclassReadFile{//读取文件可能发生异常,使用throws关键字抛出异常 publicstaticvoidmain(String[]args)throwsIOException{ InputStreamtext=null; //创建一个InputStream对象 try{ //创建一个FileInputStream对象 text=newFileInputStream("D:/java_source/littlestar.txt"); intn; //定义一个int值,用于显示输入流中的字节 while((n=text.read())!=-1){//判断是否到文件末尾 System.out.println(n);//输出字符对应的字节 } }finally{ if(text!=null)text.close();//关闭输入流 } }}上面的代码构造了一个FileInputStream对象,指向磁盘中的文本文件littlestar.txt。如果读取过程中发生了错误,InputStream将没法正确地关闭,资源也就无法及时释放。上面的代码使用try…finally语句保证无论是否发生IO错误,InputStream都能正确地关闭。(3)运行程序,在控制台窗格中可以看到文本文件内容的字节形式,如图7-7所示,对应的文本文件如图7-8所示。图7-7运行结果图7-8文本文件三、文件字符流在处理字符时,会涉及到不同的字符编码,不同的字符编码相应不同的字符编码表。为了便于解析不同类型的字符,Java将字节流和编码表封装成对象,这就是字符流。1.文件字符输入流FileReaderJava提供了Reader类创建字符输入流,其实质是一个能自动编解码的InputStream,是所有字符输入流的父类。Reader类的方法与InputStream类的方法类似,不同的是,Reader类的read()方法的参数是char类型的数組。虽然数据源是字节,但Reader类将读入的byte数据进行了编码,转换为char类型的字符。此外,Read类还提供了一个返回值为boolean类型的ready()方法,用于判断是否准备读取流。FileReader类是Reader类常用的一个子类,必须实现的方法只有read(char[],int,int)和close()。FileReader类使用如下两个构造方法创建文件字符输入流:FileReader(Stringname):创建源为name指定的文件的字符输入流。FileReader(Filefile):创建源为file指定的文件的文件字符输入流。2.文件字符输出流FileWriterJava标准库提供Writer类处理字符输出流,Writer实质上是一个能自动编解码的OutputStream,将char转换为byte并输出,是所有字符输出流的父类。Write类的常用方法如表7-4所示。表7-4Write类的常用方法方法说明voidwrite(intc)写入一个字符voidwrite(char[]c)写入字符数组c中的所有字符voidwrite(char[]c,intoff,intlen)写入字符数组c从索引off开始的len个字符voidwrite(Strings)写入字符串s续表方法说明voidwrite(Strings,intoff,intlen)写入字符串s从索引off开始的len个字符voidflush()将缓冲区的内容完全输出并清空缓冲区voidappend(charc)将指定字符追加到输出流末尾voidappend(charSequencecs)将指定字符序列追加到输出流末尾voidappend(charSequencecs,intstart,intend)将指定字符序列添加到输出流的指定位置voidclose()关闭输出流,释放与该流关联的系统资源FileWriter类是Writer类常用的一个子类,必须实现的方法仅有write(char[],int,int)、flush()和close()。FileWriter类使用如下两个构造方法创建文件字符输出流:FileWriter(Stringname):创建目的地文件为name指定的文件的文件字符输出流。FileWriter(Filefile):创建目的地文件为file指定的文件的文件字符输出流。与FileOutputStream类似,如果目的地文件已存在,通过在构造方法中添加一个布尔类型的参数,可以指定输出流是否刷新目的地文件。如下所示:FileWriter(Stringname,booleanappend)FileWriter(Filefile,booleanappend)案例——创建文件写入诗词本实战在指定路径创建一个文件夹,并在文件夹中创建一个文本文件。然后在文件中写入诗词内容。(1)新建一个Java项目NewFile,在其中添加一个同名的类。(2)引入操作IO流和异常处理需要的包,在类中添加主方法main(),编写实现代码。具体代码如下所示:importjava.io.File;importjava.io.FileWriter;importjava.io.IOException;publicclassNewFile{ publicstaticvoidmain(String[]args)throwsIOException{ Stringpath="D:"+File.separator+"workspace"+File.separator+"newFile";//路径 Stringname="shici.txt"; //定义要创建的文件名称 Filenewfolder=newFile(path); //创建File对象,指向path表示的目录 Filenewfile=newFile(path+File.separator+name);//创建File对象指向文件 if(!newfile.exists()){ //判断指定文件是否存在 //如果不存在,创建文件夹,包括不存在的父文件夹 newfolder.mkdirs(); newfile.createNewFile(); //在指定路径创建文件 System.out.println("在路径"+newfolder+"已创建文件"+name); } try{ FileWriterfw=newFileWriter(newfile);//创建指向文件的输出流fw //调用write()方法,写入缓冲区 fw.write("一曲新词酒一杯,去年天气旧亭台。\n"); fw.write("夕阳西下几时回?\n"); fw.write("无可奈何花落去,似曾相识燕归来。\n"); fw.write("小园香径独徘徊。\n"); fw.flush();//刷新缓冲区,在控制台输出内容 fw.close();//关闭输出流 }catch(IOExceptione){//捕获异常,输出异常消息 System.out.println(e); } }}(3)运行代码,在控制台窗格中可以看到如图7-9所示的提示信息。图7-9运行结果此时,在资源管理器中定位到指定的路径,可以看到创建的文本文件,如图7-10所示。双击打开该文件,可以看到写入的诗词内容,如图7-11所示。图7-10创建的文本文件图7-11写入的诗词内容四、缓冲数据流在大型项目中,如果要传输的内容较多,通常会采用缓冲数据流对I/O进行性能优化。缓冲数据流为I/O流增加了内存缓冲区,数据以块为单位读入读出缓冲区,从而提升操作效率。Java提供BufferedReader类和BufferedWriter类处理缓冲数据流,这两个类分别继承自Reader类和Writer类,以行为单位进行输入和输出,创建的对象分别称为缓冲输入流和缓冲输出流。构造方法如下所示:BufferedReader(Readerin);BufferedWriter(Writerout);从构造方法可以看出,ButteredReader流和ButteredWriter流的源和目的地必须为字符流。对于BufferedReader类,要注意read()方法读取的是单个字符;readLine()方法则可以读取一个文本行,并返回为不带换行符的字符串,如果没有内容,则返回null。对于BufferedWriter类,使用newLine()方法可以写入一个行分隔符。注意:关闭输出流时要首先关闭缓冲输出流,然后关闭缓冲输出流指向的字符输出流。在程序中,只需要关闭缓冲流,其对应的字符流将自动关闭。案例——大小写转换本实战获取键盘输入的字符串,将输入的字符转成大写后输出,直到输入“end”结束程序。(1)新建一个Java项目BufferedDemo,在其中添加一个同名的类。(2)引入操作IO流和异常处理需要的包,在类中添加主方法main(),编写实现代码。具体代码如下所示:importjava.io.BufferedReader;importjava.io.BufferedWriter;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.OutputStreamWriter;publicclassBufferedDemo{ publicstaticvoidmain(String[]args){ System.out.println("请输入要转换为大写的内容:"); //创建输入流,读取键盘输入的内容,并将缓冲区与指定的输入流相关联 BufferedReaderbufr=newBufferedReader(newInputStreamReader(System.in)); //创建输出流,将缓冲区与指定的输出流相关联 BufferedWriterbufw=newBufferedWriter(newOutputStreamWriter(System.out)); Stringline=null; //初始化行位置 try{ while((line=bufr.readLine())!=null){//读取输入的行内容,直到结束 if("end".equals(line))//如果输入的是end,则终止程序 break; bufw.write(line.toUpperCase());//将输入的字符转成大写字符写入到缓冲区 bufw.newLine(); //根据操作系统输出一个相应的换行符 bufw.flush(); //刷新缓冲区,在控制台输出内容 } //关闭缓冲数据流 bufw.close(); bufr.close(); }catch(IOExceptione){//捕获异常,输出异常消息System.out.println(e);}}}(3)运行程序,在控制台窗格中输入要转换为大写的内容,按Enter键即可输出对应的大写内容。如果输入“end”,则结束程序,如图7-12所示。图7-12运行结果 五、随机流前面介绍的读写数据的操作都需要创建指向文件的输入流和输出流,且只能顺序读写。Java还提供了一个既能读文件也能写文件的流,而且可以从任何指定的位置读写文件内容,这就是随机流。随机流使用RandomAccessFile类的以下两个构造方法创建。RandomAccessFile(Stringname,Stringmode)RandomAccessFile(Filefile,Stringmode)这两种构造方法创建源和目的地均为name或file指向的文件,对文件的访问方式为mode的随机流。其中,参数mode有以下几种取值:r:只读,只能从文件中读取内容。rw:可读写,既可以读取文件内容,也可以将数据写入文件。rwd:可读写,对文件内容的修改会同步写入存储设备。rws:可读写,对文件内容的修改和元数据都会同步写入存储设备。在读写文件时,可能会因文件不存在而导致FileNotFoundException异常,应在程序中捕获并处理。提示:如果使用rw模式的RandomAccessFile对象写入的文件不存在,系统会自动创建。创建随机流之后,要使用随机流读写文件,可以执行以下步骤:(1)调用RandomAccessFile类的length()方法获取文件的长度,并指定读写文件的起始位置。(2)调用seek(longposition)方法定位到指定位置。其中参数position是随机流的读写位置距离文件开头的字节个数。使用skipBytes(intn)方法可以将指针移动n个字节。(3)调用读/写方法读写数据。RandomAccessFile类常用的读写方法如表7-5所示。表7-5RandomAccessFile类常用的读写方法方法说明intread()从文件中读取数据的一个字节intread(byte[]b)将内容读取到字节数组b中finalbytereadByte()读取一个字节finalintreadInt()读取int型数据finalvoidwriteBytes(Strings)将字符串s写入文件中,按字节方式处理finalvoidwriteInt(intn)将int型数据n写入文件(4)操作完成后,调用close()方法关闭流。案例——随机读写商品信息本案例利用RandomAccessFile对象在文件中写入商品信息,然后反序读取商品信息并输出。(1)在Eclipse中新建一个名为ProductInfo的Java项目。然后在其中添加一个名为Entering.java的类。(2)在Entering.java类中定义main()方法,指定要进行操作的文件,并创建一个RandomAccessFile对象用于读写文件。接下来使用RandomAccessFile对象在文件中写入商品信息数据,然后调用静态成员方法output()反序读取写入的商品信息并输出。具体代码如下所示:importjava.io.File;importjava.io.RandomAccessFile;publicclassEntering{ //在main()方法中抛出异常,交由JVM处理 publicstaticvoidmain(String[]args)throwsException{ //定义文件路径和文件名 Stringparent="D:"+File.separator+"workspace"+File.separator+"ProductInfo"; Stringname="products.txt"; Filefile=newFile(parent,name); //创建文件对象指向文件 RandomAccessFileraf=null; //声明随机流对象 //以读写方式打开文件,会自动创建指定的文件 raf=newRandomAccessFile(file,"rw"); String[]pro_name={"cup","book","pencil"};//8个字节的商品名称 int[]num={20,35,55}; //4个字节的商品数量 //利用循环语句依次写入商品名称和数量 for(inti=0;i<pro_name.length;i++){ raf.writeBytes(pro_name[i]); raf.writeInt(num[i]); } output(file,raf); //调用静态方法读取并输出信息 raf.close(); //关闭随机流 } //定义静态成员方法读取文件内容并输出 publicstaticvoidoutput(Filefile,RandomAccessFileraf){ Stringread_name=null; //声明读取的商品名称 intread_num; //声明读取的商品数量 //利用循环语句反序读取各件商品的名称和数量并输出 for(intposition=24;position>=0;position=position-12){ try{ byteb[]=newbyte[8]; //存放读取的商品名称 raf.seek(position); //定位开始读取的位置 //利用循环语句读取商品名称,存放在数组b中 for(inti=0;i<b.length;i++) b[i]=raf.readByte(); read_name=newString(b); //将字节数组转换为字符串 read_num=raf.readInt(); //读取商品数量 System.out.println("第"+(position/12+1)+"件商品>品名:"+read_name+"\t数量:"+read_num); //输出商品信息 }catch(Exceptione){ e.printStackTrace(); } } }}由于RandomAccessFile对象按字节方式将内容读取到字节数组,长度为8位。因此本例为了保证可以进行随机读取,写入的商品名称字符串都是8个字节,商品数量是固定的4个字节,也就是说每条商品信息为12个字节。在定义main()方法时使用了关键字throws声明,因此在main()方法体中不用再分别处理创建随机流、写入数据和关闭随机流时可能会产生的异常。在定义静态成员方法output()时,没有使用关键字throws声明,所以要在方法体中使用try…catch结构捕获并处理读取数据、移动读指针位置可能产生的异常。(3)运行程序,即可在指定路径创建文件products.txt,并依次写入数组pro_name和num中的数据。然后反序读取文件中各条商品信息并输出,如图7-13所示。图7-13运行结果项目总结项目实战在上一章的项目实战中已实现了进销存管理系统的基本功能。本章将在之前的项目基础上添加文件操作,将商品入库和出库操作的数据写入一个文本文件中,生成一个简单的进销报表。(1)复制并粘贴“进销存管理系统V6.0”,在CopyProject对话框中修改项目名称为“进销存管理系统V7.0”,然后单击Copy按钮关闭对话框。(2)打开Controllers.java,在该文件中添加writeData()方法,用于将商品入库、出库的信息写入指定的文件。具体代码如下: publicvoidwriteData(Stringstr,Goodsgoods)throwsIOException{ //设置时间格式 SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss"); Stringtime=sdf.format(System.currentTimeMillis());//获取当前时间 //定义要创建目录的相对路径 Stringpath="."+File.separator+"src"+File.separator+"report"; Stringname="record.txt"; //定义要创建的文件名称 Filefolder=newFile(path); //创建File对象,指向path表示的目录 //创建File对象,指向特定路径的文件 Filefile=newFile(path+File.separator+name); if(!file.exists()){ //判断指定文件是否存在 //如果不存在,创建文件夹,包括不存在的父文件夹report folder.mkdirs(); file.createNewFile(); //在指定路径创建文件 } try{ //创建输出流fw,写入输出流时不刷新文件,而是追加数据 FileWriterfw=newFileWriter(file,true); //调用write()方法,写入缓冲区 fw.write(time+"\t"+goods.getName()+"\t"+goods.getNu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论