前面讲述了如何利用 File类对文件或目录的属性进行操作,但File类不能访问文件内容,即不能从文件中读取或往文件中写入数据,所以,下面要来介绍java中如何通过“流”来实现对文件的读写操作。
流的概念
流(Stream),是一个抽象的概念,是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道。
当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。
一般来说关于流的特性有下面几点:
先进先出:最先写入输出流的数据最先被输入流读取到。
顺序存取:可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile除外)
只读或只写:每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。
IO流的分类
- 按数据流的方向:输入流、输出流
- 按处理数据单位:字节流、字符流
- 按功能:节点流、处理流
InputStream类的常用方法
int read():从输入流中读取下一个字节数据,返回的是该字节的整数表示形式,如果读到输入流的末尾,则返回-1。不可输出中文
public class TestIO {
public static void main(String[] args) throws IOException {
//FileInputStream fis=new FileInputStream("a1.txt");
File f=new File("a1.txt");
FileInputStream fis=new FileInputStream(f);
// for (int i=0;i<f.length();i++) {//套个循环实现全文本输出
// int read = fis.read();//数据类型为int,需强转为char型
// System.out.print((char) read);//结果:t——a1文件里的第一个值
// }
int temp;
while((temp=fis.read())!=-1){//read()方法一次只运行一次读一个保证能全部输出
System.out.println((char)temp);
}
}
}
结果如下:
拓展:利用StringBUilder动态字符串数组来输出文本
public class TestIO {
public static String readFile(String path) throws IOException {
FileInputStream fis=new FileInputStream(path);
StringBuilder sb=new StringBuilder();//利用动态字符串是数组来接收每一个字节
int temp;
while((temp=fis.read())!=-1){
sb.append((char)temp);//往动态字符串数组添加
}
return sb.toString();
}
public static void main(String[] args) throws IOException {
File f=new File("a1.txt");
FileInputStream fis=new FileInputStream(f);
String s = readFile("a1.txt");//调用readFile方法
System.out.println(s);
}
}
int read(byte[] b):从输入流中读取数据,并将数据存储在缓冲区数组b中,返回实际读取的字节数,如果读到输入流的末尾,则返回-1。可以输出中文数组。
public static String readFileBytes(String path) throws IOException{
FileInputStream fis=new FileInputStream(path);
byte[] b=new byte[fis.available()];//fis.available()可从输入流中读取的字节数目
fis.read(b);
return new String(b);
}
public static void main(String[] args) throws IOException {
File f=new File("a1.txt");
FileInputStream fis=new FileInputStream(f);
String s = readFileBytes("a1.txt");//调用readFileBytes方法
System.out.println(s);
}
不抛出异常,采用try-catch来解决异常
public static String readFileBytes(String path){
FileInputStream fis=null;
byte[] b=null;
try {
fis = new FileInputStream(path);
b = new byte[fis.available()];//fis.available()可从输入流中读取的字节数目
fis.read(b);
}catch(IOException e){
e.printStackTrace();
}
finally{
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return new String(b);
}
int read(byte[] b,int off,int len):从输入流中读取最多len长度的字节保存到数组b中,保存的位置从off开始。
public static String readFileBytes(String path) throws IOException{
FileInputStream fis=new FileInputStream(path);
byte[] b=new byte[fis.available()];//fis.available()可从输入流中读取的字节数目
fis.read(b,5,10);
return new String(b);
}
public static void main(String[] args) throws IOException {
File f=new File("a1.txt");
FileInputStream fis=new FileInputStream(f);
String s = readFileBytes("a1.txt");//调用readFileBytes方法
System.out.println(s);
}
OutputStream常用方法:
void write(int c):将指定字节数据写入此输出流中,源文件中不能有中文!!!
public static void writeFile(String path,String s)throws IOException{
FileOutputStream fos=new FileOutputStream(path);
for (int i = 0; i < s.length() ; i++) {
char c = s.charAt(i);
fos.write(c);
}
fos.close();
}
public static void main(String[] args) throws IOException {
File f=new File("a1.txt");
FileInputStream fis=new FileInputStream(f);
String s = readFileBytes("a1.txt");//调用readFileBytes方法
System.out.println(s);
writeFile("b.txt",s);
void write(byte[] buf):将数组buf中的所有字节写入此输出流中。
public static void writeFileBytes(String path,String s)throws IOException{
FileOutputStream fos=new FileOutputStream(path);
byte[] b=s.getBytes();
fos.write(b);
fos.close();
}
public static void main(String[] args) throws IOException {
File f=new File("a1.txt");
FileInputStream fis=new FileInputStream(f);
String s = readFileBytes("a1.txt");//调用readFileBytes方法
System.out.println(s);
writeFileBytes("b1.txt",s);
在后面加个true就可以实现不覆盖原文件二在其基础上实现追加!
void write(byte[] b,int off,int len):将字节数组从偏移量off开始的长度为len的字节数据输出到输出流中