java教程

java教程 Java IO技术

位置:首页 > java教程 > java技巧,2016-02-25
最近又看了看Java IO技术的具体内容,记一下。IO的由来:不管是对象的什么信息都是在内存中操作的(以前学操作系统、汇编等课程时总是纠结于RAM与ROM,后来

最近又看了看Java IO技术的具体内容,记一下。

IO的由来:不管是对象的什么信息都是在内存中操作的(以前学操作系统、汇编等课程时总是纠结于RAM与ROM,后来才知道我根本就不必纠结那东西的),计算机一旦断电或者操作系统关闭,那么内存中的数据都会消失,因此要想个办法把这些数据保存起来以备下次使用,于是人类发明了各种介质来保存数据。我记得最初的计算机是用纸带打孔来记录数据的,这也是刁刁的( ⊙ o ⊙ )啊!后来有了各种高级的东东,硬盘,软盘,磁带、CD、U盘、SD卡……现在的SSD也是刁刁的。就是太贵了点,我2014年买了个256G的SSD花了六百多,而这可以买个1T的机械硬盘了。IO技术由此产生:就是将内存中的数据写到外围存储设备中去,或者将外围存储设备上的数据读到内存中来。

所谓的持久化,就是将内存数据保存到硬盘中去(在此用形象的硬盘代表外围存储设备这种东西),持久,就是能长久保持不变嘛!

I/O:Input输入、Output输出。

输入输出不应该弄混!但是我刚开始学时总是要想半天才把二者对应上各自的功能,还经常把两个单词想半天了才写。给个简单的方法说明下:

内存→外围设备:从内到外,就是出去,所以是输出Output。

外围设备→内存:从外到内,就是进来,所以是输入Input。


文件操作:

知道了IO这个东西,然后就要进行操作一下呢,就是往外设中写点数据保存起来然后再读取一下呗。感觉有点傻。

写?写到哪里去呢?磁盘中。哪个磁盘呢?D盘。D盘哪个位置呢?哪个文件呢?……你干脆一次性说完整得了!

既然准备往磁盘上写数据,那必须得有一个文件接收它才行,或者写数据的人自己创建一个文件。数据在磁盘上的保存后的东西我们都称之为“文件”,由于文件有名称、大小、创建时间……等信息,因此将之构建成了一个对象,于是有了File这个类:java.io.File。然后学习这个类的使用。


然后看文档:File类的构造器:四种:

File(File parent, String child) 
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
File(String pathname) 
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(String parent, String child) 
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(URI uri) 
通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。


于是准备好文件:   File file = new File("D:\test.txt");

报错了!因为\的问题,\在java中是个转义字符,要用\\才能表示。注意UNIX中是用/来分隔路径的,不需要转义。

于是改成:File file = new File("D:\\test.txt");

然后想到:既然要区分window系统与UNIX系统(两者有很多不同,换行符就是其中一例),那么可以将这些不同的信息封装起来,然后给你提供个方法,你告诉这个方法要什么信息,这个方法内部就根据当前平台返回给你正确的值,所以就有了System类封装了很多与平台有关的信息,

public static String getProperty(String key)获取指定键指示的系统属性。
根据文档,我们只需要告诉他想要获取的key关键字就可以了,文件分隔符是file.separator


所以又改成了:File file = new File("D:"+System.getProperty("file.separator")+"test.txt");

然后又想到(人们没事了总是爱多想):既然经常要用到\来分隔路径,那就总是要用到System.getProperty("file.separator")获取分隔符,还是嫌麻烦了,所以干脆将之定义成了File的一个static常量

所以就有了:File file = new File("D:"+File.separator+"test.txt");

这样还是麻烦,总是要自己使用File然后进行.操作,所以又成了:

private static final String FILE_SEPARATOR = File.separator;

File file = new File("D:"+FILE_SEPARATOR +"test.txt");

改了四次终于改好了!


然后文件对象有了,接着就进行文件操作,无非增删改查。

:获取文件信息:路径、名称、大小、时间……绝壁是getXXX()方法啊!

查文档

String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串。 

String getPath() 将此抽象路径名转换为一个路径名字符串。File("XXX")构造时写的什么则返回什么。

String getName() 

long length() 返回由此抽象路径名表示的文件的长度。 

long lastModified() 返回此抽象路径名表示的文件最后一次被修改的时间。 毫秒值。

boolean isDirectory()  测试此抽象路径名表示的文件是否是一个目录。 

boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件。 
boolean isHidden() 测试此抽象路径名指定的文件是否是一个隐藏文件。 

注意区分绝对路径与相对路径,如果使用相对路径new File("test.java"),则jvm将自动在用户目录user_dir下寻找该文件,


增:

boolean createNewFile() 创建文件,如果不存在则创建并返回true,如果文件已存在则返回false,如果路径错误则抛出IOException异常。

boolean mkdir() 创建此抽象路径名指定的目录。 

boolean mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。 


删:

boolean delete() 删除文件或目录,该方式删除后文件不会到回收站。文件正在被使用时会返回false,如果是目录并且目录中有东西则无法删除,需要从内往外逐个删除。

boolean exists()  删除前最好先判断文件是否存在


String[] list() 
String[] list(FilenameFilter filter) 

File[] listFiles() 

File[] listFiles(FileFilter filter) 

File[] listFiles(FilenameFilter filter) 

学会写过滤器,想到了everything这个工具,挺快的挺好用的。


使用递归遍历目录,但是递归层级多了可能会造成StackOverFlow栈溢出,可以采用队列的形式来遍历,往队列中边添加边删除,FIFO~First In First Out先进先出的策略。

犹记得刚开始学数据结构时,为了模仿写一个Stack,一直理解了好久然后死记代码。

Queue也是有好多种的,然后还有不同的存储结构的,单链表、双链表、循环队列……


弄了半天,说好的增删改查中的“改”呢?

这里要弄清楚类的设计思想了,File代表一个文件,是不能读写自己身上的东西,还需要一支笔或者一双眼睛,用作者和读者是不是更符合些?就像是一个目的地,需要车往里面运输东西。

因此有了IO流。

OutputStream:抽象类,定义了一些共用的方法,用来输出字节流。具体的输出功能由各个子类实现。根据作用的不同分成了文件输出FileOutputStream、对象输出ObjectOutputStream……后缀都是OutputStream

该类的所有方法:


 void close() 
          关闭此输出流并释放与此流有关的所有系统资源。 
 void flush() 
          刷新此输出流并强制写出所有缓冲的输出字节。 
 void write(byte[] b) 
          将 b.length 个字节从指定的 byte 数组写入此输出流。 
 void write(byte[] b, int off, int len) 
          将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。 
abstract  void write(int b) 
          将指定的字节写入此输出流。 

写一次刷新一次以免丢失内容,close时会自动调用刷新。



主要看一下FileOutputStream这个类,对文件进行操作!

FileOutputStream的构造函数:


FileOutputStream(File file) 
          创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 
FileOutputStream(File file, boolean append) 
          创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 
FileOutputStream(FileDescriptor fdObj) 
          创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接
FileOutputStream(String name) 
          创建一个向具有指定名称的文件中写入数据的输出文件流。 
FileOutputStream(String name, boolean append) 
          创建一个向具有指定 name 的文件中写入数据的输出文件流。 

这里就可以看出File对象的作用了,就像是一个目的地,输出流就是那辆小卡车。


window中的换行符是\r\n,UNIX的是\n,用System.getProperty("line.separator")来获取

使用时注意处理各种IOException异常


InputStream:接口,定义了一些共用的方法,用来读取字节流。 类似输入流,主要了解了FileInputStream

InputStream的主要读取方法:

<pre name="code" class="java">int available() 
          返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。 
void close() 
          关闭此输入流并释放与该流关联的所有系统资源。 
abstract int read() 从输入流中读取数据的下一个字节。 如果到达流的末尾,则返回 -1 子类必须提供此方法的一个实现。 
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。 int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。
注意读取文件的效率问题,使用缓冲区。缓冲区大小设置成1024的整数倍。

有了输入输出流就可以自己复制文件了。这是可以实现很多功能的,记得大学时总是找各种插入U盘后自动复制文件到指定的地方的软件,想用来拷老师的试卷,但是从未成功过~后来找到一段window的vbs脚本代码就完全可以解决问题。现在还存在电脑里面,将这代码保存成.vbs文件,然后双击运行就可以了。就是要自己手动改目录麻烦。

set fso=createobject("scripting.filesystemobject")
set ws=createobject("wscript.shell")
on error resume next
do
wscript.sleep 1000
if fso.driveexists("f:\") then
fso.copyfile "f:\*","E:\USB\"
fso.copyfolder "f:\*","E:\USB\"
wscript.sleep 20000
end if
loop
上面说的都是对文件进行的字节流操作,下面说对文件的字符流进行操作。

未完待续……

TAGS:Java IO

猜你喜欢

NewHot