一.文件读取

  FileInputStream和FileReader是文件字节输入流和文件字符输入流,都是提供文件读取功能,只是读取形式不同,一个以字节为最小单位读取,一个以字符为最小单位读取,并且两者都必须从文件头开始,按顺序读取,读取结束后需要调用close()方法释放流对象.

两个文件输入流的有参构造方法一致,以FileInputStream为例

public FileInputStream(String name)

public FileInputStream(File file)

public FileInputStream(FileDesciptor fd)

  1.FileInputStream

  FileInputStream直接继承自InputStream

package com.java.io;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; /**
* 在桌面创建一个input.txt文本,内容为"The quick brown fox jumps over a lazy dog.",文件大小是42字节,
* 下面分别测试FileInputStream成员方法
*/
public class FileInputStreamTest {
private final static String filePath = "C:\\Users\\Administrator\\Desktop\\input.txt"; //测试read()方法单字节读取
public static void readCase() throws IOException {
InputStream input = new FileInputStream(filePath); int data = input.read();
while (data != -1) {
System.out.print((char) data);
data = input.read();
}
input.close();
} //测试read(byte[] b)方法使用数组读取,read(byte[] b,int off,int len)相同
public static void readByteArrayCase() throws IOException {
InputStream input = new FileInputStream(filePath); byte[] bytes = new byte[10];
int data = input.read(bytes);
while (data != -1) {
System.out.print(new String(bytes,0,data)); //每次读入到bytes数组中时,会按索引重复覆盖数据,
data=input.read(bytes); //最后一次读入可能会残留上一次的数据
}
input.close();
}
//测试skip(int)方法,使流可以跳过一定字节数据,最大跳过字节数为2048
public static void skipCase() throws IOException{
InputStream input=new FileInputStream(filePath);
input.skip(4); //跳过四个字节 int data=input.read();
while(data!=-1){
System.out.print((char)data);
data=input.read();
}
input.close();
}
//测试available()方法,获取文件的大小
public static void availableCase() throws IOException{
InputStream input=new FileInputStream(filePath);
System.out.print(input.available());
input.close();
}
//测试markSupported()等方法
public static void markSupportedCase() throws IOException{
InputStream input=new FileInputStream(filePath); System.out.print(input.markSupported());
input.mark(10);
try {
input.reset();
}catch (IOException e){
System.out.print(e.getMessage());
}finally {
input.close();
}
}
//测试获取属性等方法
public static void getPropertiesCase() throws IOException{
FileInputStream input=new FileInputStream(filePath);
System.out.println(input.getChannel()); //获取文件FileChannel对象
System.out.print(input.getFD()); //获取文件FileDescriptor对象
} public static void main(String[] args) throws IOException {
readCase();
System.out.println("\n-------------------------------");
readByteArrayCase();
System.out.println("\n-------------------------------");
skipCase();
System.out.println("\n-------------------------------");
availableCase();
System.out.println("\n-------------------------------");
markSupportedCase();
System.out.println("\n-------------------------------");
getPropertiesCase();
}
}

  下面是控制台输出结果

The quick brown fox jumps over a lazy dog.               readCase()
-------------------------------
The quick brown fox jumps over a lazy dog. readByteArraycase()
-------------------------------
quick brown fox jumps over a lazy dog. skipCase()
-------------------------------
42                          availableCase()
-------------------------------
falsemark/reset not supported markSupportedCase()
-------------------------------
sun.nio.ch.FileChannelImpl@1540e19d getPropertiesCase()
java.io.FileDescriptor@677327b6

由输出结果可以看出FileInputStream并没有重写markSupported()方法,所以FileInputStream并不支持mark()和reset()方法,读取文件时无法标记读取位置和重置.

  2.FileReader

  FileReader直接继承自InputStreamReader,而InputStreamReader是一个输入转换流,将输入字节转换为字符形式,这说明FileReader底层还是依靠字节流读取,只不过java帮我们进行了编码工作.

二.文件写入

  FileOutputStream和FileWriter是文件字节输出流和文件字符输出流,都是提供文件写入功能,只是写入形式不同,一个以字节为最小单位写入,一个以字符为最小单位写入,此外还可以选择是在原来文件基础上重新写入还是追加写入,写入结束后需要调用close()方法释放流对象.

两个文件输出流的有参构造方法一致,以FileOutputStream为例

public FileOutputStream(String name)

public FileOutputStream(String name, boolean append)

