首先扯点别的:真是好记性不如烂笔头啊,关于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[]清空,准备下一次写入。这样减少了内存和外存的交互次数,从而提高了写的效率。
行,差不多到结尾了。休息一下。有错误和疑问欢迎指出,感激不尽。
参考链接:
- java 字节流与字符流的区别
- 毕向东老师的java视频