标签:错误 操作文件 i++ 读取数据 文件读取 传递 abc 返回 单位
参考资料:《Java从入门到精通》/明日科技编著. 4版. 北京:清华大学出版社,2016
Java由数据流处理输入/输出模式,程序从指向源的输入流中读取数据,数据源可以是文件、网络、压缩包或其他数据源,这个过程也称为数据的读取,如下图所示:
输出流是指向数据要到达的目的地,程序通过向输出流中写入数据,把信息传递到目的地,输出流的目的地可以是文件、网络、压缩包或其他输出目标,该过程也称为数据的写入,如下图所示:
总的来说,在Java程序中,要想从文件中读取数据或者将数据写入文件中,都需要在程序和文件之间建立一条数据的传输通道,这个通道就是输入/输出流。
Java语言在java.io包中定义了很多处理各种输入/输出的类。
字节流与字符流的区别:
简而言之,字节流在操作文件时不会用到缓存(内存),而是直接操作文件本身。而字符流在操作的时候使用了缓存区,而不是直接操作文件。例如,使用字符流执行写入数据操作,如果使用close()方法没有关闭输出流,则文件中看不到任何写入的内容,除非使用flush()方法强行将缓存数据写入目标文件。
本质上来说,一切都是字节流,其实没有字符流这个东西。字符只是根据编码集对字节进行解码的产物。
字节流:01010100010010100101
字符流:aah65Khannskm3bhbasv //本质上还是字节流
【技巧】:字节流可以处理所有数据文件,若处理的是纯文本数据,建议使用字符流。
InputStream类是字节输入流的抽象类,是所有字节输入流的父类,其层次结构如下所示:
该类中所有方法遇到错误时都会引发IOException异常,下面是该类的一些常用方法:
说明:并不是所有的InputStream类的子类都支持InputStream中定义的所有方法,如skip()、mark()、reset()等方法只对某些子类有用。
Java中的字符是Unicode编码,是双字节的,即一个字符占用两个字节。InputStream是用来处理字节的,并不适合处理字符文本。Java为字符文本的输入专门提供了一套单独的类Reader,但是Reader类并不是InputStream类的替换者,只是在处理字符串时简化了编程。
Reader类是字符输入流的抽象类,是所有字符输入流的父类。
OutputStream类是字节输出流的抽象类,该类是所有表示字节输出流类的父类,其层次结构如下所示:
OutputStream类中的所有方法均返回void,在遇到错误时会引发IOException异常,下面对OutputStream类中的方法做简单的介绍:
Writer类是字符输出流的抽象类,此类为所有字符输出流类的父类,其层次结构如下所示:
可以使用File类创建一个文件对象。通常使用以下3种构造方法来创建文件对象:
该构造方法通过将给定的路径名字符串,并转换为抽象路径名来创建一个新的File实例。语法格式如下:
new File(String pathname)
其中,pathname指路径名称(包含文件名),例如:
File file = new File("C:\Users\XULIANG\abc.txt")
该构造方法根据定义的父路径和子路径字符串(包含文件名)创建一个新的File对象。语法格式如下:
new File (String parent, String child)
【问】那何为父路径与子路径呢?
这里举个例子,关于"C:\Users\XULIANG\Documents"这个目录,"C:"是"C:\Users"的父目录,"C:\Users"是"C:\Users\XULIANG"的父目录。简而言之,父目录就是当前目录的上级目录。
该构造方法根据parent抽象路径名和子路径字符串创建一个新的File对象。语法格式如下:
new File (File f, String child)
import java.io.File;
public class FileTest {
public static void main(String[] args) {
//创建文件对象,并指定文件名
File file = new File("test.txt");
//判断该文件是否存在
if (file.exists()){
//若存在,则删除文件
file.delete();
System.out.println("文件已删除");
}else {
//捕捉可能出现的异常
try {
//若不存在,则创建该文件
file.createNewFile();
System.out.println("文件已创建");
}catch (Exception e){
e.printStackTrace();
}
}
}
}
运行结果:
文件已创建
上述代码执行后,会在该项目所在的路径下创建一个名为"test.txt"的文本文件。
File类提供了很多方法用于获取文件的一些信息,常用的方法如下所示:
方法 | 返回值 | 说明 |
---|---|---|
getName() | String | 获取文件的名称 |
canRead() | boolean | 判断文件是否可读 |
canWrite() | boolean | 判断文件是否可写 |
exits() | boolean | 判断文件是否存在 |
length() | long | 获取文件的长度(以字节为单位) |
下面通过实例来介绍使用方法来获取文件的信息:
import java.io.File;
public class FileTest2 {
public static void main(String[] args) {
File file = new File("test.txt");
if(file.exists()){
String name = file.getName();
long length = file.length();
Boolean hidden = file.isHidden();
System.out.println("文件的名字:" + name);
System.out.println("文件的长度:" + length);
System.out.println("是否为隐藏文件:" + hidden);
}
}
}
运行结果:
文件的名字:test.txt
文件的长度:0
是否为隐藏文件:false
在程序的运行期间,大部分数据都保存在内存中进行操作,当程序结束后或关闭时,这些数据将消失。如果需要将数据永久保存,可使用文件输入/输出流与指定的文件建立连接,将需要的数据永久保存到文件中。
FileInputStream和FileOutputStream类都是用来操作磁盘文件。
FileInputStream类继承于InputStream类,满足比较简单的文件读取要求。FileInputStream类常用的构造方法有两种:
第一种构造方法使用给定文件名name,创建一个FileInputStream对象。第二种构造方法使用File对象创建FileInputStream对象,该构造方法允许在把文件连接输入流之前对文件作进一步分析。
FileOutputStream类与FileInputStream类具有相同的构造方法,创建一个FileOutputStream
对象时,可以指定不存在的文件名,但此文件不能是一个被其他程序打开的文件。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileTest3 {
public static void main(String[] args) {
File file = new File("word.txt");
System.out.println("---------------写入操作----------------");
try{
FileOutputStream fileOutputStream = new FileOutputStream(file);
//字符串转化成字节码形式,采用Java平台默认字符集进行编码
byte[] bytes = "Java基础班学习".getBytes();
System.out.println("\"Java基础班学习\"字符串的字节码形式:");
//遍历数组
for (int i = 0; i < bytes.length; i++) {
System.out.print(bytes[i] + " ");
}
System.out.println("\n总共 " + bytes.length + " 个字节");
//执行写入文件操作
fileOutputStream.write(bytes);
//关闭输出流
fileOutputStream.close();
}catch (IOException e){
e.printStackTrace();
}
System.out.println("---------------读取操作----------------");
try{
FileInputStream inputStream = new FileInputStream(file);
byte bytes[] = new byte[100];
//读取文件的数据内容,然后保存到bytes数组中,返回字节的个数
int str = inputStream.read(bytes);
System.out.println("该文件内容所占用的字节个数为:" + str);
/*
* 将数组中的字节进行解码,并转化为字符串
* 采用Java平台默认字符集进行解码
* 形参0表示起始索引位置,str表示截取长度
*/
String content = new String(bytes,0, str);
System.out.println("文件中的内容为:" + content);
//关闭输入流
inputStream.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
运行结果:
---------------写入操作----------------
"Java基础班学习"字符串的字节码形式:
74 97 118 97 -27 -97 -70 -25 -95 -128 -25 -113 -83 -27 -83 -90 -28 -71 -96
总共 19 个字节
---------------读取操作----------------
该文件内容所占用的字节个数为:19
文件中的内容为:Java基础班学习
【注意】虽说Java在程序结束时自动关闭所有打开的流,但是当使用完流后,应该显示地关闭所有打开地流仍是一个良好的习惯,一个被打开的流有可能耗尽系统资源。
使用FileOutputStream类向文件中写入数据与FileInputStream类从文件中读取内容,都存在一点不足,即这两个类都只提供了对字节或字节数组的读取方法。由于汉字在文件中占两个字节,如果使用字节流,读取不好可能会出现乱码现象,此时采用字符流Reader或Writer类即可避免这种现象。
FileReader和FileWriter字符流对应了FileInputStream和FileOutputStream类。FileReader流顺序地读取文件,只要不关闭流,每次调用read()方法就会顺序地读取源中地内容,直到源的末尾或流被关闭。
BufferedInputStream类可以对所有InputStream类进行缓存区的包装以达到性能优化的目的。BufferedInputStream类有两个构造方法:
第一种形式的构造方法创建了一个带有32个字节的缓存流,第二种形式的构造方法按指定的大小来创建缓存区。BufferedInputStream读取文件的过程如下所示:
数据流 数据流 数据流
文件 -------> InputStream -------> BufferedInputStream -------> 目的地
使用BufferedOutputStream输出信息和OutputStream输出信息完全一样,只不过BufferedOutputStream有一个flush()方法将缓存区的数据强制写入文件中。BufferedOutputStream也有两个构造方法:
第一种形式的构造方法创建了一个带有32个字节的缓存流,第二种形式的构造方法按指定的大小来创建缓存区。
【注意】flush()方法用于即使在缓存区没有满的情况下,也将缓存区的内容强制写入到外设,习惯上将这个过程称为刷新。
BufferedReader与BufferedWriter类分别继承于Reader和Writer类,这两个类同样具有内部缓存机制,并可以以行为单位进行输入/输出。
BufferedReader类常用的方法:
BufferedWriter类的方法都返回void,常用的方法:
在使用BufferedWriter类的write()方法时,数据并没有立刻被写入输出流,而是首先进入缓存区中。如果想立即将缓存区中的数据写入输出流时,必须调用flush()方法。
import java.io.*;
public class Student {
public static void main(String[] args) {
String content[] = {"你好吗","好久不见","记得常联系"};
File file = new File("word.txt");
try{
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
for (int i = 0; i < content.length; i++) {
bw.write(content[i]); //将字符数组的元素写入磁盘文件
bw.newLine(); //写入行分隔符
}
bw.close(); //关闭BufferedWriter流
fw.close(); //关闭FileWriter流
}catch (IOException e){
e.printStackTrace();
}
try {
FileReader fr = new FileReader(file);
BufferedReader bufr = new BufferedReader(fr);
String str = null;
int i = 0;
//读取文件的一行,若不为null,则进入循环
while ((str = bufr.readLine()) != null){
i++;
System.out.println("第" + i + "行:" + str);
}
bufr.close(); //关闭BufferedReader流
fr.close(); //关闭FileReader流
}catch (IOException e){
e.printStackTrace();
}
}
}
运行结果:
第1行:你好吗
第2行:好久不见
第3行:记得常联系
标签:错误 操作文件 i++ 读取数据 文件读取 传递 abc 返回 单位
原文地址:https://www.cnblogs.com/xuliang-daydayup/p/12946038.html