Java IO 一 (读写字符串,拷贝文本文件)

本文详细介绍如何使用Java的FileWriter向文件写入字符串及FileReader读取字符串的方法,并演示了使用字符缓冲流BufferedReader和BufferedWriter高效处理文本文件的具体实现。

首先扯点别的:真是好记性不如烂笔头啊,关于java的输入输出流真是看一遍忘一遍,每次用的时候还得查看API,也是艰难。除了知道IO可以分为输入流,输出流,字符流,字节流,其他的忘得干干净净的,都还给老师了。所以再看一遍,再把这些基础知识好好整理学习一下。

今天写的内容

  • 如何创建一个文件并写入字符串。
  • 从一个文件总读取字符串。

FileWriter,向文件中写字符串

在这里插入图片描述

package read_writer;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterDemo {

	public static void main(String[] args) {
		writeString();
	}
	/**
	 * 向文件中写入一个字符串
	 */
	private static void writeString() {
		FileWriter fw=null;
		try {
			//创建FileWriter对象
			fw=new FileWriter("FileWriterDemo.txt",true);
			//要被写入的字符串
			String str="helloworld";
			fw.write(str);
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if(fw!=null){
					//关闭数据流
					fw.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

运行后,在工程名上右击,点击refresh,就会发现在工程的根目录下出现一个FileWriterDemo.txt,双击打开,就会发现字符串已经被写入。

重点看看上面的几行代码

//创建一个FileWriter对象,第二个参数传入true,表示使用append模式向文件中追加写入,
//不会覆盖文件中原来的内容
fw=new FileWriter("FileWriterDemo.txt",true);

FileWriter的构造函数们,都出来吧,别藏着掖着了。

//通过给定的file创建一个FileWriter对象
FileWriter(File file) 

//通过给定的file创建一个FileWriter对象,
//第二个参数取值为false,标识向文件中写入会覆盖旧的内容.
//取值为true,接着文件中的内容继续在后面写。
FileWriter(File file, boolean append) 

//通过给定的文件描述符创建一个FlieWriter对象。
FileWriter(FileDescriptor fd) 

//通过字符串文件名创建一个FileWriter
FileWriter(String fileName) 

//通过字符串文件名创建一个FileWriter,
//第二个参数取值为false,标识向文件中写入会覆盖旧的内容.
//取值为true,接着文件中的内容继续在后面写。
FileWriter(String fileName, boolean append) 

选用的时候根据自己的实际需求选择构造函数。

//将字符串写入文件。
fw.write(str);

write还有几个比较常用的重载方法

// 把字符数组写入文件
void write(char[] cbuf) 

//把字符数组的一部分写入文件。off表示从数组cbuf的什么位置开始写,len表示写入的字符数
void write(char[] cbuf, int off, int len) 

// 把字符串写入文件,就是代码中用到的。
write(String str);

//写单个字符
write(int c);
 
//把字符串的一部分写入文件。off表示从字符串str的什么位置开始写,len表示写入的字符数
void write(String str, int off, int len) 

下面我来演示一下使用void write(String str, int off, int len) 可能出现的错误。其他代码都没变,就变了一行代码。

String str="helloworld";
//就变了这行代码。
fw.write(str,5,10);

看看出现的错误。

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 15

字符串越界。出现这种错误的原因是没有理解void write(String str, int off, int len) 方法的参数的含义。
String str=“helloworld”;长度为10,我从下标为5的位置(w)为起点开始写,然而这时候从起点到字符串末尾(d)的字符的个数是5,而我的第三个参数指定为10.所以肯定越界了,我改成5运行一下,就没错了。这是我遇到过的错误,希望大家注意。

另外,如果你想写入字符串之前换一行,怎么办,可以这样写

String str="\nhelloworld";
fw.write(str);

但是当你写完用记事本打开这个FileWriterDemo.txt文件时,发现没有换行。这是不要怀疑。这是记事本的错。它不能识别\n,所以建议你用notePad++,或EditPlus等软件打开。

写完数据后,注意在finally块中关闭数据流。

if(fw!=null){
	//关闭数据流
	fw.close();
}

使用FileReader,读入一个字符串

使用FileReader从我们刚才创建的文件中读取字符串**

private static void testRead() {
    FileReader reader = null;
    try {
        reader = new FileReader("FileWriterDemo.txt");
        char[] buffer = new char[1024];
        StringBuilder builder = new StringBuilder();
        int count;
        while ((count = reader.read(buffer)) != -1) {
            builder.append(buffer, 0, count);
        }
        System.out.println(builder.toString());
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

FileReader的构造函数

//通过指定的文件创建一个FileReader。
FileReader(File file) 

//通过一个文件描述符创建一个FileReader
FileReader(FileDescriptor fd) 

//通过一个字符串形式的文件名创建一个FileReader
FileReader(String fileName) 

看一看重点代码

char[] buffer = new char[1024];
StringBuilder builder = new StringBuilder();
int count;
while ((count = reader.read(buffer)) != -1) {
       builder.append(buffer, 0, count);
}

看看这行代码:(count = reader.read(buffer)) != -1。意思就是如果没到文件的末尾

//这个方法把文件中的内容读取到buf数组中,如果到了文件的末尾会返回-1.
//否则就返回读到的字符的个数。
int read(char[] cbuf) 

read方法的几个重载方法

//读取一个字符
public int read() throws IOException

//读取字符到字符数组cbuf中,offset表示数组开始储存读取到的字符的起始位置,length
//表示要读取的最大的字符数
public int read(char cbuf[], int offset, int length) throws IOException

使用字符缓冲流拷贝一个文本文件

 private static void copy() {
    BufferedReader bfr = null;
    BufferedWriter bfw = null;
    try {
        bfr = new BufferedReader(new FileReader("D:/FileInputStreamTest.java"));
        bfw = new BufferedWriter(new FileWriter("D:/FileInputStreamTestCopy.java"));
        String line;
        while ((line = bfr.readLine()) != null) {
            bfw.write(line);
            bfw.newLine();
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (bfw != null) {
            try {
                bfw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bfr != null) {
            try {
                bfr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

JAVA中关于BufferedReader的相关描述。

从一个字符输入流中读入文本信息,提供字符缓存,来提高读取字符、字符数组或者一行字符的效率。你可以指定缓冲区的大小,如果不指定,就是用默认的大小。一般我们不需要去指定,使用默认的即可。通常情况下,一个“Reader”的读取操作会导致底层的字符或者字节流产生一个相应的读取请求(这里的请求,是指从外存读进内存)。因此,建议用BufferedReader把一些“读取效率不高Reader包裹起来”,比如“FlieReader和InputStreamReader”。

那么BufferedReader是如何提高读取效率的呢?看一下BufferedReader中的两个成员变量

private char cb[];//用来缓冲的字符数组
private static int defaultCharBufferSize = 8192;//用来缓冲的字符数组的默认的大小

在BufferedReader的读取方法中,如果每次读取的字符数大于8192,那就直接从外存读到内存中。否则read方法内部就会从cb[]中读取数据,如果此时已经读到了cb[]的末尾,或者cb[]中的字符数已经少于要读取的字符数,就调用fill()方法就先从外存读取8192个字符到内存cb[]中。然后BufferReader的读取操作,就是从cb[]中读取。通过这种方式减少了内存外存交互的次数,所以提高了读取效率。

这里说明一下,当调用read(char cbuf[], int offset, int length) 方法的时候,内部会调用read1(char[] cbuf, int off, int len) 方法从cb[]中读取数据。如果cb[]中的有效字符不够length的时候,会多次调用read1()方法,多次从cb中读取,直到读够length个字符,或者读到了文件的末尾(没有读满length个字符)。

JAVA JDK 关于BufferedWriter的解释

向字符输出流中写文本信息,提供字符缓存,以提高写单个字符、字符数组、字符串的效率。缓冲区大小可以指定,也可以使用默认的,通常我们使用默认的就够了。默认缓冲区大小是8192。newLine()方法使用系统自带的换行符进行换行。如果你在写完一行数据后想在新的一行写数据,可以调用这个方法。通常情况下,一个Writer会立即向底层的字符或者字节输出流发送要写出的数据。除非是要求立即输出,建议使用BufferedWriter来包裹任何Writer,例如FileWriter和OutputStreaemWriter—-因为这些Writer的效率不高。

看一下BufferedWriter中的两个成员变量,和BufferedReader中是对应的。

private char cb[];//用来缓冲的字符数组
private static int defaultCharBufferSize = 8192;//用来缓冲的字符数组的默认的大小

在BufferedWriter的write方法中,如果每次写出的字符数超过8192,那么就直接写出外存。否则,就先把写出的数据放入cb[]中,等到凑够8192个字符以后,调用void flushBuffer() throws IOException一次性写出外存,并把cb[]清空,准备下一次写入。这样减少了内存和外存的交互次数,从而提高了写的效率。

行,差不多到结尾了。休息一下。有错误和疑问欢迎指出,感激不尽。

参考链接:

  1. java 字节流与字符流的区别
  2. 毕向东老师的java视频
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值