2019-03-02
2019-03-03 本文已影响5人
DreamPath
IO之字符流基础整理
字符流:
当使用字节流读取文本文件时,遇到中文字符时,可能不会显示完整的字符,由于一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。
字符输入流 Reader
java.io.Reader抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。
- public void close() :关闭此流并释放与此流相关联的任何系统资源。
- public int read() : 从输入流读取一个字符。
- public int read(char[] cbuf) : 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中。
FileReader子类
java.io.FileReader类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
- 字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。
- 字节缓冲区:一个字节数组,用来临时存储字节数据。
读取字符串
- 读取字符: read 方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回 -1 ,循环读取。
package Reader_Demo;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* FileReader(File file) : 创建一个新的 FileReader ,给定要读取的File对象。
* FileReader(String fileName) : 创建一个新的 FileReader ,给定要读取的文件的名称
*/
public class ReaderDemo1 {
public static void main(String[] args) throws IOException {
File file=new File("D:\\Java代码\\Java基础加强\\c.txt");
//使用File对象创建流对象
Reader reader1=new FileReader(file);
//直接使用文件名称创建流对象
Reader reader=new FileReader("D:\\Java代码\\Java基础加强\\c.txt");
int len;
//循环读取
while((len=reader.read())!=-1){
System.out.print((char)len);
}
reader.close();
reader1.close();
}
}
- 使用字符数组读取: read(char[] cbuf) ,每次读取b的长度个字符到数组中,返回读取到的有效字符个数, 读取到末尾时,返回 -1
package Reader_Demo;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class ReaderDemo2 {
public static void main(String[] args) throws IOException {
FileReader reader=new FileReader("c.txt");
//使用字符数组读取
char [] ss=new char[2];
// 定义变量,保存有效字符个数
int len;
// 定义字符数组,作为装字符数据的容器
while((len=reader.read(ss))!=-1){
//将ss的int编码转化为字符串输出
System.out.println(new String(ss));
}
char [] sss=new char[2];
int lenss;
while((lenss=reader.read(sss))!=-1){
//优化程序
System.out.println(new String(sss,0,len));
}
reader.close();
}
}
字符输出流 Writer
- java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。
FileWriter类
java.io.FileWriter 类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
package writer_demo;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author lx
* @date 2019/3/3 - 6:54
* FileWriter(File file) : 创建一个新的 FileWriter,给定要读取的File对象。
* FileWriter(String fileName) : 创建一个新的 FileWriter,给定要读取的文件的名称。
* 写出字符:
* write(int b) 方法,每次可以写出一个字符数据。
* 注意:
* 关闭资源时,与FileOutputStream不同。
* 如果不关闭,数据只是保存到缓冲区,并未保存到文件
*/
public class FileWriterDemo1 {
public static void main(String[] args) throws IOException {
/*//使用File对象来创建流对象
File dir=new File("D:\\Java代码\\Java基础加强\\c.txt");
FileWriter fileWriter=new FileWriter(dir);*/
//直接使用文件路径名创建流对象
FileWriter files=new FileWriter("D:\\Java代码\\Java基础加强\\c.txt");
// 写出字符
files.write(97);//写出第一个字符
files.write('a');//写出第二个字符
files.write('c');//写出第三个字符
files.write(30000);//写出第四个字符,中文编码中的一个汉字
files.close();
//输出结果:默认覆盖原文件数据。false
// aac田
}
}
关闭和刷新
- 因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。
- 但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要 flush 方法了。
- 如果不使用flush方法,输入的字节将会只存在于缓冲区里,数据关闭将会丢失。
package writer_demo;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* flush :刷新缓冲区,流对象可以继续使用。
* close :先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
*/
public class WriterDemo2 {
public static void main(String[] args) throws IOException {
File dir=new File("D:\\Java代码\\Java基础加强\\c.txt");
FileWriter fileWriter=new FileWriter(dir);
// 写出字符
fileWriter.write("刷");
fileWriter.flush();
fileWriter.write("新");//继续写出第二个字符,写出成功
fileWriter.flush();
fileWriter.write("关");
fileWriter.close();
// fileWriter.write("闭");//直接抛出异常 Stream closed 流被关闭了
// fileWriter.close();
}
}
写出其他字符串
package writer_demo;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author lx
* @date 2019/3/3 - 7:39
* 1. 写出字符数组 : write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,
* 每次可以写出字符数组中的数据,用法类似FileOutputStream
* 写出字符串
* 2. write(String str) 和 write(String str, int off, int len) ,
* 每次可以写出字符串中的 数据,更为方便。
*/
public class FileWriterDemo3 {
public static void main(String[] args) throws IOException {
FileWriter files=new FileWriter("D:\\Java代码\\Java基础加强\\c.txt");
char [] chars="程序员的世界".toCharArray();
//直接写出字符数组
files.write(chars);
//换行
files.write("\r\n");
//写出指定初始索引和长度的字符串
files.write(chars,2,2);
//换行
files.write("\r\n");
String msg="你好呀,Java";
//写出字符串
files.write(msg);
//换行
files.write("\r\n");
//写出指定索引长度字符串
files.write(msg,1,3);
files.close();
}
}
字符流,只能操作文本文件,不能操作图片,视频等非文本文件。
io异常处理
package io_exception;
import java.io.FileWriter;
import java.io.IOException;
/**
*异常建议使用 try...catch...finally
*/
public class IOExceptionDemo {
public static void main(String[] args) {
// jdk以前的处理方式:
//声明流对象,便于关流
FileWriter fw=null;
try {
//创建流对象 追加数据 true
fw=new FileWriter("D:\\Java代码\\Java基础加强\\出师表.txt",true);
//写出数据
fw.write("lalala");
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//jdk7的处理方式
// 要在try(异常处理多个语句时需用分号隔开){}
try(FileWriter fileWriter=new FileWriter
("D:\\Java代码\\Java基础加强\\出师表.txt",true)){
fileWriter.write("黑马程序员");
}catch (IOException e){
e.printStackTrace();
}
}
}
使用jdk9的处理方式来实现文本文件的复制
package copy_jdk9_StringFile;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author lx
* @date 2019/3/3 - 8:25
*使用jdk9异常引入来实现文本文件的复制操作
* JDK9中 try-with-resource 的改进,对于引入对象的方式,支持的更加简洁。
* 被引入的对象,同样可以自动关闭, 无需手动close
*/
public class CopyFileDemo {
public static void main(String[] args){
//创建文件的数据源
try (FileReader fr = new FileReader("D:\\Java代码\\Java基础加强\\出师表.txt")) {){
//创建文件的目的存储地
FileWriter fw = new FileWriter("D:\\Java代码\\Java基础加强\\复制出师表.txt");
try (fr; fw) {
int len;
while ((len = fr.read()) != -1) {
fw.write(len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
属性集
- java.util.Properties 继承于 Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值 都是一个字符串。
- 该类也被许多Java类使用,比如获取系统属性时, System.getProperties 方法就是返回一个 Properties 对象
Properties类
package properties_demo;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
/**
* 构造方法:
* public Properties() :创建一个空的属性列表。
* 基本方法:
* public Object setProperty(String key, String value) : 保存一对属性。
* public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。
* public Set<String> stringPropertyNames() :所有键的名称的集合
* 与流相关方法:
* public void load(InputStream inStream) : 从字节输入流中读取键值对
*/
public class PropertiesDemo {
public static void main(String[] args) throws IOException {
//创建属性集对象
Properties properties = new Properties();
//添加键值对元素
properties.setProperty("filename","a.txt");
properties.setProperty("length","2546894");
properties.setProperty("location","D:\\a.txt");
//打印属性集对象
System.out.println(properties);
//通过键的键获取属性值
System.out.println(properties.getProperty("filename"));
System.out.println(properties.getProperty("length"));
System.out.println(properties.getProperty("location"));
// 遍历属性集,获取所有键的集合
Set<String> set=properties.stringPropertyNames();
// 打印键值对
for (String ss:set) {
System.out.println(ss+"--"+properties.getProperty(ss));
}
//加载文本中信息到属性集
properties.load(new FileInputStream("复制出师表.txt"));
Set<String> set1=properties.stringPropertyNames();
//打印集合并输出
for (String sss:set1) {
System.out.println(sss+"---"+properties.getProperty(sss));
}
//文本中的数据,必须是键值对形式,可以使用空格、等号、冒号等符号分隔。
}
}