201711671215《Java程序设计》第10周学习总结
教材学习内容总结
第10章:输入、输出流
输入、输出流提供一条通道程序,可以使用这条通道读取源中的数据或把数据传送到目的地。把输入流的指向称作源,程序从指向源的输入流中读取源中的数据;而输出流的指向是数据要去的一个目的地,程序通过向输出流中写入数据把数据传送到目的地。
重点:通过文件流读写数据,各种数据流的区别。掌握流的连接思想。
难点:流的连接思想及各种数据流的使用。
一、File类
1 File类的对象主要用来获取文件本身的一些信息,例如文件所在的目录、文件的长度或文件读写权限等,不涉及对文件的读写操作;创建一个File对象的构造方法有3个:
File(String filename);
File(String directoryPath,String filename);
File(File dir,String filename);
//filename是文件名字,directoryPath是文件的路径,dir为一个目录。使用File(String filename)创建文件时,该文件被认为与当前应用程序在同一目录
2 文件的属性
File类的下列方法获取文件本身的一些信息:
--public String getName() 获取文件的名字
--public boolean canRead() 判断文件是否是可读的
--public boolean canWrite() 判断文件是否是课被写入的
--public boolean exits() 判断文件是否存在
--public long length() 获取文件的长度(单位是字节)
--public String getAbsolutePath() 获取文件的绝对路径
--public String getParent() 获取文件的父目录
--public boolean isFile() 判断文件是否是一个普通文件,而不是目录
--public boolean isDirectory() 判断文件是否是一个目录
--public boolean isHidden() 判断文件是否是隐藏文件
--public long lastModified() 获取文件最后修改的时间(时间是从1970年午夜至文件最后修改时刻的毫秒数)
3 目录
--创建目录:File对象调用方法public boolean mkdir()创建一个目录,如果创建成功返回true,否则返回false(如果该目录已经存在将返回false)
--列出目录中的文件:-public String[] list() 用字符串形式返回目录下的全部文件
-public File[] listFiles() 用File对象形式返回目录下的全部文件
-public String[] list(FilenameFilter obj) 用字符串形式返回目录下的指定类型的所有文件
-public File[] listFiles(FilenameFilter obj) 用File对象形式返回目录下的指定类型所有文件
上述两个方法的参数FilenameFilter是一个接口,该接口有一个方法:
-public boolean accept(File dir,String name);
File对象dirFile 调用list方法时,需向该方法传递一个实现FilenameFilter接口的对象,list方法执行时,参数obj不断回调接口方法accept(File dir,String name),该方法中的参数dir为调用list的当前目录dirFile,参数name被实例化为dirFile 目录中的一个文件名,当接口方法返回true 时,list方法就将名字为name的文件存放到返回的数组中。
4 文件的创建和删除
当使用File类创建一个文件对象后,例如
File file = new File("c:\\myletter","letter.txt");
如果c:\myletter目录中没有名字为letter.txt文件,文件对象file调用方法
public boolean createNewFile();
可以在c:\myletter目录下创建一个letter文件。
文件调用方法 public boolean delete() 可以删除当前文件,例如: file.delete();
5 运行可执行文件
用Runtime类声明一个对象(Runtime 类在java.lang包):Runtime ec;
然后使用该类的getRuntime()静态方法创建这个对象:
ec = Runtime.getRuntime();
ec可以调用 exec(String command)方法打开本地机器上的可执行文件或执行一个操作。
二、文件字节输入流
1 使用输入流通常包括4个基本步骤:设定输入流的源,创建指向源的输入流,让输入流读取源中的数据,关闭输入流。
当文件读取需求较简单时,可以使用FileInputStream(文件字节输入流),该类是InputStream类的子类(以字节为单位读取文件),该类的实例方法都是从InputStream类继承来的。
构造方法:
FileInputStream(String name); //使用给定的文件名name创建FileInputStream流
FileInputStream(File file); //使用File对象创建FileInputStream流
参数name和file指定的文件称为输入流的源。
2 使用输入流读取字节
文件字节调用从父类继承的read方法顺序地读取文件,只有不关闭流,每次调用read方法就顺序地读取文件中的其余内容,知道文件的末尾或文件字节输入流被关闭。
--int read() 读取单个字节的数据,返回字节值(0~255整数),如果未读出字节就返回 -1。
--int read(byte b[]) 读取b.length个字节到字节数组b中,返回实际读取的字节数。如果到达文件的末尾,则返回-1.
--int read(byte b[],int off,int len) 读取len个字节到字节数组b中,并返回实际读取的字节数目。如果到达文件的末尾,则返回-1,参数 off 指定从字节数组的某个位置开始存放读取的数据。
3 关闭流
输入流都提供了关闭方法close(),当使用完流后,显式地关闭任何打开的流是一个良好的习惯;如果没有关闭那些被打开的流,那么可能不允许另一个程序操作这些流所用的资源。
三、文件字节输出流
使用输出流通常包括4个基本步骤:给出输出流的目的地,创建指向目的地的输出流,让输出流的数据写入到目的地,关闭输出流。当文件写入需求较简单时,可以使用FileOutStream类(文件字节输出流),它是OutputStream类的子类(以以字节为单位向文件写入内容),该类的实例方法都是从OutputStream类继承来的。
1 构造方法:使用FileOutputStream 类的下列具有刷新功能的构造方法创建指向文件的输出流
FileOutputStream(String name);
FileOutputStream(File file);
参数name和file指定的文件称为输出流的目的地。
FileOutputStream输出流开通一个到达文件的通道(目的地就是这个文件,输出流指向这个文件)。需要注意的是:如果输出流指定的文件不存在,Java就会创建该文件,如果指向的文件已存在,输出流将刷新该文件(使得文件的长度为0)
也可以实验FileOutputStream 类的下列能选择是否具有刷新功能的构造方法创建指向文件的输出流:
FileOutputStresm(String name,boolean sppend);
FileOutputStresm(File file,boolean sppend);
如果参数append取值true,输出流不会刷新所指向的文件,输出流的write的方法将从文件的末尾开始向文件写入数据,参数取值false,输出流将刷新所指向的文件。
2 使用输出流写字节
输出流的write方法以字节单位向目的地写数据,
--void write(int n) 向目的地写入单个字节
--void write(byte b[]) 向目的地写入一个字节数组
--void write(byte b[],int off,int len) 从字节数组中偏移量off处取len个字节写到目的地
3 关闭流
调用方法 : void close(); //可以保证操作系统把流缓冲区的内容写到它的目的地,及关闭输出流可以把该流所用的缓冲区的内容冲洗掉(通常冲洗到磁盘文件)
四、文件字符输入、输出流
1 文件字符输入流及输出流的构造方法如下:
FileReader(String filename);
FileReader(File filename);
FileWriter(String filename);
FileWriter(File filename);
FileWriter(String filename,boolean append);
FileWriter(File filename,boolean append);
2 对于Writer流,write方法将数据首先写入到缓冲区,每当缓冲区溢出时,缓冲区的内容被自动写入到目的地,如果关闭流,缓冲区的内容会立刻被写入到目的地。流调用flush()方法可以立刻冲洗当前缓冲区,即将缓冲区的内容写入到目的地。
Reader类提供的read方法以字符为单位顺序读取源中的数据。
五、缓冲流
BufferedReader 和 BufferedWriter 类创建的对象称为缓冲输入、输出流,二者增加了读写文件的能力;二者的源和目的地必须是字符输入流和字符输出流。
构造方法:
BufferedReader(Reader in);
BufferedWriter(Writer out);
-BufferedReader 和 BufferedWriter 类读写文件的方法:
--readLine() 读取文件行
--write(String s,int off,int len) 把字符串s写到文件中
--newLine(); 向文件写入一个回行符
注:关闭输出流时要首先关闭缓冲输出流,然后关闭缓冲输出流指向的流,即先关闭上层流再关闭底层流。在编写代码时只需关闭上层流,那么上层流的底层流将自动关闭。
六、随机流
RandomAccessFile 类创建的流称作随机流,与上述的输入、输出流不同,RandomAccessFile类既不是InputStream 类的子类,也不是OutputStream 类的子类,但是RandomAccessFile 类创建的流的指向既可以作为流的源,也可以作为流的目的地。
构造方法如下:
RandomAccessFile(String name,String mode);
RandomAccessFile(File file,String mode);
参数name 用来确定一个文件名,参数file是一个File对象,给出创建的流的源也是流目的地,参数mode 取 r(只读)或rw(可读写),决定创建的流对文件的访问权限。
其中有几个相关方法:
seek(long a) 定位RandomAccessFile流的读写位置
getFilePointer() 获取流的当前读写位置
readLine()方法在读取含有非ASCII字符的文件时出现“乱码”现象的解决方法:
1、读取String str = in.readLine();
2、用"iso-8859-1"重新编码 btye b[]= str.getBytes("iso-8859-1");
3、使用当前机器的默认编码将字节数组转化为字符串:String content = new String(b);
七、数组流
流的源和目的地除了可以是文件外,还可以是计算机内存;
字节数组流:
1 字节数组输入流ByteArrayInputStream和字节数组输出流ByteArrayOuputStream 分别使用字节数组作为流的源和目的地,构造方法如下:
ByteArrayInputStream(byte [] buf);
ByteArrayInputStream(byte [] buf,int offest,int length);
第一个构造方法的构造的字节数组的源是参数buf指定的数组的全部字节单元;第二个构造方法构造的字节数组的源是buf指定的数组从offset 处按顺序取得length个字节单元。
其常用的方法有:public int read(); 顺序地从源中读出一个字节; public int read(byte [] b,int off,int len)顺序地从源中读出参数len指定的字节数;
2 字节数组输出流的构造方法及常用方法:
ByteArrayOuputStream();
ByteArrayOuputStream(int size);
public void write(int b); //顺序向缓冲区写入一个字节
public void write(byte[] b,int off,int len); //将参数b中指定的len个字节顺序写入缓冲区
public byte[] toByteArray(); //返回输出流写入到缓冲区的全部字节
第一个构造方法构造的字节数组输出流指向一个默认大小为32字节的缓冲区,如果输出流向缓冲区写入的字节个数大于缓冲区时,缓冲区的容量会自动增加;第二个构造方法构造的字节数组输出流指向的缓冲区的初始大小由参数size决定,如果输出流向缓冲区写入的字节个数大于缓冲区时,缓冲区容量会自动增加。
3 字符数组流:与字节数组流对应的字符数组流CharArrayReader 和CharArrayWriter 类,字符数组流分别使用字符数组作为流的源和目标。
八、数据流
和 DataOuputStream类创建的对象称为数据输入流和数据输出流。
构造方法为:
DataInputStream(InputStream in); //创建的数据输入流指向一个由参数in指定的底层输入流
DataOutputStream(OutputStream out);//创建的数据输出流指向一个由参数out指定的底层输出流
九、对象流
ObjectInputStream 和 ObjectOutputStream 类创建的对象称为对象输入流和对象输出流,构造方法是:
ObjectInputStream(InputStream in);
ObjectOutputStream(OutputStream out);
相关方法:
--writeObject(Object obj) 将一个对象obj写入到一个文件
--readObject() 读取一个对象到程序中
十、序列化与对象克隆
1 所谓序列化:一个类如果实现了Serializable接口,那么这个类创建的对象就是所谓序列化的对象。
2 如果一个“复制品”实体的变化不会引起原对象实体发生变化,反之亦然。这样的“复制品”称为原对象的一个克隆对象或简称克隆。
一个对象调用clone()方法就可以获取该对象的克隆对象;
对象输入流通过对象的序列化信息来得到当前对象的一个克隆。
十一、使用Scanner解析文件
使用Scanner类和正则表达式来解析文件。
1.使用默认分隔标记解析文件
创建Scanner对象,并指向要解析的文件,例如:
File file = new File("hello.java");
Scanner sc = new Scanner(file);
sc将空白作为分隔标记
相关方法:
next()依次返回file中的单词
hasNext()判断file最后一个单词是否已被next()方法返回
2.使用正则表达式作为分隔标记解析文件 : 创建Scanner对象,指向要解析的文件,并使用useDelimiter方法指定正则表达式作为分隔标记,例如:
File file = new File("hello.java");
Scanner sc = new Scanner(file);
sc.useDelimiter(正则表达式);
sc将正则表达式作为分隔标记
相关方法:
next() 依次返回file中的单词
hasNext() 判断file最后一个单词是否已被next()方法返回
十二、文件对话框
文件对话框是一个选择文件的界面,javax.swing包中的JFileChooser 类可以创建文件对话框,使用该类的构造方法JFileChooser() 创建初始不可见的有模式文件对话框,然后文件对话框调用下述2个方法:
showSaveDialog(Component a);
showOpenDialog(Component a);
可以让对话框可见,不过外观有所不同;showSaveDialog方法提供保存文件的界面,showOpenDialog方法提供打开文件的界面。上述两个方法中的参数a指定对话框可见时的位置,当a是null时,文件对话框出现在屏幕的中央;如果组件a不空,文件对话框在组件a的正前面居中显示。
十三、带进度条的输入流
如果读取文件时希望看见文件的读取进度可以使用javax.swing包提供的输入流类:
ProgressMonitorInputStream。
它的构造方法是:
–ProgressMonitorInputStream(Conmponent c,String s,InputStream); /*该类创建的输入流在读取文件时会弹出一个显示读取速度的进度条,进度条在参数c指定的组件的正前方显示,若参数c取null,则在屏幕正前方显示。*/
十四、文件锁
文件锁是为了解决由几个程序处理同一个文件时可能出现的混乱。
FileLock、FileChannel类处理Java提供的文件锁功能。它们分别在java.nio和java.nio.channels包中。
输入、输出流读写文件时可以使用文件锁。 如果创建的流在读写文件时使用了文件锁,那么只要不解除文件锁,其他程序无法操作被锁定的文件。
RondomAccessFile创建的流在读写文件时使用文件锁的步骤如下:
1.先使用RondomAccessFile流建立指向文件的流对象,该对象的读写属性必须是rw,例如:
RandomAccessFile input=new RandomAccessFile("Example.java","rw");
2.input流调用方法getChannel()获得一个连接到地层文件的FileChannel对象(信道),例如:
FileChannel channel=input.getChannel();
3.信道调用tryLock()或lock()方法获得一个FileLock(文件锁)对象,这一过程也称作对文件加锁。
教材学习中的问题和解决过程
无。
代码调试中的问题和解决过程
无。
感悟