1.缓冲输入文件


  • FileReader

  • BufferedReader

  FileReader可以直接对文件进行读操作。但是简化编程,加快读取速度,我们加入了缓冲机制,使用了BufferedReader。BufferedReader内置了一个char[]数组(大小为8192)作为缓冲区,每次调用fill()函数将该缓冲区尽可能填满。而我们自己的程序在调用BufferedReader提供的方法时,实质上是从该缓冲区读取的。

  BufferedReader中的fill()方法

  private void fill() throws IOException {
int dst;
if (markedChar <= UNMARKED) {
/* No mark */
dst = 0;
} else {
/* Marked */
int delta = nextChar - markedChar;
if (delta >= readAheadLimit) {
/* Gone past read-ahead limit: Invalidate mark */
markedChar = INVALIDATED;
readAheadLimit = 0;
dst = 0;
} else {
if (readAheadLimit <= cb.length) {
/* Shuffle in the current buffer */
System.arraycopy(cb, markedChar, cb, 0, delta);
markedChar = 0;
dst = delta;
} else {
/* Reallocate buffer to accommodate read-ahead limit */
char ncb[] = new char[readAheadLimit];
System.arraycopy(cb, markedChar, ncb, 0, delta);
cb = ncb;
markedChar = 0;
dst = delta;
}
nextChar = nChars = delta;
}
} int n;
do {
n = in.read(cb, dst, cb.length - dst);//该方法调用了read方法
} while (n == 0);
if (n > 0) {
nChars = dst + n;
nextChar = dst;
}
}

  BufferedReader中的read()方法

 public int read() throws IOException {
synchronized (lock) {
ensureOpen();
for (;;) {
if (nextChar >= nChars) {
fill(); //调用内置的fill()方法
if (nextChar >= nChars)
return -1;
}
if (skipLF) {
skipLF = false;
if (cb[nextChar] == '\n') {
nextChar++;
continue;
}
}
return cb[nextChar++]; //返回给用户的是个缓冲区
}
}
}

从上面的代码中可以看出BufferedReader对我们普通的Reader进行了包装,通过缓冲区机制提高了用户读写的速度。

使用方式:

 package com.dy.xidian;

 import java.io.BufferedReader;
import java.io.FileReader; public class BufferedInputFile {
public static String read(String filename) throws Exception {
BufferedReader in = new BufferedReader(new FileReader(filename));
String s;
StringBuilder sb = new StringBuilder();
while ((s = in.readLine()) != null) {
sb.append(s);
}
in.close();
return sb.toString();
} public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("Usage: BufferedInputFile filepath!");
}
String s = read(args[0]);
System.out.println(s);
}
}

注意readline()的使用:

  1. 读入的数据要注意有/r或/n或/r/n
  2. 没有数据时会阻塞,在数据流异常或断开时才会返回null
  3. 使用socket之类的数据流时,要避免使用readLine(),以免为了等待一个换行/回车符而一直阻塞

2.从内存输入


  StringReader的输入是一个String对象,所以StringReader是从内存读取数据的。上一个例子输出的是个String对象,我们恰好可以利用一下。

 public class MemoryInput {
public static void main(String[] args) throws Exception {
String filename = "E:/html/111.php";
StringReader sr = new StringReader(BufferedInputFile.read(filename));
int c;
while ((c = sr.read()) != -1)
System.out.print((char) c);
}
}

3.格式化的内存输入


  要读取格式化数据,可以使用DataInputStream,它是一个面向字节的I/O类。

package com.dy.xidian;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException; class BufferedInputFile {
BufferedReader br; public BufferedInputFile(String path) throws FileNotFoundException {
br = new BufferedReader(new FileReader(path));
} public String read() throws IOException {
StringBuilder sb = new StringBuilder();
String s;
while ((s = br.readLine()) != null)
sb.append(s);
return sb.toString();
}
}
public class FormattedMemoryInput {
public static void main(String[] args) throws IOException {
String path = "E:/html/utf-8.php";
DataInputStream in = new DataInputStream(new ByteArrayInputStream(
path.getBytes()));
while (in.available() != 0)
System.out.print((char) in.readByte());
}
}

4.基本的文件输出


  FileWriter对象可以向文件中写入数据。首先创建一个与指定文件连接的FileWriter。然后我们对其进行装饰。为了提高写的效率,加入缓冲机制,使用BufferedWriter类对其进行包装。为了能够格式化输出,使用PrintWriter类包装。

package com.dy.xidian;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter; public class BasicFileOutput {
static String File = "E:/html/utf-8.php";
public static void main(String[] args) throws IOException {
PrintWriter os = new PrintWriter(new BufferedWriter(
new FileWriter(File)));
String s1 = "hello world!";
String s2 = "世界 你好";
os.println(s1);
os.print(s2);
os.close();
}
}

  更为简单的方式:利用PrintWriter提供的辅助构造器

    public PrintWriter(String fileName) throws FileNotFoundException {
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
false);
} /* Private constructor */
private PrintWriter(Charset charset, File file)
throws FileNotFoundException
{
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)),
false);
}
package com.dy.xidian;

