- IO流的作用是实现内存(Java程序)和硬盘之间的数据交互
- 我们以内存为参照物
- I 表示intput ,是数据从硬盘进内存的过程,称之为读数据
- O 表示output ,是数据从内存到硬盘的过程。称之为写数据
- IO的分类
-
按流向分类
-
按类型分类
-
字节流写数据入门
1创建字节输出流对象
注意事项:
如果文件不存在,就创建
如果文件存在就清空
2写数据
注意事项:
写出的整数,实际写出的是整数在码表上对应的字符
3释放资源
注意事项:
每次使用完流必须要释放资源
public class Test3 {
public static void main(String[] args) throws IOException {
// 创建字节输出流对象
/*如果字节输出流指向的对象不存在,会自动创建一个空的文件
如果字节输出流指向的文件存在,会将原文件中的内容清空 */
FileOutputStream fos = new FileOutputStream("day10\\x.txt");
// 写入数据
fos.write(97);
fos.write(98);
fos.write(99);
// 释放资源
fos.close();
/*x.txt内容:abc*/
}
}
- 字节流写数据的3种方式
void write(int b) // 一次写一个字节数据,得益于隐式数据转换,int可以接受byte和char类型的数据
void write(byte[] b) // 一次写一个字节数组数据
void write(byte[] b, int off, int len) // 一次写一个字节数组的部分数据
public class Test02 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("day10\\x.txt");
/*
fos.write(65);
fos.write(66);
fos.write('c');
// ABc
*/
/*
fos.write("nihaoahiahiahia".getBytes());
// nihaoahiahiahia
*/
fos.write("ahaha".getBytes(), 1, 3); // hah
fos.close();
}
}
-
字节流写数据的换行和追加写入
写完数据后,加换行符 windows : \r\n linux : \n mac : \r 字节流写数据如何实现追加写入呢? public FileOutputStream(String name,boolean append) 创建文件输出流以指定的名称写入文件 如果第二个参数为true, 不会清空文件里面的内容
public class Test03 {
public static void main(String[] args) throws IOException {
// 不会清空原来文件中的内容,而是在其基础上进行追加
FileOutputStream fos = new FileOutputStream("day10\\x.txt", true);
for (int i = 0; i < 10; i++) {
fos.write("hello".getBytes());
fos.write("\r\n".getBytes()); // windows下的换行
}
fos.close();
}
字节流读数据入门
1创建字节输入流对象
注意事项:
如果文件不存在,就直接报错
2读数据
注意事项:
读出来的是文件中数据的码表值 a->97
3释放资源
注意事项:
每次使用完流必须要释放资源
public class Test04 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("day10\\x.txt");
int by;
while ((by = fis.read()) != -1) {
System.out.print((char)by);
}
fis.close();
}
}
- 复制文件案例
public class Test05 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\11946\\Desktop\\idea快捷键.jpg");
FileOutputStream fos = new FileOutputStream("day10\\new.jpg");
int by;
while ((by = fis.read()) != -1) {
fos.write(by);
}
fis.close();
fos.close();
}
}
IO资源的处理
JDK7版本异常的捕获处理
- JDK7版本对流的释放做了优化 . 可以使用 try-with-resource 语句 , 该语句确保了每个资源在语句结束时自动关闭。简单理解 : 使用此语句,会自动释放资源 , 不需要自己在写finally代码块了
public class Test01 {
public static void main(String[] args) {
/*
try (创建流对象语句1 ; 创建流对象语句2 ...) {
// 读写数据
} catch (IOException e) {
处理异常的代码...
}
*/
try (FileInputStream fis1 = new FileInputStream("day10\\a.txt");
FileInputStream fis2 = new FileInputStream("day10\\b.txt")) {
// 读写数据
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 使用try-with-resource , 需要把流对象放在try的小括号中 , 流资源在使用完毕 , 会自动释放资源 , 代码相对于做了简化
字节输入流-读字节数组
- 为了解决速度问题,把字节流的数据读取字节数组中,提高读取效率
- 一次读一个字节数组的方法:
- public int read(byte[] b):从输入流读取最多b.length个字节的数据
- 返回的是真实读到的数据个数
public class Test09 {
public static void main(String[] args) {
try(FileInputStream fis = new FileInputStream("day10\\a.txt");) {
byte[] byts = new byte[1024]; // 数组的大小一般为1024的倍数
int len = -1; // 一次读取的字节个数
while((len = fis.read(byts)) != -1) {
System.out.print(new String(byts, 0, len)); // 读取了多少个就用多少个,防止用到没被覆盖的数据
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节缓冲流
- BufferedOutputStream:缓冲输出流
- BufferedInputStream:缓冲输入流
构造方法:
- 字节缓冲输出流:BufferedOutputStream(OutputStream out)
- 字节缓冲输入流:BufferedInputStream(InputStream in)
为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
- 字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作
public class homework03 {
public static void main(String[] args) {
File f1 = new File("F:\\img1");
File f2 = new File("F:\\img2");
copy(f1, f2);
}
// 将f1文件中的内容复制到f2文件中
private static void copy(File f1, File f2) {
File[] files = f1.listFiles();
String path = f2.getPath(); // 文件夹2的路径
for (File f : files) {
File newFile = new File(path + "\\" + f.getName());
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));) {
int len = -1;
byte[] bys = new byte[1024];
while((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Properties
Properties概述:
- 是一个Map体系的集合类
- Properties中有跟IO相关的方法
- 不需要加泛型, 默认存储的是Object类型, 但是工作中只存字符串
public class PropertiesDemo01 {
public static void main(String[] args) {
// 1 创建集合对象
Properties properties = new Properties();
// 2 添加数据
properties.put("it001", "张三");
properties.put("it002", "李四");
properties.put("it003", "王五");
// 3 遍历集合
Set<Object> keys = properties.keySet();
for (Object key : keys) {
System.out.println(key + " : " + properties.get(key));
}
}
}
因为在工作中使用Properties集合主要用来存储字符串, 因此其关于字符串的三个方法我们必须了解
// Object setProperty(String key, String value) 设置集合的键和值,都是String类型,相当于put方法
// String getProperty(String key) 使用此属性列表中指定的键搜索属性,相当于get方法
// Set<String> stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串 , 相当于keyset方法
public class PropertiesDemo02 {
public static void main(String[] args) {
// 1 创建集合对象
Properties properties = new Properties();
// 2 添加数据
properties.setProperty("it001", "张三");
properties.setProperty("it002", "李四");
properties.setProperty("it003", "王五");
// 3 遍历集合
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
System.out.println(key + " : " + properties.getProperty(key));
}
}
}
Properties和IO流结合的方法:
// void load(InputStream inStream) 以字节流形式 , 把文件中的键值对, 读取到集合中
// void load(Reader reader) 以字符流形式 , 把文件中的键值对, 读取到集合中
// void store(OutputStream out, String comments) 把集合中的键值对,以字节流形式写入文件中 , 参数二为注释, 可以传入null代表不写注释
// void store(Writer writer, String comments) 把集合中的键值对,以字符流形式写入文件中 , 参数二为注释
// load读取
public class PropertiesDemo03 {
public static void main(String[] args) throws IOException {
// 1 创建集合对象
Properties properties = new Properties();
// load 读取 properties文件中的信息
properties.load(new BufferedInputStream(new FileInputStream("day10\\test.properties")));
System.out.println(properties);
}
}
// store写入
public class PropertiesDemo04 {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
properties.setProperty("it001", "zhangsan");
properties.setProperty("it002", "lisi");
properties.setProperty("it003", "wangwu");
properties.store(new BufferedOutputStream(new FileOutputStream("day10\\test.properties")), null);
}
}
ResourceBundle工具类
API介绍
- java.util.ResourceBundle它是一个抽象类
- 我们可以使用它的子类PropertyResourceBundle来读取以.properties结尾的配置文件
- 通过静态方法直接获取对象
- static ResourceBundle getBundle(String baseName) 可以根据名字直接获取默认语言环境下的属性资源
- 参数注意: baseName
- 1.属性集名称不含扩展名
- 2.属性集文件是在src目录中的
public class ResourceBundleDemo {
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("user"); // 获取src目录下的user.properties中的内容
String username = bundle.getString("username"); // 通过键值获取内容
System.out.println(username);
// 链式编程
System.out.println(ResourceBundle.getBundle("user").getString("password"));
}
}