【Java SE】IO流
1.File类
①File类的一个对象代表一个文件或一个文件目录
②File类声明在java.io下
1.1 FIle类的声明
路径分隔符
Windows和DOS系统默认使用'',UNIX和URL使用'/'
由于Java支持跨平台运行,File类为了解决这个问题动态提供了一个常量:public static final String separator 根据操作系统动态地提供分隔符
构造器 | |
---|---|
File(String pathname) | |
File(String parnter, String child) | |
File(File file, String child) |
构造器创建的仅仅是内存层面的几个对象,在main方法中路径相较于当前工程,在单元测试时路径则相较于当前Module。
1.2 File类的常用方法
String getAbsolutePath() | 获取绝对路径 |
String getPath() | 获取路径 |
String getName() | |
String getParent() | |
long length() | 长度,单位为字节 |
lastModified() | 最后一次修改时间 |
String[] list() | 以String的形式返回下一层目录中的文件或者目录的名字 |
File[] listFiles() | 返回下一层目录中的文件或者目录的File对象 |
boolean file1.renameTo(file2) | file1改名(且移动)为file2,要求file1存在且file2不存在 |
boolean isDirectory() | |
boolean isFile() | |
boolean exists() | 当前File对象是不是存在于硬盘 |
boolean canRead() | |
boolean canWrite() | |
boolean isHidden() |
boolean createNewFile() | |
boolean mkdir() | 如果文件存在就不创建了,上层目录如果不存在也不创建。 |
boolean mkdirs() | 上层文件目录不存在一并创建。 |
boolean delete() | java的删除不走回收站,删除时文件目录内不能包含文件或者文件目录。 |
File类的常用方法并未涉及到文件的写入和读取文件内容的操作,当需要读取和写入文件内容,必须使用IO流来完成。
2.IO流
Input/Output的缩写,用于处理设备之间的数据传输。如读、写文件、网络通信等。Java中对于数据的输入输出是以流(stream)的方式进行的。java.io下提供了各种“流”类和接口,用于获取不同种类的数据,并将这些数据以标准的方法输出。
2.1 流的分类
按操作数据单位不同分为:字节流(8bit)、字符流(16bit)
按数据流的流向不同分为:输入流(字节流:InputStream,字符流:Reader)、输出流(字节流:OutputStream,字符流:Writer),四种被称作抽象基类。
按流的角色不同分为:节点流(直接作用在文件上)、处理流(作用在已有流基础之上)
2.2 流的体系结构
2.2.1 节点流(文件流)
FileReader:文件字符读入流
File file1 = new File("Hello.txt");
FileReader fr = null;
try {
//提供具体的流
fr = new FileReader(file1);
int data;
//数据的读入
while((data = fr.read()) != -1) {
System.out.print((char) data);
}
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
} finally {
//流的关闭
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
读入的文件一定要存在,否则会报FileNotFoundException异常
对read()方法的升级:len = fr.read(cbuf),返回读取到字符数组cbuf的字符个数
int len;
while((len = fr.read(cbuf)) != -1) {
// 方法一
// System.out.print(new String(cbuf, 0, len));
// 方法二
// for(int i = 0;i < len;i++)
// System.out.print(cbuf[i]);
// 方法三,最后一次为 1,2,3,\r,\n
for(int i = 0;i < cbuf.length;i++)
System.out.print(cbuf[i]);
FileWriter:文件字符写出流
File file = new File("Hello1.txt");
FileWriter fw = new FileWriter(file);
fw.write("qwerdfb");
fw.close();
写出操作文件可以不存,如果文件不存在会自动创建,如果存在每次会对已存在文件进行覆盖
FileWriter fw = new FileWriter(file, true);
流使用的构造器第二个参数表示若已存在文件,则对文件进行追加而不是覆盖文件
FileWriter fw = null;
FileReader fr = null;
try {
File srcFile = new File("Hello.txt");
File destFile = new File("Hello1.txt");
fw = new FileWriter(destFile, true);
fr = new FileReader(srcFile);
int len;
char[] cbu = new char[5];
while((len = fr.read(cbu)) != -1) {
fw.write(cbu, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
对于图片等字节数据,基本单位不是字符而是二进制,不能使用字符流处理:
FileInputStream:字节读入流
FileOutputStream:字节写出流
FileOutputStream fw = null;
FileInputStream fr = null;
try {
File srcFile = new File("1.png");
File destFile = new File("2.png");
fw = new FileOutputStream(destFile);
fr = new FileInputStream(srcFile);
int len;
byte[] bytes = new byte[5];
while((len = fr.read(bytes)) != -1) {
fw.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
对于文本文件(.txt,.java,.c,.cpp),使用字符流处理
对于非文本文件(视频,音频,.doc,.ppt),使用字节流处理。文本文件使用字节流处理的话,可能会出现乱码,比如一个汉字占3个字节,读取用的数组不足三个字节的话就读不到完整的一个汉字因而出现乱码。但是如果非文本文件不在内存中进行读取的话,单纯使用字符流复制是造不成乱码的。
2.2.2 处理流:套接在已有的流之上的流
1.缓冲流:提高文件的读写效率
缓冲字节流:BufferedInputStream、BufferedOutputStream
@Test
public void BufferedStreamTest() {
FileInputStream fis = null;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
File srcFile = new File("1.png");
File destFile = new File("2.png");
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
int len;
byte[] bytes = new byte[5];
while((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bis.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
资源关闭时要先关闭外部缓冲流,再关闭内部节点流,缓冲流关闭时也会对内部流进行关闭,因此内部流的关闭可以省略。
bos.write()方法隐式地调用了flush(),flush的作用是刷新缓冲区,在缓冲区满的时候对数据进行一次性输出。
@Test
public void copyFileTest() {
long startTime = System.currentTimeMillis();
copyFile("1.png", "2.png");
long endTime = System.currentTimeMillis();
System.out.println("花费时间为:" + (endTime - startTime) + "ms");
startTime = System.currentTimeMillis();
copyFileByBuffer("1.png", "3.png");
endTime = System.currentTimeMillis();
System.out.println("使用缓冲流花费时间为:" + (endTime - startTime ) + "ms");
}
花费时间为:123ms
使用缓冲流花费时间为:4ms
缓冲字符流:BufferedReader、BufferedWriter
@Test
public void BufferedRWTest() {
BufferedReader br = null;
BufferedWriter bw = null;
try {
File srcFile = new File("Hello.txt");
File destFile = new File("Hello1.txt");
FileReader fr = new FileReader(srcFile);
FileWriter fw = new FileWriter(destFile);
br = new BufferedReader(fr);
bw = new BufferedWriter(fw);
int len;
char[] buffer = new char[5];
while((len = br.read(buffer)) != -1) {
bw.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用缓冲流readLine(),以String的形式进行读入操作:
String str;
while((str = br.readLine()) != null) {
//方式一
// bw.write(str + "\n");
//方式二
bw.write(str);
bw.newLine();
}
2.转换流:InputStreamReader、OutputStreamWriter
InputStreamReader:将一个字节的输入流转换为一个字符的输入流。对应解码过程。
OutputStreamWriter:将一个字符的输出流转换为一个字节的输出流。对应编码过程。
原因是文本文件可以使用字节流读取,才设计了转换流
InputStreamReader
@Test
public void test() {
File file = new File("Hello.txt");
InputStreamReader isr = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
isr = new InputStreamReader(fis, "utf-8");
int len;
char[] cs = new char[5];
while((len = isr.read(cs)) != -1) {
System.out.print(new String(cs, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
try {
isr.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
转换流第二个参数为解码字符集,对应文本文件保存时的编码。
OutputStreamWriter
@Test
public void test() {
File file = new File("Hello.txt");
File destFile = new File("Hello3.txt");
FileInputStream fis = null;
FileOutputStream fos = null;
InputStreamReader isr = null;
OutputStreamWriter osw = null;
try {
fis = new FileInputStream(file);
isr = new InputStreamReader(fis);
fos = new FileOutputStream(destFile);
osw = new OutputStreamWriter(fos);
int len;
char[] chs = new char[10];
while((len = isr.read(chs)) != -1) {
osw.write(chs, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符集
ASCII | 美国标准信息交换码,用一个字节的7位表示,其他方式均兼容ASCII |
ISO8859-1 | 拉丁码、欧洲码表,用一个字节的8位表示 |
GBK2312 | 中文编码表,最多两个字节编码所有字符 |
GBK | 中文编码表,最多两个字节编码所有字符,通过首位1、0的方式判断一个字符占一个还是两个字节 |
Unicode | 国际标准码,为每一个字符分配一个字符码,所有文字都用两个字节表示 |
UTF-8 | 解决了Unicode编码字节个数问题,变长编码方式,一个到四个字节表示一个字符,每8个位传输数据,汉字占三个字节 |
3.标准输入、输出流:字节流
System.in: 类型为InputStream字节写入流
System.out: 类型为PrintStream字节读出流
//字节流转换为字符流
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
while(true) {
String str = br.readLine();
if("e".equalsIgnoreCase(str) || "exit".equalsIgnoreCase(str))
break;
System.out.println(str.toUpperCase());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.in(InputStream 字节写入流) --InputStreamReader 转换流--> BufferedReader 字符读出缓冲流
面试题: 用标准输入流模拟Scanner
public class MyInput {
private InputStreamReader isr = new InputStreamReader(System.in);
private BufferedReader br = new BufferedReader(isr);
public int readInt() {
int result = 0;
try {
result = Integer.parseInt(br.readLine());
} catch (NumberFormatException e) {
System.out.println("输入不是整形!");
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public double readDouble() {
Double result = null;
try {
result = new Double(br.readLine());
} catch (NumberFormatException e) {
System.out.println("输入不是Double类型!");
} catch (IOException e) {
e.printStackTrace();
}
return result.intValue();
}
public static void main(String[] args) {
MyInput myInput = new MyInput();
while(true) {
int result1 = myInput.readInt();
System.out.println(result1);
double result2 = myInput.readDouble();
System.out.println(result2);
}
}
}
4.打印流
File file = new File("Hello.txt");
PrintStream ps = null;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
ps = new PrintStream(fos);
if(ps != null) {
System.setOut(ps);
}
for(int i = 0;i <= 255;i++) {
System.out.print((char) i);
if(i % 50 == 0)
System.out.println();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
ps.close();
}
System.setOut(PrintStream)可以设置读出为打印流处理的节点流(文件流)
5. 数据流
DataOutputStream、DataInputStream
//将内存中的数据经被数据流处理过的节点流写入文件
@Test
public void test() {
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("Hello1.txt"));
dos.writeUTF("刘");
dos.writeInt(25);
dos.writeBoolean(true);
dos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
//将文件中的数据经被数据流处理过的节点流读入内存
@Test
public void test2() {
try {
DataInputStream dis = new DataInputStream(new FileInputStream("Hello1.txt"));
System.out.println(dis.readUTF());
System.out.println(dis.readInt());
System.out.println(dis.readBoolean());
} catch (IOException e) {
e.printStackTrace();
}
}
6. 对象流
ObjectInputStream和ObjectOutputStream:用于存储和读取基本数据类型数据或对象的处理流。
序列化: 用ObjectOutputStream类保存基本数据类型或对象的机制。
反序列化: 用ObjectInputStream类读取基本数据类型或对象的机制。
注意: 二者均不能序列化static和transient修饰的成员变量。
对象的序列化机制允许将内存中的Java对象转换成平台无关的二进制流,从而允许把这些二进制流永久地保存在磁盘上,或则通过网络将这种二进制流传输到另一个网络节点。当其他程序获取到这种二进制流,就能将其转换为相应的对象。
@Test
public void test3() {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("Object.txt"));
oos.writeObject(new String("宇田多光"));
oos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void test4() {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("Object.txt"));
Object object = ois.readObject();
System.out.println(object);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
对自定义类进行序列化和反序列化:
自定义类能够序列化需要满足的要求:
1.需要实现接口Serializable
2.当前类提供一个全局常量:serialVersionUID
3.保证类中的所有属性也能够序列化(基本数据类型和String默认可序列化),static、trasient(static不归对象而归类所有,trasient为Java设计不可序列化)
@Test
public void test3() {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("Object.txt"));
oos.writeObject(new String("宇田多光"));
oos.flush();
oos.writeObject(new Person("宇多田光", 32));
oos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void test4() {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("Object.txt"));
Object object = ois.readObject();
System.out.println(object);
Person p = (Person) ois.readObject();
System.out.println(p);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
serialVersionUID的意义:
用来表明类的不同版本的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容。如果类中没有显示定义这个全局常量,那么它的值由Java运行时环境根据类的内部细节自动生成,因此类发生改变时serialVersionUID也会跟着变化,可能导致对象反序列化失败。
7. RandomAccessFile implements DataInput, DataOutput
RandomAccessFile类直接继承于java.lang.Object类,支持随机访问方式,程序可以直接跳到文件的任意地方来读、写文件,即既可以作为输入流又可以作为输出流。写文件时若文件存在则进行从头覆盖。
8.NIO
NIO是面向缓冲区的、基于通道的操作,而IO是面向流的 。以更加高效的操作进行文件的读写操作。
8.1Path
早期的Java只提供一个File类来访问文件系统,File类的功能有限,所提供的方法性能也不高,而且大多数方法在出错时仅返回失败而不抛出异常。Path可以看做是File的升级版本,实际引用的资源也可以不存在。
File file = new File(".\\IOT.\\data\\index.html");
System.out.println(file.exists());
Path path = Paths.get(".\\IOT.\\data\\index.html");
System.out.println(path.toString());
// Path和File可以相互转换
Path newpath = file.toPath();
File newfile = path.toFile();
【Java SE】IO流的更多相关文章
- java的IO流
java的IO流继承四大抽象类分别是字节流 inputStream outputStream与字符流 read write.怎么理解记忆很重要. 直接连接读写对象的是结点流,例如对文件读取字节类的名字 ...
- Java基础——IO流
今天刚刚看完java的io流操作,把主要的脉络看了一遍,不能保证以后使用时都能得心应手,但是最起码用到时知道有这么一个功能可以实现,下面对学习进行一下简单的总结: IO流主要用于硬板.内存.键盘等处理 ...
- 【Java】IO流简单分辨
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827509.html Java的IO流体系十分庞大,并且体系层次稍复杂,很容易记混或记错.在此,我把平时经常用 ...
- Java - 文件(IO流)
Java - 文件 (IO) 流的分类: > 文件流:FileInputStream | FileOutputStream | FileReader | FileWriter ...
- Java中IO流的总结
有关Java中IO流总结图 流分类 按方向分 输入流 输出流 按单位分 字节流 字符流 按功能分 节点流 处理流(过滤流) 其他 所有的流继承与这四类流:InputSteam.OutputStream ...
- JAVA中IO流总结
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42119261 我想你对JAVA的IO流有所了解,平时使用的 ...
- 第15章-输入/输出 --- 理解Java的IO流
(一)理解Java的IO流 JAVA的IO流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作,在Java中把不同的输入/输出(键盘.文件.网络连接等)抽象表述为"流"( ...
- Java基础IO流(二)字节流小案例
JAVA基础IO流(一)https://www.cnblogs.com/deepSleeping/p/9693601.html ①读取指定文件内容,按照16进制输出到控制台 其中,Integer.to ...
- java的Io流学习
Java中io流的学习(一)File:https://blog.csdn.net/qq_41061437/article/details/81672859 Java中io流的学习(二)FileInpu ...
- Java基础-IO流对象之压缩流(ZipOutputStream)与解压缩流(ZipInputStream)
Java基础-IO流对象之压缩流(ZipOutputStream)与解压缩流(ZipInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 之前我已经分享过很多的J ...
随机推荐
- Spring Boot 中的异步调用
通常我们开发的程序都是同步调用的,即程序按照代码的顺序一行一行的逐步往下执行,每一行代码都必须等待上一行代码执行完毕才能开始执行.而异步编程则没有这个限制,代码的调用不再是阻塞的.所以在一些情景下,通 ...
- Spring Boot统一日志框架
一.日志框架的选择 市面上常见的日志框架有很多,它们可以被分为两类:日志门面(日志抽象层)和日志实现,如下表. 日志分类 描述 举例 日志门面(日志抽象层) 为 Java 日志访问提供一套标准和规范 ...
- CF 1272 D. Remove One Element
D. Remove One Element time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- (十三).CSS3中的变换(transform),过渡(transition),动画(animation)
1 变换 transform 1.1 变换相关 CSS 属性 CSS 属性名 含义 值 transform 设置变换方式 transform-origin 设置变换的原点 使用关键字或坐标设置位置 t ...
- python Queue(队列学习)
Python 的Queue模块中提供了同步的.线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue.这些队列都实 ...
- 使用IDEA的webservice工具解析生成的客户端调用远程接口
由于这个接口的报文格式比较麻烦,是XML的请求头加上JSON格式的请求体,所以看起来比较复杂,也可以用RPC的方式调用,那样需要将请求头和请求体,响应头和响应体建实体.public JSONObjec ...
- 替换yum源
1.yum源进行备份 进入到yum源的配置文件中 执行命令如下:cd /etc/yum.repos.d 将yum源进行备份:mv Centos-Base.repo Centos-Base.repo.b ...
- dubbo服务多网卡IP问题
起因 更换电脑,dubbo服务不能调试,win7电脑好使,win10不行 分析 经过调试发现注册的ip地址,不是VPN分配的地址,多方面查找资料说ip排序的问题,尝试一下方法: 网络连接重新命名成一样 ...
- 线程Thread小记
1 public class ConcurentDemo extends Thread { 2 @Override 3 public void run() { 4 super.run(); 5 Sys ...
- HTTP通信基础
1. HTTP通信流程: 1)输入www.baidu.com2)解析成IP地址:192.168.0.13)浏览器通过该IP访问web服务器获取web资源4)再返回给客户端5)最后呈现在用户面前 2. ...