import java.io.IOException;
import java.io.PrintWriter; public class BasicFileOutput {
static String File = "E:/html/utf-8.php";
public static void main(String[] args) throws IOException {
PrintWriter os = new PrintWriter(File);
String s1 = "hello world!";
String s2 = "世界 你好";
os.println(s1);
os.print(s2);
os.close();
}
}

5.储存和恢复数据


  DataInputStream和DataOutputStream一般用来对对象的成员属性读取和输出操作。这两个类都是面向字节流的。

package com.dy.xidian;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; public class StoringAndRecoveringData {
public static void main(String args[]) throws IOException {
String path = "E:/html/utf-8.php";
FileOutputStream fs = new FileOutputStream(path);
DataOutputStream os = new DataOutputStream(new BufferedOutputStream(fs));
os.writeDouble(3141.5);
os.writeUTF("这是Pi1"); //使用UTF-8编码
os.close();
DataInputStream is = new DataInputStream(new BufferedInputStream(
new FileInputStream(path)));
System.out.println(is.readDouble()); //先读double
System.out.println(is.readUTF()); //在读字符串
is.close();
}
}

  

  从输出文件的内容我们可以发现是DataOutputStream输出的是一大堆编码,这些编码只适合DataInputStream来读取。这种方式可以用来进行对象的序列化存储。并且读取的顺序要与存储的顺序保持一致。

6.随机访问文件


  RandomAccessFile提供了随机访问的文件的方法,它可以看成是DataInputStream和DataOutputStream的组合。RandomAccessFile也是面向字节流的,所以我们想修改文件某处的值时,需要计算出该值的偏移量(单位为字节),通过seek方法,将文件指针指向该处,才可以修改成功。

package com.dy.xidian;

import java.io.IOException;
import java.io.RandomAccessFile; public class UsingRandomAccessFile {
static String file = "E:/html/utf-8.php";
static void display() throws IOException {
RandomAccessFile rf = new RandomAccessFile(file, "r");
for (int i = 0; i < 7; i++)
System.out.println("Value " + i + ": " + rf.readDouble());
System.out.println(rf.readUTF());
rf.close();
} public static void main(String[] args) throws IOException {
RandomAccessFile rf = new RandomAccessFile(file, "rw");
for (int i = 0; i < 7; i++)
rf.writeDouble(i * 1.414);
rf.writeUTF("文件末尾");
rf.close();
display();
rf = new RandomAccessFile(file, "rw");
rf.seek(5 * 8);
rf.writeDouble(47.0001);
rf.close();
display();
}
}

  

  我们想修改第六个Double值。首先算出偏移量,每个double类型8个字节,所以第六个double起始位置的偏移量为40=5*8,所以应该调用seek(5*8)将文件指针指向该处,在调用write方法来修改该值。

7.读写文件工具类


 package com.dy.xidian;

 import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.TreeSet; public class TextFile extends ArrayList<String> { /**
*
*/
private static final long serialVersionUID = 1L; /**
*
* @param 文件名
* @param 字符集编码
* @return 文件内容
*/
public static String read(String fileName, String Charset) {
StringBuilder sb = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(fileName), Charset));
try {
String s;
while ((s = br.readLine()) != null) {
sb.append(s);
sb.append("\n");
}
} finally {
br.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return sb.toString();
} /**
*
* @param 文件名
* @param 文本内容
*/
public static void write(String fileName, String text) {
try {
PrintWriter out = new PrintWriter(
new File(fileName).getAbsoluteFile());
try {
out.print(text);
} finally {
out.close();
}
} catch (IOException e) {
throw new RuntimeException();
}
} public TextFile(String fileName, String splitter) {
super(Arrays.asList(read(fileName, "utf-8").split(splitter)));
// split()会留一个空字符串在开始的位置
if (get(0).equals(""))
remove(0);
} public TextFile(String fileName) {
this(fileName, "\n");
} public void write(String fileName) {
try {
PrintWriter out = new PrintWriter(
new File(fileName).getAbsoluteFile());
try {
for (String item : this) {
out.print(item);
}
} finally {
out.close();
}
} catch (IOException e) {
throw new RuntimeException();
}
} public static void main(String[] args) {
String file = TextFile.read("com/dy/xidian/TextFile.java", "utf-8");
TextFile.write("test.txt", file);
TextFile text = new TextFile("test.txt");
text.write("test2.txt");
TreeSet<String> words = new TreeSet<String>(new TextFile(
"com/dy/xidian/TextFile.java", "\\W+"));
for (String string : words) {
System.out.println(string);
}
System.out.println(words.headSet("a"));
}
}