public FileOutputStream(File file)

public FileOutputStream(File file, boolean append)

public FileOutputStream(FileDescriptor fdObj)

其中有两个构造方法带有一个boolean类型形式参数,它规定写入形式,当为true时,表明要在原来文件尾追加写入,为false时是重写文件,不带此参数默认为false.

  1.FileOutputStream

  FileOutputStream直接继承自OutputStream

package com.java.io;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream; /**
* Created by Administrator on 2017/3/20 0020.
*/
public class FileOutputStreamTest {
public static final String filePath="C:\\Users\\Administrator\\Desktop\\outStream.txt";
public static final String lineSeparator = System.getProperty("line.separator", "/n"); //获取当前系统的文本分隔符 public static void main(String[] args) throws IOException {
writeCase();
constructorCase();
} //写入方法方法测试,分别是write(int a),write(byte[] b),write(byte[] b,int off,int len)三种写入方式
public static void writeCase() throws IOException {
OutputStream output=new FileOutputStream(filePath); //如果文件不存在,则创建该文件 output.write(98);
output.write(lineSeparator.getBytes());
output.write('a');
output.write(lineSeparator.getBytes());
output.write("hello world".getBytes());
output.write(lineSeparator.getBytes());
output.write("hello world".getBytes(),2,3);
output.close();
}
//构造方法测试,主要看追加写入效果演示
public static void constructorCase() throws IOException{
OutputStream output1=new FileOutputStream(filePath);
output1.write('a');
output1.close(); OutputStream output2=new FileOutputStream(filePath,true);
output2.write('b');
output2.close();
}
}
复制代码

  上面代码中当执行writeCase()方法后,桌面创建了outStream.txt文件夹,内容为

b
a
hello world
llo

  需要注意的是FileOutputStream执行write()方法时,文件会立即写入内容,不需要调用flush()方法刷入,FileOutputStream也没有重写flush()方法,其方法体为空

  执行constructorCase()方法第一次创建output1并写入时,文件outStream.txt被重新创建,文本内容为

a

  第二次创建output2,写入模式变为追加写入,文件内容变为

ab

  2.FileWriter

  FileWriter直接继承自OutputStreamWriter,而OutputStreamWriter是一个输出转换流,将输出的字符转换为字节形式,这说明FileWriter底层还是依靠字节流写入,只不过java帮我们进行了编码工作.

  此外需要注意的是FileWriter具有一个缓冲区,写入的字符首先会存在缓冲区内,因此write()方法并不会直接写入到文本,

package com.java.io;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer; /**
* Created by Administrator on 2017/3/20 0020.
*/
public class FileWriterTest {
public static final String filePath="C:\\Users\\Administrator\\Desktop\\writer.txt";
public static final String lineSeparator = System.getProperty("line.separator", "/n"); //获取当前系统的文本分隔符 public static void main(String[] args) throws IOException {
writeAndFlushCase();
}
//测试 write()方法各种形式,一时flush()方法作用
public static void writeAndFlushCase() throws IOException{
Writer writer=new FileWriter(filePath); writer.write(98);
writer.write(lineSeparator);
writer.write("你好,世界".toCharArray());
writer.write(lineSeparator);
writer.write("你好,世界".toCharArray(),3,2);
writer.flush(); //调用flush(),将缓冲区内字符刷入到文本
writer.write(lineSeparator);
writer.write("你好,世界");
writer.write(lineSeparator);
writer.write("你好,世界",1,4); writer.close(); }
}

  为了测试FileWriter的缓冲区效果,我们在debug模式下一行行执行,实例化FileWriter对象后,java会自动帮我们在所写路径下创建相应文件,如果原来不存在的话

  在代码执行到flush()方法调用前,打开文本内容一直为空,调用flush()方法后,文本内容为

b
你好,世界
世界

  执行完close()前文本内容一直不变,调用close()后,再次查看文本内容为

b
你好,世界
世界
你好,世界
好,世界

  可见FileWriter使用写入方法时,会首先将字符写入到一个字符缓冲区,等缓冲区满后才会真正写入到文本,这样设计的目的我想不是为了提高写入速度,因为一是相对应的FileOutputStream类没有使用缓冲区,二是后面有专门的缓冲流,我们知道FileWriter继承自OutputStreamWriter,这是一个转换流,说明FileWriter本质上还是以字节的形式写入.只不过java自动帮我们编码,而之所以要使用一个缓冲区,就是为了每执行一次写入,确保写入的是一个字符.

  此外FileWriter方法最后调用close()方法时并没有执行flush()方法,后面的同样被写入,说明FileWriter的close()方法会自动执行一次flush()操作,通过源码也会发现这一点.

