IO流
I/O流
存储和读取数据的解决方案
字节流(所有类型的文件)
字节输入流(InputStream)
书写步骤
- 创建字节输入流对象
- 如果文件不存在,就直接报错
- 读数据
- 细节一:一次读一个字节,读出来的是数据在ASCII上对应的数字
- 细节二:读到文件末尾了,read方法返回-1
- 释放资源
- 每次使用完流之后都要释放资源
import java.io.FileInputStream;
import java.io.IOException;
/**
* 字节输入流FileInputStream
* 实现需求:读取文件中的数据
*/
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建对象
FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\a.txt");
//2.读取数据
int b1 = fis.read();
System.out.println(b1); //97
int b2 = fis.read();
System.out.println((char)b2); //b
//3.释放资源
fis.close();
}
}
FileInputSteam循环读取
import java.io.FileInputStream;
import java.io.IOException;
/**
* FileInputSteam循环读取
*/
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建对象
FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\a.txt");
//2.循环读取
int b;
while ((b = fis.read()) != -1){
System.out.print((char)b);
}
//3.释放资源
fis.close();
}
}
字节输出流(OutputStream)
书写步骤
- 创建字节输出流对象
- 细节一:参数是字符串表示的路径或者是File对象都是可以的
- 细节二:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
- 细节三:如果文件已经存在,则会清空文件
- 写数据
- write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符
- 释放资源
- 每次使用完流之后都要释放资源
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 字节输出流FileOutputStream
* 实现需求:写出一段文字到本地文件中
*/
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建对象
FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\a.txt");
//2.写出数据
fos.write(97);
//3.释放资源
fos.close();
}
}
FileOutputStream写数据的三种方式
方法名称 | 说明 |
---|---|
void write(int b) | 一次写一个字节数据 |
void write(byte[] b) | 一次写一个字节数组数据 |
void write(byte[] b,int off,int len) | 一次写一个字节数组的部分数据 |
import java.io.FileOutputStream;
import java.io.IOException;
/**
* void write(int b)
* void write(byte[] b)
* void write(byte[] b,int off,int len) //byte[] b:数组 int off:起始索引 int len:个数
*/
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建对象
FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\a.txt");
//2.写出数据
//fos.write(97); //a
//fos.write(98); //b
//byte[] bytes = {97,98,99,100,101}; //abcde
//fos.write(bytes);
byte[] bytes = {97,98,99,100,101};
fos.write(bytes,1,2);
//3.释放资源
fos.close();
}
}
换行和续写
换行:再次写出一个换行符就可以了
- windows:\r\n
- Linux:\n
- Mac:\r
续写:如果想要续写,打开续写开关即可
开关位置:创建对象的第二个参数
默认false:表示关闭续写,此时创建对象会清空文件
手动传递true:表示打开续写,此时创建对象不会清空文件
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 换行和续写
*/
public class Demo03 {
public static void main(String[] args) throws IOException {
//1.创建对象
FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\a.txt",true);
//2.写出数据
String str1 = "abc";
byte[] bytes1 = str1.getBytes();
fos.write(bytes1);
String wrap = "\r\n";
byte[] bytes2 = wrap.getBytes();
fos.write(bytes2);
String str2 = "666";
byte[] bytes3 = str2.getBytes();
fos.write(bytes3);
//3.释放资源
fos.close();
}
}
文件拷贝
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 练习:文件拷贝
*/
public class Demo01 {
public static void main(String[] args) throws IOException {
long beginTime = System.currentTimeMillis();
copyFile();
long endTime = System.currentTimeMillis();
System.out.println("拷贝文件花费了"+(endTime-beginTime)+"毫秒");
}
public static void copyFile() throws IOException {
//1.创建对象
FileInputStream fis = new FileInputStream("C:\\Users\\86155\\Videos\\Captures\\a.mp4");
FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\copy.mp4");
//2.拷贝
//核心思想:边读边写
int b;
while ((b = fis.read()) != -1){
fos.write(b);
}
//3.释放资源
//规则:先开的最后关闭
fos.close();
fis.close();
}
}
FileInputSteam一次读取多个字节
方法名称 | 说明 |
---|---|
public int read() | 一次读一个字节数据 |
public int read(byte[] buffer) | 一次读一个字节数组数据 |
import java.io.FileInputStream;
import java.io.IOException;
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建对象
FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\a.txt");
//2.读取数据
byte[] bytes = new byte[2];
//一次读取多个字节数据,具体读多少,跟数组的长度有关
//返回值:本次读取到了多少个字节数据
int len1 = fis.read(bytes);
System.out.println(len1); //2
String str1 = new String(bytes,0,len1);
System.out.println(str1);
int len2 = fis.read(bytes);
System.out.println(len2); //2
String str2 = new String(bytes,0,len2);
System.out.println(str2);
int len3 = fis.read(bytes);
System.out.println(len3); //1
String str3 = new String(bytes,0,len3);
System.out.println(str3);
//3.释放资源
fis.close();
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo03 {
public static void main(String[] args) throws IOException {
long beginTime = System.currentTimeMillis();
//1.创建对象
FileInputStream fis = new FileInputStream("C:\\Users\\86155\\Videos\\Captures\\a.mp4");
FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\copy.mp4");
//2.拷贝
int len;
byte[] bytes = new byte[104 * 1024 * 5];
while ((len = fis.read(bytes)) != -1){
fos.write(bytes,0,len);
}
//3.释放资源
//规则:先开的最后关闭
fos.close();
fis.close();
long endTime = System.currentTimeMillis();
System.out.println("拷贝文件花费了"+(endTime-beginTime)+"毫秒");
}
}
字节缓冲流
原理:底层自带了长度为8192的缓冲区提高性能
方法名称 | 说明 |
---|---|
public BufferedInputStream(InputStream is) | 把基本流包装成高级流,提高读取数据的性能 |
public BufferedOutputStream(OutputStream os) | 把基本流包装成高级流,提高写出数据的性能 |
import java.io.*;
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建缓冲流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\code\\基础语法\\copy.txt"));
//2.循环读取并写到目的地
int b;
while ((b = bis.read()) != -1){
bos.write(b);
}
//3.释放资源
bos.close();
bis.close();
}
}
import java.io.*;
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建缓冲流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\code\\基础语法\\copy2.txt"));
//2.拷贝(一次读写多个字节)
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1){
bos.write(bytes,0,len);
}
//3.释放资源
bos.close();
bis.close();
}
}
序列化流/操作对象输出流
可以把Java中的对象写到本地文件中
细节:使用对象输出流将对象保存到文件时会出现NotSerializableException异常
解决方案:需要让Javabean类实现Serializable接口
构造方法 | 说明 |
---|---|
public ObjectOutputStream(OutputStream out) | 把基本流包装成高级流 |
成员方法 | 说明 |
---|---|
public final void writeObject(Object obj) | 把对象序列化(写出)到文件中 |
import java.io.Serializable;
/**
* Serializable接口里面没有抽象方法,标记型接口
* 一旦实现了这个接口,那么就表示当前的Student类可以被序列化
*/
public class Student implements Serializable {
private static final long serialVersionUID = 4322507240361300607L;
private String name;
private int age;
//transient:瞬态关键字
//作用:不会把当前属性序列化
private transient String address;
public Student() {
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建对象
Student s1 = new Student("张三",21,"北京");
//2.创建序列化流的对象/对象操作输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\code\\基础语法\\a.txt"));
//3.写出数据
oos.writeObject(s1);
//4.释放资源
oos.close();
}
}
反序列化流/操作对象输入流
可以把序列化到本地文件中的对象,读取到程序中来
构造方法 | 说明 |
---|---|
public ObjectInputStream(InputStream out) | 把基本流包装成高级流 |
成员方法 | 说明 |
---|---|
public Object readObject() | 把序列化到本地文件中的对象,读取到程序中来 |
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Demo02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1.创建反序列化流的对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
//2.读取数据
Student o = (Student) ois.readObject();
//3.打印对象
System.out.println(o);
//4.释放资源
ois.close();
}
}
字节打印流PrintStream
特点:
- 打印流只操作文件目的地,不操作数据源
- 特有的写出方法可以实现,数据原样写出
- 特有的写出方法,可以实现自动刷新,自动换行
构造方法 | 说明 |
---|---|
public PrintStream(OutStream/File/String) | 关联字节输出流/文件/文件路径 |
public PrintStream(String filename,Charset charset) | 指定字符编码 |
public PrintStream(OuntputStream out,boolean autoFlush) | 自动刷新 |
public PrintStream(OutputStream out,boolean autoFlush,String encoding) | 指定字符编码且自动刷新 |
成员方法 | 说明 |
---|---|
public void write(int b) | 常规方法:规则跟之前一样,将指定的字节写出 |
public void println(Xxx xx) | 特有方法:打印任意数据,自动刷新,自动换行 |
public void print(Xxx xx) | 特有方法:打印任意数据,不换行 |
public void printf(String format,Object... args) | 特有方法:带有占位符的打印语句,不换行 |
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
public class Demo01 {
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
//1.创建字节打印流的对象
PrintStream ps = new PrintStream(new FileOutputStream("F:\\code\\基础语法\\a.txt"),true,Charset.forName("UTF-8"));
//2.写出数据
ps.println(97);
ps.print(true);
ps.println();
ps.printf("%s爱%s","我","你");
//3.释放资源
ps.close();
}
}
压缩流
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建File对象表示要压缩的文件
File src = new File("F:\\a.txt");
//2.创建File对象表示压缩包的位置
File dest = new File("F:\\");
//3.调用方法来压缩
toZip(src,dest);
}
/**
* 作用:压缩
* 参数一:表示要压缩的文件
* 参数二:表示压缩包的位置
*/
public static void toZip(File src,File dest) throws IOException {
//1.创建压缩流关联压缩包
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest,"a.zip")));
//2.创建ZipEntry对象,表示压缩包里面的每一个文件和文件夹
ZipEntry entry = new ZipEntry("a.txt");
//3.把ZipEntry对象放到压缩包当中
zos.putNextEntry(entry);
//4.把src文件中的数据写到压缩包当中
FileInputStream fis = new FileInputStream(src);
int b;
while ((b = fis.read()) != -1){
zos.write(b);
}
zos.closeEntry();
zos.close();
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Demo03 {
public static void main(String[] args) throws IOException {
//1.创建File对象表示要压缩的文件夹
File src = new File("F:\\压缩包1");
//2.创建File对象表示压缩包放在那里(压缩包的父级路径)
File destParent = src.getParentFile();
//3.创建File对象表示压缩包的路径
File dest = new File(destParent, src.getName() + ".zip");
//4.创建压缩流关联压缩包
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest));
//5.获取src里面的每一个文件,变成ZipEntry对象,放入到压缩包当中
toZip(src,zos,src.getName());
//6.释放资源
zos.close();
}
/**
* 作用:获取src里面的每一个文件,变成ZipEntry对象,放入到压缩包当中
* 参数一:数据源
* 参数二:压缩流
* 参数三:压缩包内部的路径
*/
public static void toZip(File src,ZipOutputStream zos,String name) throws IOException {
//1.进入src文件夹
File[] files = src.listFiles();
//2.遍历数组
for (File file : files) {
if (file.isFile()){
//3.判断-文件,变成ZipEntry对象,放入到压缩包当中
ZipEntry entry = new ZipEntry(name + "\\" + file.getName());
zos.putNextEntry(entry);
//读取文件中的数据,写到压缩包
FileInputStream fis = new FileInputStream(file);
int b;
while ((b = fis.read()) != -1){
zos.write(b);
}
fis.close();
zos.closeEntry();
}else{
//4.判断-文件夹,递归
toZip(file,zos,name + "\\" + file.getName());
}
}
}
}
解压缩流
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建一个File表示要解压的压缩包
File src = new File("F:\\压缩包.zip");
//2.创建一个File表示解压的目的地
File dest = new File("F:\\");
//3.调用方法
unzip(src,dest);
}
//定义一个方法用来解压
public static void unzip(File src,File dest) throws IOException {
//解压的本质:把压缩包里面的每一个文件或者文件夹读取出来,按照层级拷贝到目的地当中
//创建一个解压缩流用来读取解压缩包中的数据
ZipInputStream zip = new ZipInputStream(new FileInputStream(src));
//要先获取压缩包里面的每一个zipentry对象
//表示当前在压缩包中获取到的文件或者文件夹
ZipEntry entry;
while ((entry = zip.getNextEntry()) != null){
System.out.println(entry);
if (entry.isDirectory()){
//文件夹:需要在目的地dest处创建一个同样的文件夹
File file = new File(dest,entry.toString());
file.mkdirs();
}else{
//文件:需要读取到压缩包中的文件,并把它存放到目的地dest文件夹中(按照层级目录进行存放)
FileOutputStream fos = new FileOutputStream(new File(dest,entry.toString()));
int b;
while((b = zip.read()) != -1){
//写到目的地
fos.write(b);
}
fos.close();
//表示在压缩包中的一个文件处理完毕了
zip.closeEntry();
}
}
zip.close();
}
}
字符集
-
计算机的存储规则:在计算机中,任意数据都是以二进制的形式来存储的
-
计算机中最小的存储单元是一个字节
-
ASCII字符集中,一个英文占一个字节
-
简体中文版windows,默认使用GBK字符集
-
GBK字符集完全兼容ASCII字符集
- 一个英文占一个字节,二进制第一位是0
- 一个中文占两个字节,二进制高位字节的第一位是1
-
Unicode字符集的UTF-8编码格式
- 一个英文占一个字节,二进制第一位是0,转成十进制是正数
- 一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数
Java中编码和解码的代码实现
Java中编码的方法:
String类中的方法 | 说明 |
---|---|
public byte[] getBytes() | 使用默认方式进行编码 |
public byte[] getBytes(String charsetName) | 使用指定方式进行编码 |
Java中解码的方法:
String类中的方法 | 说明 |
---|---|
String(byte[] bytes) | 使用默认方式进行解码 |
String(byte[] bytes,String charsetName) | 使用指定方式进行解码 |
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Demo01 {
public static void main(String[] args) throws UnsupportedEncodingException {
//1.编码
String str = "ai你呦";
byte[] bytes1 = str.getBytes();//utf-8
System.out.println(Arrays.toString(bytes1));
byte[] gbks = str.getBytes("GBK");
System.out.println(Arrays.toString(gbks));
//2.解码
String str2 = new String(bytes1);
System.out.println(str2);
String str3 = new String(bytes1,"GBK");
System.out.println(str3);
}
}
字符流(纯文本文件)
字符流的底层其实就是字节流
字符流=字节流+字符集
特点:
- 输入流:一次读一个字节,遇到中文时,一次读多个字节
- 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中
字符输入流(Reader)
书写步骤
-
创建字符输入流对象
构造方法 说明 public FileReader(File file) 创建字符输入流关联本地文件 public FileReader(String pathname) 创建字符输入流关联本地文件 - 如果文件不存在,就直接报错
-
读取数据
成员方法 说明 public int read() 读取数据,读到末尾返回-1 public int read(char[] buffer) 读取多个数据,读到末尾返回-1 -
细节一:按字节进行读取,遇到中文,一次读多个字节,读取后解码,返回一个整数
-
细节二:读到文件末尾了,read方法返回-1
-
-
释放资源
成员方法 说明 public int close() 释放资源/关流
import java.io.FileReader;
import java.io.IOException;
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建对象并关联本地文件
FileReader fr = new FileReader("F:\\code\\基础语法\\a.txt");
//2.读取文件
int ch;
while ((ch = fr.read()) != -1){
System.out.print((char)ch);
}
//3.释放资源
fr.close();
}
}
import java.io.FileReader;
import java.io.IOException;
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建对象
FileReader fr = new FileReader("F:\\code\\基础语法\\a.txt");
//2.读取数据
char[] chars = new char[2];
int len;
//read(chars):读取数据,解码,强制三步合并了,把强转之后的字符放到数组当中
//空参的read+强制类型转换
while ((len = fr.read(chars)) != -1){
//把数组中的数据变成字符串再进行打印
System.out.println(new String(chars,0,len));
}
//3.释放资源
fr.close();
}
}
字符输出流(Writer)
书写步骤
-
创建字符输出流对象
构造方法 说明 public FileWriter(File file) 创建字符输出流关联本地文件 public FileWriter(String pathname) 创建字符输出流关联本地文件 public FileWriter(File file,boolean append) 创建字符输出流关联本地文件,续写 public FileWriter(String pathname,boolean append) 创建字符输出流关联本地文件,续写 -
细节一:参数是字符串表示的路径或者File对象都是可以的
-
细节二:如果文件不存在就会创建一个新的文件,但是要保证父级路径是存在的
-
细节三:如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关
-
-
写出数据
成员方法 说明 void write(int c) 写出一个字符 void write (String str) 写出一个字符串 void write(String str,int off,int len) 写出一个字符串的一部分 void write(char[] cbuf) 写出一个字符数组 void write(char[] cbuf,int off,int len) 写出一个字符数组的一部分 - 如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符
-
释放资源
- 每次使用完流之后都要释放资源
import java.io.FileWriter;
import java.io.IOException;
public class Demo03 {
public static void main(String[] args) throws IOException {
//1.创建对象
FileWriter fw = new FileWriter("F:\\code\\基础语法\\a.txt",true);
//2.写数据
//fw.write(25105);
//fw.write("你好!!!");
//String str = "你你你好好好";
//fw.write(str,2,2);
char[] chars = {'a','b','c','我'};
fw.write(chars);
//3.释放资源
fw.close();
}
}
字符缓冲流
原理:底层自带了长度为8192的缓冲区提高性能
方法名称 | 说明 |
---|---|
public BufferedReader(Reader r) | 把基本流变成高级流 |
public BufferedWriter(Writer r) | 把基本流变成高级流 |
字符缓冲输入流(BufferedReader)
字符缓冲输入流特有方法 | 说明 |
---|---|
public String readLine() | 读取一行数据,如果没有数据可读了,会返回null |
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Demo03 {
public static void main(String[] args) throws IOException {
//1.创建字符缓冲输入流的对象
BufferedReader br = new BufferedReader(new FileReader("F:\\code\\基础语法\\a.txt"));
//2.读取数据
//细节:
//readLine方法在读取的时候,一次读一整行,遇到回车换行结束,但是它不会把回车换行读到内存当中
//String line = br.readLine();
//System.out.println(line);
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
//3.释放资源
br.close();
}
}
字符缓冲输出流(BufferedWriter)
字符缓冲输出流特有方法 | 说明 |
---|---|
public void newLine() | 跨平台的换行 |
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Demo04 {
public static void main(String[] args) throws IOException {
//1.创建字符缓冲输出流的对象
BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\code\\基础语法\\a.txt",true));
//2.写出数据
bw.write("我我我");
bw.newLine();
bw.write("你你你");
bw.newLine();
//3.释放资源
bw.close();
}
}
字符转换流
是字符流和字节流之间的桥梁
字符转换输入流:InputStreamReader
字符转换输出流:OutputStreamWriter
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
/**
* 利用转换流按照指定字符编码读取
*/
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建对象并指定字符编码
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\code\\基础语法\\gbkfile.txt"),"GBK");
//2.读取数据
int ch;
while ((ch = isr.read()) != -1){
System.out.println((char)ch);
}
//3.释放资源
isr.close();
//替代方案
//FileReader fr = new FileReader("F:\\code\\基础语法\\gbkfile.txt", Charset.forName("GBK"));
//2.读取数据
//int ch;
//while ((ch = fr.read()) != -1){
//System.out.println((char)ch);
//}
//3.释放资源
//fr.close();
}
}
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
/**
* 利用转换流按照指定字符集编码写出
*/
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建转换流的对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\code\\基础语法\\a.txt"),"GBK");
//2.写入数据
osw.write("你好");
//3.释放资源
osw.close();
//FileWriter fw = new FileWriter("F:\\code\\基础语法\\b.txt", Charset.forName("GBK"));
//2.写出数据
//osw.write("你好");
//3.释放资源
//osw.close();
}
}
import java.io.*;
import java.nio.charset.Charset;
/**
* 将本地文件中的GBK文件,转成UTF-8
*/
public class Demo03 {
public static void main(String[] args) throws IOException {
//1.JDK11以前的方案
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\code\\基础语法\\gbkfile.txt"),"GBK");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\code\\基础语法\\b.txt"),"UTF-8");
int b;
while ((b = isr.read()) != -1){
osw.write(b);
}
osw.close();
isr.close();
//替代方案
//FileReader fr = new FileReader("F:\\code\\基础语法\\gbkfile.txt", Charset.forName("GBK"));
//FileWriter fw = new FileWriter("F:\\code\\基础语法\\b.txt",Charset.forName("UTF-8"));
//int b;
//while ((b = fr.read()) != -1){
//fw.write(b);
//}
//fr.close();
//fw.close();
}
}
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码
*/
public class Demo04 {
public static void main(String[] args) throws IOException {
// FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\b.txt");
// InputStreamReader isr = new InputStreamReader(fis);
// BufferedReader br = new BufferedReader(isr);
//
// String str = br.readLine();
// System.out.println(str);
// br.close();
//替代方案
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("F:\\code\\基础语法\\b.txt")));
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
br.close();
}
}
字符打印流PrintWriter
字符流底层有缓冲区,想要自动刷新需要开启
特点:
- 打印流只操作文件目的地,不操作数据源
- 特有的写出方法可以实现,数据原样写出
- 特有的写出方法,可以实现自动刷新,自动换行
构造方法 | 说明 |
---|---|
public PrintWriter(Write/File/String) | 关联字节输出流/文件/文件路径 |
public PrintWriter(String filename,Charset charset) | 指定字符编码 |
public PrintWriter(Write w,boolean autoFlush) | 自动刷新 |
public PrintWriter(OutputStream out,boolean autoFlush,Charset charset) | 指定字符编码且自动刷新 |
成员方法 | 说明 |
---|---|
public void write(...) | 常规方法:规则跟之前一样,将指定的字节写出 |
public void println(Xxx xx) | 特有方法:打印任意类型的数据并且换行 |
public void print(Xxx xx) | 特有方法:打印任意数据,不换行 |
public void printf(String format,Object... args) | 特有方法:带有占位符的打印语句 |
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建字符打印流的对象
PrintWriter pw = new PrintWriter(new FileWriter("F:\\code\\基础语法\\a.txt"),true);
//2.写出数据
pw.println("我我哦我我");
pw.print(true);
pw.printf("%s爱%s","我","你");
//3.释放资源
pw.close();
}
}
综合练习
1.拷贝文件夹
/**
* 拷贝文件夹
*/
import java.io.*;
public class Test01 {
public static void main(String[] args) throws IOException {
//拷贝一个文件夹,考虑子文件夹
//1.创建对象表示数据源
File test = new File("F:\\test");
//2.创建对象表示目的地
File dest = new File("F:\\dest");
//3.调用方法开始拷贝
copydir(test,dest);
}
/**
* 作用:拷贝文件夹
* 参数一:数据源
* 参数二:目的地
*/
private static void copydir(File test,File dest) throws IOException {
//递归
//1.进入数据源
File[] files = test.listFiles();
//2.遍历数组
for (File file : files){
if (file.isFile()){
//3.判断文件,拷贝
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(new File(dest,file.getName()));
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1){
fos.write(bytes,0,len);
}
fos.close();
fis.close();
}else{
//4.判断文件夹,递归
copydir(file,new File(dest,file.getName()));
}
}
}
}
2.加密和解密文件
/**
* 加密和解密文件
*/
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test02 {
public static void main(String[] args) throws IOException {
//加密
//1.创建对象关联原始文件
FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\gy.jpg");
//2.创建对象关联加密文件
FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\ency.jpg");
//3.加密处理
int b;
while ((b = fis.read()) != -1){
fos.write(b ^ 2);
}
//4.释放资源
fos.close();
fis.close();
//解密
//1.创建对象关联原始文件
FileInputStream fis1 = new FileInputStream("F:\\code\\基础语法\\ency.jpg");
//2.创建对象关联加密文件
FileOutputStream fos1 = new FileOutputStream("F:\\code\\基础语法\\redu.jpg");
//3.加密处理
int b1;
while ((b1 = fis1.read()) != -1){
fos1.write(b1 ^ 2);
}
//4.释放资源
fos.close();
fis.close();
}
}
3.将文件中的数据进行排序
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
/**
* 将文件中的数据进行排序
*/
public class Test03 {
public static void main(String[] args) throws IOException {
//1.读取数据
FileReader fr = new FileReader("F:\\code\\基础语法\\a.txt");
StringBuffer sb = new StringBuffer();
int ch;
while ((ch = fr.read()) != -1){
sb.append((char)ch);
}
fr.close();
System.out.println(sb);
//2.排序
String str = sb.toString();
String[] arrstr = str.split("-");
ArrayList<Integer> list = new ArrayList<>();
for (String string : arrstr){
int i = Integer.parseInt(string);
list.add(i);
}
Collections.sort(list);
System.out.println(list);
//3.写出
FileWriter fw = new FileWriter("F:\\code\\基础语法\\a.txt");
for (int i = 0; i < list.size(); i++) {
if (i == list.size()-1){
fw.write(list.get(i)+"");
}else{
fw.write(list.get(i)+"-");
}
}
fw.close();
}
}
4.四种拷贝方式效率对比
/**
* 四种拷贝方式效率对比
*/
import java.io.*;
public class Test04 {
public static void main(String[] args) throws IOException {
long beginTime = System.currentTimeMillis();
//method1();
//method2();
//method3();
method4();
long endTime = System.currentTimeMillis();
System.out.println("拷贝文件花费了"+(endTime-beginTime)+"毫秒");
}
/**
* 字节流的基本流:一次读写一个字节
*/
public static void method1() throws IOException {
//1.创建对象
FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\a.txt");
FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\a1.txt");
//2.拷贝
//核心思想:边读边写
int b;
while ((b = fis.read()) != -1){
fos.write(b);
}
//3.释放资源
//规则:先开的最后关闭
fos.close();
fis.close();
}
/**
* 字节流的基本流:一次读写一个字节数组
*/
public static void method2() throws IOException {
//1.创建对象
FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\a.txt");
FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\a1.txt");
//2.拷贝
int len;
byte[] bytes = new byte[104 * 1024 * 5];
while ((len = fis.read(bytes)) != -1){
fos.write(bytes,0,len);
}
//3.释放资源
//规则:先开的最后关闭
fos.close();
fis.close();
}
/**
* 字节缓冲流:一次读写一个字节
*/
public static void method3() throws IOException {
//1.创建缓冲流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\code\\基础语法\\a1.txt"));
//2.循环读取并写到目的地
int b;
while ((b = bis.read()) != -1){
bos.write(b);
}
//3.释放资源
bos.close();
bis.close();
}
/**
* 字节缓冲流:一次读写一个字节数组
*/
public static void method4() throws IOException {
//1.创建缓冲流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\code\\基础语法\\a1.txt"));
//2.拷贝(一次读写多个字节)
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1){
bos.write(bytes,0,len);
}
//3.释放资源
bos.close();
bis.close();
}
}
5.将<<出师表>>的文章顺序进行恢复到一个新文件中
/**
* 将<<出师表>>的文章顺序进行恢复到一个新文件中
*/
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Test05Case01 {
public static void main(String[] args) throws IOException {
//1.读取数据
BufferedReader br = new BufferedReader(new FileReader("F:\\code\\基础语法\\a.txt"));
String line;
ArrayList<String> list = new ArrayList<>();
while ((line = br.readLine()) != null){
list.add(line);
}
br.close();
//2.排序
//排序规则:按照每一行前面的序号进行排序
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//获取o1和o2的序号
int i1 = Integer.parseInt(o1.split("\\.")[0]);
int i2 = Integer.parseInt(o2.split("\\.")[0]);
return i1 - i2;
}
});
//3.写出
BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\code\\基础语法\\csb.txt"));
for (String str : list){
bw.write(str);
bw.newLine();
}
bw.close();
}
}
import java.io.*;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class Test05Case02 {
public static void main(String[] args) throws IOException {
//1.读取数据
BufferedReader br = new BufferedReader(new FileReader("F:\\code\\基础语法\\a.txt"));
String line;
TreeMap<Integer, String> tm = new TreeMap<>();
while ((line = br.readLine()) != null){
String[] arr = line.split("\\.");
//0:序号 1:内容
tm.put(Integer.parseInt(arr[0]),arr[1]);
}
br.close();
System.out.println(tm);
//2.写出数据
BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\code\\基础语法\\csb.txt"));
Set<Map.Entry<Integer,String>> entries = tm.entrySet();
for (Map.Entry<Integer,String> entry : entries){
String value = entry.getValue();
bw.write(value);
bw.newLine();
}
bw.close();
}
}
6.软件运行次数
/**
* 软件运行次数
*/
import java.io.*;
public class Test06 {
public static void main(String[] args) throws IOException {
//1.把文件中的数据读取到内存中
BufferedReader br = new BufferedReader(new FileReader("F:\\code\\基础语法\\count.txt"));
String line = br.readLine();
int count = Integer.parseInt(line);
count++;
//2.判断
//<=3 正常运行
//>3 不能运行
if (count <= 3){
System.out.println("欢迎使用本软件,第"+count+"次使用免费~");
}else{
System.out.println("本软件只能免费试用三次,欢迎您注册会员后继续使用");
}
//3.把当前自增后的count写出到文件当中
BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\code\\基础语法\\count.txt"));
bw.write(count + "");
bw.close();
}
}
7.将多个自定义对象序列化到文件中,但是对象的个数不确定,该如何操作
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = -2910356930418031274L;
private String name;
private int age;
private String address;
public Student() {
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
/**
* 将多个自定义对象序列化到文件中,但是对象的个数不确定,该如何操作
*/
public class Test07 {
public static void main(String[] args) throws IOException {
//1.序列化多个对象
Student s1 = new Student("张三", 21, "北京");
Student s2 = new Student("李四", 22, "南京");
Student s3 = new Student("王五", 23, "东京");
ArrayList<Student> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\code\\基础语法\\a.txt"));
oos.writeObject(list);
oos.close();
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
public class Test08 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1.创建反序列化流的对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
//2.读取数据
ArrayList<Student> list = (ArrayList<Student>)ois.readObject();
for (Student student : list) {
System.out.println(student);
}
ois.close();
}
}