初探JAVA中I/O流(二)的更多相关文章

  1. 初探JAVA中I/O流(一)

    一.流 流,这里是对数据交换的形象称法.进程是运行在内存中的,在运行的过程中避免不了会与外界进行数据交互.比如将数据从硬盘.控制台.管道甚至是套接字(具体点应该是我们电脑上的网卡)读到我们进程锁所占据 ...

  2. Java中的IO流(二)

    上一篇<Java中的IO流(一)>把学习IO流的字符流作了一下记录,本篇把字节流记录一下. 一,Java中的字节流 Java中的字节流的操作方式与字符流的操作方式大致相同,连方法名都是类似 ...

  3. Java中的IO流总结

    Java中的IO流总结 1. 流的继承关系,以及字节流和字符流. 2. 节点流FileOutputStream和FileInputStream和处理流BufferedInputStream和Buffe ...

  4. Java中的IO流(五)

    上一篇<Java中的IO流(四)>记录了一下Properties类,此类不属于IO流,它属于集合框架.接下来说一下IO流中的其它流 一,打印流PrintStream PrintStream ...

  5. Java中的IO流(六)

    上一篇<Java中的IO流(五)>把流中的打印流PrintStream,PrintWriter,序列流SequenceInputStream以及结合之前所记录的知识点完成了文件的切割与文件 ...

  6. Java中的IO流(四)

    上一篇<Java中的IO流(三)>把IO流中的文件及目录操作的对象File类记录了一下,本篇把本不属性IO流但又和IO流有关系的一个对象作一下记录,此对象本属于集合框架里的一个子集,即Pr ...

  7. Java中的IO流(三)

    上一篇<Java中的IO流(二)>把学习Java的字符流以及转换流作了一下记录,从本篇开始将把IO流中对文件或文件夹操作的对象File类的学习进行一下记录. 一,File类的构造函数及字段 ...

  8. java中的Stream流

    java中的Stream流 说到Stream便容易想到I/O Stream,而实际上,谁规定"流"就一定是"IO流"呢?在Java 8中,得益于Lambda所带 ...

  9. java中的IO流

    Java中的IO流 在之前的时候我已经接触过C#中的IO流,也就是说集中数据固化的方式之一,那么我们今天来说一下java中的IO流. 首先,我们学习IO流就是要对文件或目录进行一系列的操作,那么怎样操 ...

随机推荐

  1. iOS -数据库网络之xml解析

    XML文件有2种解析方式 1.基于文档(document) 2.基于事件(sax)   1.IOS中XML文件获取   首先要将XML导入工程中 在ViewController的按钮事件中,代码如下: ...

  2. C#删除文件和文件夹到回收站

    首先对项目添加名为Microsoft.VisualBasic.dll的引用,然后添加命名空间using Microsoft.VisualBasic.FileIO;usingSystem;namespa ...

  3. Tip和菜单的实现方式

    Tip和菜单有类似的功能,即鼠标光标移上去的时候显示指定元素,鼠标光标离开的时候隐藏该元素.如下 示例1:下拉菜单(鼠标移动到“客户服务”上时出现,离开则隐藏) 示例2:水平菜单(鼠标移动到“餐饮美食 ...

  4. python 发送邮件函数模块

    发送邮件函数功能 #!/usr/bin/env python # -*- coding:utf-8 -*- import smtplib from email.mime.text import MIM ...

  5. 有关Azure存储帐号监视器中的度量值

    在一次故障排错中,发现存储帐号监视器里'成功百分比'(该度量值的源选择的是blob)这个度量值始终是低于100%.引出几个问题: 1. 这个度量值所代表的意义? A: 存储基于REST协议,对服务的访 ...

  6. SVN同步大坑

    遇到的问题 这两天一直在搞svn的主从备份,使用的方法是svnsync做的主从同步,同步大部分的仓库都没有什么问题很顺利的就同步完成了,不了解svnsync同步的可以看我这篇,但是在在同步2个仓库的时 ...

  7. Linux shell basic3 dd wc comm chmod ls

    Generating files of any size /dev/zerois a character special device, which infinitely returns the ze ...

  8. Linux shell basic2 cat find tr

    Cat stands for concatenate. Case 1. When the text files have more blank lines, we want to remove the ...

  9. VMware + OpenStack: 从 Plugin 到 VIO (VMware Integrated OpenStack)的演进

    VMware 做为实际上的企业虚拟化领导者,对 OpenStack 的态度一直在变化.一开始,VMware 表达出与 OpenStack 的竞争态度.随着 OpenStack 的逐步壮大并且一步一步进 ...

  10. 【对比分析八】null和undefined的区别

    (1).  null是一个表示"无"的对象,转为数值时为0  undefined是一个表示"无"的原始值,转为数值时为NaN (2).  当声明的变量还未被初始 ...