IO 是什么?其实就是Java中的一种输入和输出功能,也可以理解为对文件的写入和读出的操作,只不过Java中对这种操作叫做对流的操作。而流不只是对文件进行读写,还可以对内存,网络,程度操作。
一、字节与字符
在Java中有输入、输出两种IO流,每种输入、输出流又分为字节流和字符流两大类。
- 关于字节,每个字节(byte)有8bit组成。
- 关于字符,我们可能知道代表一个汉字或者英文字母。
字节与字符之间的关系
Java采用unicode编码,通讲,2个字节来表示一个字符。
在0~127整数之间的字符映射,unicode向下兼容ASCII,也就是1个字节表示一个字符。
一个中文或英文字符的unicode编码都占2个字节。
编码方式 | 英文字符 | 中文字符 |
---|---|---|
GB 2312、GBK | 1 | 2 |
UTF-8 | 1 | 3-4 |
UTF-16 | 2 | 3-4 |
UTF-32 | 4 | 4 |
二、File
文件和文件夹的操作都可以用File来完成。
文件的获取
//构造函数File(String pathname)
File f1 =new File("c:\\abc\\1.txt");
//File(String parent,String child)
File f2 =new File("c:\\abc","2.txt");
//File(File parent,String child)
File f3 =new File("c:"+File.separator+"abc");//separator 跨平台分隔符
File f4 =new File(f3,"3.txt");
System.out.println(f1);//c:\abc\1.txt
文件的创建以及删除
//如果文件存在返回false,否则返回true并且创建文件
boolean createNewFile();
//创建一个File对象所对应的目录,成功返回true,否则false。且File对象必须为路径而不是文件。只会创建最后一级目录,如果上级目录不存在就抛异常。
boolean mkdir();
//创建一个File对象所对应的目录,成功返回true,否则false。且File对象必须为路径而不是文件。创建多级目录,创建路径中所有不存在的目录
boolean mkdirs() ;
//如果文件存在返回true并且删除文件,否则返回false
boolean delete();
//在虚拟机终止时,删除File对象所表示的文件或目录。
void deleteOnExit();
判断方法
boolean canExecute() ;//判断文件是否可执行
boolean canRead();//判断文件是否可读
boolean canWrite();//判断文件是否可写
boolean exists();//判断文件是否存在
boolean isDirectory();//判断是否是目录
boolean isFile();//判断是否是文件
boolean isHidden();//判断是否是隐藏文件或隐藏目录
boolean isAbsolute();//判断是否是绝对路径 文件不存在也能判断
作者:Ruheng
链接://www.greatytc.com/p/c58ed5ec7e4a
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
获取参数方法
String getName();//返回文件或者是目录的名称
String getPath();//返回路径
String getAbsolutePath();//返回绝对路径
String getParent();//返回父目录,如果没有父目录则返回null
long lastModified();//返回最后一次修改的时间
long length();//返回文件的长度
File[] listRoots();// 列出所有的根目录(Window中就是所有系统的盘符)
String[] list() ;//返回一个字符串数组,给定路径下的文件或目录名称字符串
String[] list(FilenameFilter filter);//返回满足过滤器要求的一个字符串数组
File[] listFiles();//返回一个文件对象数组,给定路径下文件或目录
File[] listFiles(FilenameFilter filter);//返回满足过滤器要求的一个文件对象数组
其中FilenameFileter 是一个文件过滤器。找到所有png图片。
file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".png");
}
});
三、IO流
Java的IO流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作,在Java中把不同的输入/输出源抽象表述为"流"。
流是一组有顺序的字节集合,是对数据传输的总称或抽象。
流有输入和输出,输入时是流从数据源流向程序。输出时是流从程序传向数据源,而数据源可以是内存,文件,网络或程序等。
四、分类
- 按照流向不同,分为 输入流、输出流
- 按照流对象不同,分为 字节流、字符流
字节流可以处理任意类型的数据,而字符只能处理字符类型的数据
- 按照处理过程不同,分为 节点流、处理流(一种典型的装饰器模式)
五、4中基本方式的讲解 和 实例
- inputStream
- outputStream
- Reader
- Write
四大抽象基类,其中inputStream,outputStream是字节流的基类,Reader,Write是字符流的基类。不能创建实例,但是为所有实现类提供了基础的模板。
inputStream
outputStream
Reader
Write
总结:
从上面的方法中我可以看出。inputStream和reader,outputStream与write的函数都很相似,并且每次进行了IO操作,要记得close,因为IO资源并不属于内存资源,并不会被GC回收。所以需要显示的 手动的回收资源。对于输出操作,close还会自动flush。
六、RandomAccessFile的使用与简介
RandomAccessFile简介
我们在对文件的操作过程中,除了使用字节流和字符流的方式之外,我们还可以使用RandomAcessFile这个工具类来实现。
RandomAccessFile可以实现对文件的读 和 写,但是他并不是继承于以上4中基本虚拟类。
而且在对文件的操作中,RandomAccessFile有一个巨大的优势,他可以支持文件的随机访问,程序快可以直接跳转到文件的任意地方来读写数据。所以如果需要访问文件的部分内容,而不是把文件从头读到尾,使用RandomAccessFile将是更好的选择。
RandomAccessFile的方法虽然多,但它有一个最大的局限,就是只能读写文件,不能读写其他IO节点。
RandomAccessFile的一个重要使用场景就是网络请求中的多线程下载及断点续传。
构造方法以及参数
mode中,有4中启动的方式
"r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
"rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
"rws" 打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。
"rwd" 打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到底层存储设备。
RandomAccessFile使用
读取文件内容
RandomAccessFile raf = new RandomAccessFile(file,"r");
String s = null;
while ((s = raf.readLine())!=null){
System.out.println(s);
}
raf.close();
写入文件内容
String text = "写入的内容 \n";
RandomAccessFile raf = new RandomAccessFile(file,"rw");
raf.seek(12); //改变写入偏移的位置,从地12个字节的位置开始写入
raf.write(text.getBytes());
raf.close();
注意:RandomAccessFile虽然可以设置了偏移的方法,但他不能实现中间插入的效果,如果你需要实现文本中间插入的话,要先将后面的文件内容拷贝,然后写入,最后在写入的写一行,将拷贝的东西复制回来。
七、对象的序列化与反序列化
什么是序列化和反序列化呢?这是针对对象来说的,因为我们在写入文件的时候,常常因为要保存的是一个对象,也就是一个obj,但是里面的变量又很多,我们不可能挨个申明,一个个写入,这时候,我们就可以使用对象的序列化与反序列化。
序列化就是对象到保存文件的过程。
反序列化就是从保存的文件,转换为对象的过程。
我们使用ObjectOutputStream和ObjectInputStream 实现对象的序列化和反序列化。
File file = new File("test.txt");
MyService ms = new MyService();
try {
OutputStream os = new FileOutputStream(file);
//创建时,需要给予一个outputStream,这个很好理解,
//因为对象操作肯定是字节操作,不能使用字符操作
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(ms);
oos.close();
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
InputStream is = new FileInputStream(file);
ObjectInputStream ios = new ObjectInputStream(is);
MyService object = (MyService)ios.readObject();
System.out.println(object.name);
is.close();
ios.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}