IO流操作详解
注:FileReader继承InputStreamReader类,InputStreamReader实现Reader接口,其他同理。
对于文件内容的操作主要分为两大类
分别是:
字符流
字节流
其中,字符流有两个抽象类:Writer Reader
其对应子类FileWriter和FileReader可实现文件的读写操作
BufferedWriter和BufferedReader能够提供缓冲区功能,用以提高效率
同样,字节流也有两个抽象类:InputStream OutputStream
其对应子类有FileInputStream和FileOutputStream实现文件读写
BufferedInputStream和BufferedOutputStream提供缓冲区功能
字符流和字节流的主要区别:
1.字节流读取的时候,读到一个字节就返回一个字节; 字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8码表中是3个字节)时。先去查指定的编码表,将查到的字符返回。
2.字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。
注意:
读写流使用完都要用.close方法关闭,防止占用资源,但是在关闭之前防止空值最好做空值判断再关闭;进行写操作时想立即生效用write.flush()刷新。
注意写文件路径时盘符后面用\\或者/,如:c:\\demo.txt或者c:/demo.txt
BufferedReader特有方法:readLine(),将行标记之前的数据作为字符串返回,读到结尾时返回null,读取行是将读取的字符临时存储产生的效果。
具体操作方法如下:
FileReader(字符流的读取)
FileReader r = new FileReader(path);
//方式一:读取单个字符的方式
//每读取一次,向下移动一个字符单位,返回读取的字节数
int temp1 = r.read();
System.out.println((char)temp1);
int temp2 = r.read();
System.out.println((char)temp2);
//方式二:循环读取
//read()方法读到文件末尾会返回-1
/*
while (true) {
int temp = r.read();
if (temp == -1) {
break;
}
System.out.print((char)temp);
}
*/
//方式三:循环读取的简化操作
//单个字符读取,当temp不等于-1的时候打印字符
/*int temp = 0;
while ((temp = r.read()) != -1) {
System.out.print((char)temp);
}
*/
//方式四:读入到字符数组
/*
char[] buf = new char[1024];
int temp = r.read(buf);
//将数组转化为字符串打印,后面参数的意思是
//如果字符数组未满,转化成字符串打印后尾部也许会出现其他字符
//因此,读取的字符有多少个,就转化多少为字符串
System.out.println(new String(buf,0,temp));
*/
//方式五:读入到字符数组的优化
//由于有时候文件太大,无法确定需要定义的数组大小
//因此一般定义数组长度为1024,采用循环的方式读入
/*
char[] buf = new char[1024];
int temp = 0;
while((temp = r.read(buf)) != -1) {
System.out.print(new String(buf,0,temp));
}
*/ FileWriter(字符流的写入)
String path="E:\\demo.txt";
//由于IO操作会抛出异常,因此在try语句块的外部定义FileWriter的引用
FileWriter w = null;
try {
//以path为路径创建一个新的FileWriter对象
//如果需要追加数据,而不是覆盖,则使用FileWriter(path,true)构造方法
w = new FileWriter(path);
//将字符串写入到流中,\r\n表示换行想有好的
w.write("Nerxious is a good boy\r\n");
//如果想马上看到写入效果,则需要调用w.flush()方法
w.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
//如果前面发生异常,那么是无法产生w对象的
//因此要做出判断,以免发生空指针异常
if(w != null) {
try {
//关闭流资源,需要再次捕捉异常
w.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
即FileWriter w = new FileWriter(path);//指定写的路径
w.write("Nerxious is a good boy\r\n");//写入具体内容
文本文件的复制
String doc=”...”;
String copy=”...”:
FileReader r= new FileReader(doc);
FileWriter w = new FileWriter(copy);
//方式一:单个字符写入
int temp = 0;
while((temp = r.read()) != -1) {
w.write(temp);
}
//方式二:字符数组方式写入
/*
char[] buf = new char[1024];
int temp = 0;
while ((temp = r.read(buf)) != -1) {
w.write(new String(buf,0,temp));
}
*/ 利用字符流的缓冲区来进行文本文件的复制
FileReader r = new FileReader(doc);
FileWriter w = new FileWriter(copy);
//创建缓冲区对象
//将需要提高效率的FileReader和FileWriter对象放入其构造函数内
//当然,也可以使用匿名对象的方式 br = new BufferedReader(new FileReader(doc));
BufferedReader br = new BufferedReader(r);
BufferedWriter bw = new BufferedWriter(w);
String line = null;
//读取行,直到返回null
//readLine()方法只返回换行符之前的数据
while((line = br.readLine()) != null) {
//使用BufferWriter对象的写入方法
bw.write(line);
//写完文件内容之后换行
//newLine()方法依据平台而定
//windows下的换行是\r\n
//Linux下则是\n
bw.newLine();
} 字节流:
FileOutputStream(字符流的写入)
FileOutputStream o = new FileOutputStream(path);
String str = "Nerxious is a good boy\r\n";
byte[] buf = str.getBytes();
//也可以直接使用o.write("String".getBytes());
//因为字符串就是一个对象,能直接调用方法
o.write(buf); FileInputStream(字节流的读取) FileInputStream i = new FileInputStream(path);
//方式一:单个字符读取
//需要注意的是,此处我用英文文本测试效果良好
//但中文就悲剧了,不过下面两个方法效果良好
int ch = 0;
while((ch=i.read()) != -1){
System.out.print((char)ch);
}
//方式二:数组循环读取
/*
byte[] buf = new byte[1024];
int len = 0;
while((len = i.read(buf)) != -1) {
System.out.println(new String(buf,0,len));
}
*/
//方式三:标准大小的数组读取
/*
//定一个一个刚好大小的数组
//available()方法返回文件的字节数
//但是,如果文件过大,内存溢出,那就悲剧了
//所以,亲们要慎用!!!上面那个方法就不错
byte[] buf = new byte[i.available()];
i.read(buf);
//因为数组大小刚好,所以转换为字符串时无需在构造函数中设置起始点
System.out.println(new String(buf));
*/ 二进制文件(即非纯文本文件)的复制
Bin/copy为 文件路径,“E:\\demo.mp3”,此处示例文件为mp3文件
FileInputStream i = null;
FileOutputStream o = null;
try {
i = new FileInputStream(bin);
o = new FileOutputStream(copy);
//循环的方式读入写出文件,从而完成复制
byte[] buf = new byte[1024];
int temp = 0;
while((temp = i.read(buf)) != -1) {
o.write(buf, 0, temp);
} 利用字节流的缓冲区进行二进制文件的复制
FileInputStream i = null;
FileOutputStream o = null;
BufferedInputStream bi = null;
BufferedOutputStream bo = null;
try {
i = new FileInputStream(bin);
o = new FileOutputStream(copy);
bi = new BufferedInputStream(i);
bo = new BufferedOutputStream(o);
byte[] buf = new byte[1024];
int temp = 0;
while((temp = bi.read(buf)) != -1) {
bo.write(buf,0,temp);
} 文件的操作 递归列出目录下所有文件
File f = new File(path); //方式一:list()
//返回一个包含指定目录下所有文件名的字符串数组
//如果不是一个目录则返回null
String[] files = f.list();
for (String x : files) {
System.out.println(x);
} //方式二:
if(f.isDirectory()){
File[] files = f.listFiles();
for(File x : files) {
print(x);
}
}
两者都是返回目录下的所有文件名,但是第二种方式更实用,为递归列出文件做铺垫 列出根目录:
//listRoots()是一个静态方法,返回文件数组
File[] files = File.listRoots();
//foreach循环打印File对象
for (File x : files) {
System.out.println(x);
}
本地环境是Linux,所以根目录只有一个 /,如果是Windows就能列出你的所有盘符 Scanner类: 从键盘读取
Scanner input = new Scanner(System.in);
System.out.println("请输出一个整数:");
int i = input.nextInt();
System.out.println("你输入的整数是:" + i); 从字符串读取
Scanner input = new Scanner("hello\r\nworld\r\n");
//循环读取,hasNext()方法和集合框架里面的一样使
while(input.hasNext()) {
//每次读取一行,别的读取方法见API,比较简单
String s = input.nextLine();
System.out.println(s);
} 从文件读取:
File f = new File(path);
//从文件构造Scanner对象,有可能产生异常
Scanner input = new Scanner(f);
while(input.hasNext()) {
String s = input.nextLine();
System.out.println(s);
} PrintWriter类
向文件写入内容
File file = new File(path);
//此处构造函数还可以传其他对象,具体参考API文档
PrintWriter p = new PrintWriter(file);
//向文件写入一行,此外还有print()和printf()方法
p.println("如果有一天我回到从前");
p.println("回到最原始的我");
p.println("你是否会觉得我不错");
//刷新流
p.flush(); 与PrintWriter类似的还有一个PrintStream类,此处以PrintWriter举例是因为文本文件具有人为可读性,而二进制文件(字节模式)则需要使用专门的程序来读取.可能有人会问:FileOutputStream、 FileWriter都能写文件,那么为何还需要PrintWriter和PrintStream类,如果细看API文档,可以知道前者单纯的字符写入流和字节写入流操作的方式大多用数组进行,对文件的细化处理非常不方便,而PrintWriter和PrintStream则很好的解决了这一问题,提供print()等方法,并且,PrintWriter和PrintStream对于不存在文件对象的情况下会直接创建,如果已有文件对象,它们则会把原有文件给覆盖掉,却没有增加方法。解决这问题也很简单,再看API文档,PrintWriter有一个构造方法PrintWriter(Writer out),也就是能够传入Writer对象,PrintStream有一个构造方法PrintStream(OutputStream out),也就是能传入OutputStream对象。因此,我们这样写就可以了
new PrintWriter(new FileWriter(file,true))
new PrintStream(new FileOutputStream(file,true))
既能增加数据,也能更高效的处理文件,见如下代码示范
File file = new File(path);
//利用FileWriter方式构建PrintWriter对象,实现追加
PrintWriter p = new PrintWriter(new FileWriter(file,true));
p.println("尼玛 这一句就是追加的 看到没");
p.flush(); System类相关:
//别忘了,OutputStream是所有字节写入流的父类
OutputStream out = System.out;
//写入数据,只能是数组,所以用getBytes()方法
out.write("Hello,bitch!\r\n".getBytes()); System类中的读取
InputStream in = System.in;
System.out.print("请输入文字: ");
byte[] buf = new byte[1024];
int len = 0;
//将输入的数据保证到数组中,len记录输入的长度
len = in.read(buf);
//用字符串的方式打印数组中的数据
System.out.println("你的输入是: " + new String(buf,0,len)); 利用BufferedReader实现对键盘的读取
BufferedReader b = new BufferedReader(new InputStreamReader(System.in));
System.out.print("请输入文本:");
String str = b.readLine();
System.out.println("你输入的是:" + str);
//循环读取方式
/*
while(true) {
System.out.print("请输入文本:");
String str = b.readLine();
//如果输入over就结束循环
if("over".equals(str)) {
break;
}
System.out.println("你输入的是:" + str);
IO流操作详解的更多相关文章
- Java 常用IO流操作详解
1.基本概念 IO:Java对数据的操作是通过流的方式,IO流用来处理设备之间的数据传输,上传文件和下载文件,Java用于操作流的对象都在IO包中. 2.IO流的分类 图示:(主要IO流) 3.字节流 ...
- Java之IO流技术详解
何为IO? 首先,我们看看百度给出的解释. I/O输入/输出(Input/Output),分为IO设备和IO接口两个部分. i是写入,Input的首字母.o是输出,Output的首字母. IO 也称为 ...
- Java中的IO流系统详解(转载)
摘要: Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java ...
- Java中的IO流系统详解
Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java 内用 U ...
- (转)Linux下select, poll和epoll IO模型的详解
Linux下select, poll和epoll IO模型的详解 原文:http://blog.csdn.net/tianmohust/article/details/6677985 一).Epoll ...
- MongoDB各种查询操作详解
这篇文章主要介绍了MongoDB各种查询操作详解,包括比较查询.关联查询.数组查询等,需要的朋友可以参考下 一.find操作 MongoDB中使用find来进行查询,通过指定find的第一个参数可 ...
- Linux Shell数组常用操作详解
Linux Shell数组常用操作详解 1数组定义: declare -a 数组名 数组名=(元素1 元素2 元素3 ) declare -a array array=( ) 数组用小括号括起,数组元 ...
- [Android新手区] SQLite 操作详解--SQL语法
该文章完全摘自转自:北大青鸟[Android新手区] SQLite 操作详解--SQL语法 :http://home.bdqn.cn/thread-49363-1-1.html SQLite库可以解 ...
- shell字符串操作详解
shell字符串操作详解的相关资料. 1.shell变量声明的判断 表达式 含义 ${var} 变量var的值, 与$var相同 ${var-DEFAULT} 如果var没有被声明, 那么就以$DE ...
随机推荐
- HDFS 的运行机制
hdfs haddop distributed system 由 name node, secondary name node,data node, client 组成. 真正存放数据的就是 data ...
- J2EE企业级应用架构
一.企业级应用架构解析 应用特点 多环境多系统的交互 海量数据.高并发[用户访问量].高TPS[每秒吞吐量] 安全等级高 自动化集群管理 架构原则 CAP原则(一致性[数据变动要同步].可用性[随着数 ...
- ES6学习笔记(五)-函数扩展
- BZOJ2656 [Zjoi2012]数列
Description 小白和小蓝在一起上数学课,下课后老师留了一道作业,求下面这个数列的通项公式: $$\begin{aligned}A_0 &= 0\\A_1 &= 1\\A_{2 ...
- Windows下多个JDK版本之间的切换
一.JDK版本切换批处理脚本 我们平时在window上做开发的时候,可能需要同时开发两个甚至多个项目,有时不同的项目对JDK的版本要求有区别,这时候我们可能会在一台电脑上安装多个版本的JDK,如下 ...
- Eclipse 分屏显示同一个代码文件
描述: 今天在使用Eclipse开发的时候不知按错哪个键,出现编辑框分屏显示同一个代码,由于之前没有使用过这一功能,所以就去查了一下,原来是Eclipse的分屏功能. 快捷键: 方式一:Window ...
- VS2010 创建 windows service 程序
参考网上保护眼睛程序,自写程序如下. 1.创建一个名词为“CareEyeService”,类型为“WindowsService”的应用程序. 自动生成代码如下图: 2.修改ServiceCareEye ...
- linux安装redis+RedisDesktopManager
一:redis简介 (REmote DIctionary Server Redis远程字典服务器) 1:Redis是一个开源的使用ANSI C语言编写.完全免费开源的,遵守BSD协议.支持 ...
- TMG阵列部署选择
如果用户环境中有多个网络出口,用EMS配置TMG是最佳选择.在这种情况下,可以使用EMS管理的阵列配置企业级访问规则.由于一个单一的策略适用于整个企业的所有阵列,因此管理成本将大大降低.用于EMS的服 ...
- cocos2dx加载骨骼动画,获取骨骼位置
2015/05/13 需求: (1)希望在骨骼上绑定一个粒子特效 (2)获取骨骼的位置 (3)获取骨骼动画的大小 (4)lua 1. cocostudio动画编辑器 (1)绑定粒子特效(跟随骨骼的移动 ...