三.随机文件读写

  上面无论文件的读取只能从文件头开始,写入可以重写或者追加写入,而通过文件随机读写流RandomAccessFile,我们可以在任意指定位置进行读写

  RandomAccessFile操作文件就像操作一个byte数组一样,可以通过一个文件指针(就像数组的索引),来实现从文件随机位置读写,

  此外RandomAccessFile和上面文件流不同的是,它不是java IO四个基本流的直接或间接子类,而是实现了DataOutput,DataIntput,Closeable三个接口,它有两个构造方法

  public RandomAccessFile(String name ,String mode)

  public RandomAccessFile(File file ,String mode)

  需要注意两个构造方法的第二个参数,String mode,它表示对文件操作的类型,分以下四种形式

  "r"   只读模式,如果对文件进行写操作,会报IOException错误
  "rw"  读写模式,如果文件不存在,将会创建文件
  "rws"  同步读写模式,任何对文件的修改(内容和元数据),都会立即被同步到底层存储设备ddd

  "rwd"  同步读写模式,任何对文件的修改(内容),都会立即被同步到底层存储设备

package com.java.io;

import java.io.IOException;
import java.io.RandomAccessFile; /**
* 在桌面创建一个file.txt文本,内容为"The quick brown fox jumps over a lazy dog.",文件大小是42字节,
* 主要测试以下方法
* read() 读取字节
* write(byte[] byte) 写入字节数组
* seek(long pos) 设置当前文件指针
* getFilePointer() 获取当前文件指针
*/
public class RandomAccesseFileTest {
public static final String filePath = "C:\\Users\\Administrator\\Desktop\\file.txt";
public static final String lineSeparator = System.getProperty("line.separator", "/n"); //获取当前系统的文本分隔符 public static void main(String[] args) throws IOException {
readCase();
writeCase();
} public static void readCase() throws IOException {
RandomAccessFile file = new RandomAccessFile(filePath, "r"); int data = file.read();
while (data != -1) {
System.out.print((char) data);
data = file.read();
} System.out.println(lineSeparator + "----------------------------");
file.seek(4);
System.out.println("文件现在指针位置 " + file.getFilePointer());
data = file.read();
while (data != -1) {
System.out.print((char) data);
data = file.read();
} try {
file.write(10);
} catch (IOException e) {
System.out.println(lineSeparator + "----------------------------");
System.out.println(e);
}finally {
file.close();
}
} public static void writeCase() throws IOException {
RandomAccessFile file = new RandomAccessFile(filePath, "rw"); file.write("The tardy".getBytes());
file.seek(4);
file.write("quick".getBytes());
file.close();
}
}

  执行完readCase()后控制台打出

The quick brown fox jumps over a lazy dog.
----------------------------
文件现在指针位置 4
quick brown fox jumps over a lazy dog.
----------------------------
java.io.IOException: 拒绝访问。

  在debug模式下执行writeCase()第一次写入时,打开file.txt,文件内容是

The tardy brown fox jumps over a lazy dog.

  重新设置文件指针为4,第二次写入后,查看文件,内容是

The quick brown fox jumps over a lazy dog.

