当我们需要从文本文件中读取内容,或者需要写入内容到文件中的时候,就需要用到JAVA中的流。
流包括输入流和输出流,读:使用输入流,写:使用输出流。为了方便记忆,分别拆分成以下4个步骤。
一、读取
1、新建文件输入流 FileInputStream (字节流,只能读取一个字节,fis.read())
FileInputStream fis = new FileInputStram(filePath);
2、新建一个 字符输入流InputStramReader ,(字符流,只能读取一个字符,isr.read())
InputStramReader isr = new InputStramReader(fis,"UTF-8");
3、新建一个 缓冲输入流BufferedReader (可读取一行字符,)
BufferedReader br=new BufferedReader(isr);
4、读取行
while((line=br.readLine())!=null){
System.out.println(line);
}
二、写入
1、新建文件输出流 FileOutputStream (字节流 )
FileOutputStream fos = new FileOutputStream(filePath);
2、新建一个 字符输出流OutputStreamWriter
OutputStreamWriter osw = new OutputStreamWriter(fos ,"UTF-8");
3、新建一个 缓冲输出流BufferedWriter (可写入一行字符,)
BufferedWriter bw=new BufferedWriter(osw);
4、写入行
ArrayList<String> popertiesLines = new ArrayList<String>();
for(String line:popertiesLines){
bw.write(line);
bw.newLine(); //换行
}
记忆路线(瞎扯):
读:FileInputStream -> InputStreamReader -> BufferedReader -> br.readLine();
写: FileOutputStream-> OutputStreamWriter -> BufferedWriter -> bw.write(line);
口诀:出写入读(都出血了,太恶毒),三流一操作
1、读写文件,当然首先想到文件(File),所以用到的是文件流:FileInputStream 、 FileOutputStream
用到文件流,那文件路径在哪儿? 所以需指定文件路径。
格式: new FileInputStream(fileRealPath);
2、有了文件流,要做啥操作,读or写 ? 想到 Reader,Writer。那就是 InputStreamReader 、 OutputStreamWriter
读写操作哪个文件? 所以需指定第1步创建的文件流,
读写操作使用那种字符? 所以需指定字符。
格式: new InputStreamReader(fis, "utf-8");
3、什么都不是一步到位的,需要一定的缓冲,想到 buffered,那就是 BufferedReader、BufferedWriter
读缓冲还是写缓冲? 所以需指定第2步创建的“读写流”。
格式:new BufferedReader(isr);
4、三流已备齐,开搞。
读 ? br.readLine();
写 ? bw.write(line); 写了一行记得换行啊: bw.newLine();
示例(修改一个配置文件):
/**
* 修改properties配置文件,保留原有注释。
* @param fileRealPath 文件绝对路径,
Linux: /root/iov_main/ly.mp.iov.login.main/bin
window:E:\后台开发工作空间\iov\ly.mp.iov.example.common\src\main\resources\domainname.properties
* @param keyName 键 ,如键不存在,则新增在后尾
* @param value 值
*/
public static boolean SetPropetyValue(String fileRealPath,String keyName,String value){
ArrayList<String> popertiesLines = new ArrayList<String>();
boolean hasKey=false;
BufferedReader br=null;
BufferedWriter bw=null;
try {
//1、读取配置文件
FileInputStream fis = new FileInputStream(fileRealPath);
InputStreamReader isr = new InputStreamReader(fis, "utf-8");
br = new BufferedReader(isr);
String line = "";
while ((line=br.readLine()) != null){
// 找到该key,重新赋值(修改value)
if(line.startsWith(keyName, 0)){
hasKey=true;
popertiesLines.add(keyName+"="+value);
logger.info("SetPropetyValue----->line.startsWith:"+keyName+",line:"+line);
}else{ //不是该key的行,直接追加
popertiesLines.add(line);
}
}
//全部没有找到,追加key
if(!hasKey){
popertiesLines.add(keyName+"="+value);
}
//2、重新写入配置文件
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fileRealPath),"UTF-8");
bw= new BufferedWriter(osw);
for(String lin:popertiesLines){
bw.write(lin);
bw.newLine();
}
bw.flush();
return true;
} catch (FileNotFoundException e) {
logger.error("SetPropetyValue FileNotFoundException---->exception info:" + e.toString());
return false;
} catch (IOException e) {
logger.error("SetPropetyValue IOException---->exception info:" + e.toString());
return false;
}finally{
//关闭流
if(br!=null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bw!=null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
知识点:
关于路径的分隔斜杠。
Windows:
“/”表示参数,“\” 表示本地路径。
Linux和Unix:
“/” 表示路径,“\”表示转义,“-”和“--”表示参数。
网络:
由于网络使用Unix标准,所以网络路径用“/”。
1、InputStream、OutputStream
处理字节流的抽象类
InputStream 是字节输入流的所有类的超类,一般我们使用它的子类,如FileInputStream等.
OutputStream是字节输出流的所有类的超类,一般我们使用它的子类,如FileOutputStream等.
InputStream能从來源处读取一個一個byte,所以它是最低级的。
2.InputStreamReader OutputStreamWriter
处理字符流的抽象类
InputStreamReader 是字节流通向字符流的桥梁,它将字节流转换为字符流.
OutputStreamWriter是字符流通向字节流的桥梁,它将字符流转换为字节流.
InputStreamReader封裝了InputStream在里头,它以较高级的方式,一次读取一个一个字符,初始化时需指定字符。
3.BufferedReader BufferedWriter
BufferedReader 由Reader类扩展而来,提供通用的缓冲方式文本读取,readLine读取一个文本行,
从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。
BufferedWriter 由Writer 类扩展而来,提供通用的缓冲方式文本写入, newLine使用平台自己的行分隔符,
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
BufferedReader则是比InputStreamReader更高级,它封裝了StreamReader类。
我们都知道计算机能识别的只有0和1,数据是以字节为单位存储的。
a.故在java中,我们若想要从文件中读取一个字符,首先我们需要有一个文件(数据源),于是我们就使用到了File类来制定一个文件;
b. 因为数据在计算机中都是0和1代码,以字节为单位,所以我们所指定的file对象就需要先转化成字节流,所以需要用到InputStream类;
c. 这时候,如果在java中只是以字节来读取文件的话,就足够了。但是如果想要以字符来读取文件的话,还需要对字节流进行以某种方式编码,因为不同的字符采用不同的编码方式,如果仍然使用字节流的话,可能会达不到我们想要的效果。我们可以指定字符编码方式,这个通过在InputStreamReader相关类的构造器中指定并实例化,默认下是Unicode编码方式。到了这里,我们已经用到了InputStreamReader。
d. 经过了上面三个步骤,我们已经可以从文件中读取到一个字符了,但是每次只读取一个字符又不能满足我们读取大数据的需求,这时候BufferedReader就派上用场了。从名字中的Buffer我们可以推测出它具有缓冲的作用,事实也是如此,它可以一次读取多个字符,一次性读取的字符数目还可以自由设置。