java I/O框架 (四)文件流的更多相关文章

  1. java I/O框架 (三)基本流

    概述 基本流有字节输入输出流(InputStream,OutputStream),和字符输入输出流(Reader,Writer),它们都是抽象类,作为Java IO API中其他所有流的父类存在. 我 ...

  2. java I/O框架 (二)文件操作(File)

    1.介绍 java io中最常操作的就是我们电脑中的文件,将这些文件以流的形式本地读写,或者上传到网络上.java中的File类就是对这些存储于磁盘上文件的虚拟映射,这也体现了java面向对象的思想, ...

  3. Java后端HttpClient Post提交文件流 及服务端接收文件流

    客户端将文件转换为流发送: 依赖的包: <dependency> <groupId>org.apache.httpcomponents</groupId> < ...

  4. Java 基础(四)| IO 流之使用文件流的正确姿势

    为跳槽面试做准备,今天开始进入 Java 基础的复习.希望基础不好的同学看完这篇文章,能掌握泛型,而基础好的同学权当复习,希望看完这篇文章能够起一点你的青涩记忆. 一.什么是 IO 流? 想象一个场景 ...

  5. 自己写一个java的mvc框架吧(四)

    自己写一个mvc框架吧(四) 写一个请求的入口,以及初始化框架 上一章写了获取方法的入参,并根据入参的参数类型进行数据转换.这时候,我们已经具备了通过反射调用方法的一切必要条件.现在我们缺少一个htt ...

  6. 笨鸟先飞之Java(一)--使用struts2框架实现文件上传

    无论是.net还是Java,我们最常接触到的就是文件的上传和下载功能,在Java里要实现这两个经常使用功能会有非常多种解决方案,可是struts2的框架却能给我们一个比較简单的方式,以下就一起来看吧: ...

  7. Java中常用IO流之文件流的基本使用姿势

    所谓的 IO 即 Input(输入)/Output(输出) ,当软件与外部资源(例如:网络,数据库,磁盘文件)交互的时候,就会用到 IO 操作.而在IO操作中,最常用的一种方式就是流,也被称为IO流. ...

  8. java 读取文件流

    搬运自速学堂:https://www.sxt.cn/Java_jQuery_in_action/ten-iqtechnology.html JAVA中IO流体系: 四大IO抽象类 ·InputStre ...

  9. 《手把手教你》系列基础篇(八十四)-java+ selenium自动化测试-框架设计基础-TestNG日志-上篇(详解教程)

    1.简介 TestNG还为我们提供了测试的记录功能-日志.例如,在运行测试用例期间,用户希望在控制台中记录一些信息.信息可以是任何细节取决于目的.牢记我们正在使用Selenium进行测试,我们需要有助 ...

随机推荐

  1. 图片文档倾斜矫正算法 附完整c代码

    2年前在学习图像算法的时候看到一个文档倾斜矫正的算法. 也就是说能将一些文档图像进行旋转矫正, 当然这个算法一般用于一些文档扫描软件做后处理 或者用于ocr 文字识别做前处理. 相关的关键词: 抗倾斜 ...

  2. awk中引用shell变量执行替换的脚本

    遇到问题: 现在有两个脚本,我想 将file1中的内容按file2来匹配 [root@154 home]# cat file1 3-1-1 POTV=1,POTA=0,POTP=2 1-4-76 PO ...

  3. 【转】wget

    wget 下载整个网站,或者特定目录 需要下载某个目录下面的所有文件.命令如下 wget -c -r -np -k -L -p www.xxx.org/pub/path/ 在下载时.有用到外部域名的图 ...

  4. 我的java之路week2类的无参、带参方法

    2.1语法 public 返回值类型 方法名(){ //方法体 } 2.2方法的调用语法 对象名.方法名 计算平均分和总成绩 public class Score { /** * 创建类 ScoreC ...

  5. 08_Python编码与解码

    一.编码的由来 因为计算机只能处理010101二进制数据,如果要处理文本,图像,视频等,需要我们把数据转换成01010二进制格式才能被计算机处理 最先出现的是ASCII,用8位一个字节来表示,成为单字 ...

  6. python3,进程间的通信

    本文来源于python 3.5版本的官方文档 multiprocessing模块为进程间通信提供了两种方法: 1.进程队列queue The Queue class is a near clone o ...

  7. OI常用读入方式效率测试

    我来填坑了. 这次我用自己写的测试读入的程序来分别测试cin(不关闭流同步),scanf和读入优化的效率差别.   我们分别对三个阶段的数据量n进行测试,通过时间比对来观察性能的差异. n = 102 ...

  8. POJ 2404 Jogging Trails [DP 状压 一般图最小权完美匹配]

    传送门 题意:找一个经过所有边权值最小的回路,$n \le 15$ 所有点度数为偶则存在欧拉回路,直接输出权值和 否则考虑度数为奇的点,连着奇数条边,奇点之间走已经走过的路移动再走没走过的路 然后大体 ...

  9. BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]

    传送门 题意:不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换,因为你兑换说明有利可图,是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊,一定比多天的组合好 $f[ ...

  10. python实现时间o(1)的最小栈

    这是毕业校招二面时遇到的手写编程题,当时刚刚开始学习python,整个栈写下来也是费了不少时间.毕竟语言只是工具,只要想清楚实现,使用任何语言都能快速的写出来. 何为最小栈?栈最基础的操作是压栈(pu ...