package io;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* java 标准的 IO
* java 将 IO 按照数据的流向分为输入流和输出流 -- 以程序为中心
* 输入流:把数据从外界读取到程序的流
* 输出流:把数据从程序写出到外界的流
* java 将 IO 比喻为"流",即 Stream ,就像生活中的"电流"、"水流"一样,
* 它是以同一个方向顺序移动的过程,只不过这里流动的是字节(2进制数据),
* 所以在 IO 中有输入流和输出流之分,我们可以理解它们是连接程序与另一端的"管道",
* 用于获取或发送数据到另一端.
*
* java定义了两个超类(抽象类): -- 超类、基类、父类
* java.io.InputStream: 所有字节输入流的超类
* java.io.OutputStream: 所有字节输出流的超类
* 里面定义了若干读取和写出字节的相关方法,所有字节流实现类都继承自它们,
* 因此,无论我们将来读写什么设备,只要使用对应的流,用相同的方法就可以了.
*
* java.io.FileOutputStream 和 java.io.FileInputStream
* 文件流,是常用的一对低级流,用于连接程序与文件(硬盘)的管道,负责读写文件数据.
*
* java也将流划分为两类:
* 低级流(节点流): 是真实连接我们程序与另一端的"管道",负责实际读写数据的流,
* 所有对数据的读写一定是建立在低级流基础上进行的.
* 高级流(处理流): 不能独立存在,必须连接在其他流上,
* 目的是当数据流经当前流时对其作某些加工处理,简化我们的读写操作.
*
* @author YanLy
* @date 2021/5/29 10:00
*/
public class Test01_FOSDemo {
public static void main(String[] args) throws IOException {
/*
构造方法:
FileOutputStream(String path)
FileOutputStream(File file)
以上构造方法创建的文件输出流是覆盖模式,即:
如果指定的文件已经存在,则会将该文件原有数据全部抹除,然后将通过当前流写出的数据保存到文件中
FileOutputStream(String path,boolean append)
FileOutputStream(File file,boolean append)
文件流有重载的构造方法,允许我们传入一个boolean参数,
该值如果为 true 则文件流创建时是追加模式,即:
创建文件流时若指定文件存在,则原内容全部保留,通过当前流写入的新内容都会被顺序追加到文件中。
与RandomAccessFile写文件的区别:
RAF是基于指针的随机读写形式,可以对文件任意位置 写操作 进行局部的覆盖,
但是文件流不行,由于java标准的 IO 是顺序读写形式,
对于 写操作 而言只能顺序向后写,不能回退,因此写操作的灵活性不如RAF,
但是后期基于流连接,我们可以串联若干高级流完成复杂的读写操作,这一点是RAF所不及的.
*/
FileOutputStream fos = new FileOutputStream("fos.txt",true);
String str = "改革春风吹满地,中国人民真争气,这个世界太疯狂,老鼠想给猫当伴娘.";
byte[]data = str.getBytes("utf-8");
fos.write(data);
str = "白云黑土~";
data = str.getBytes("utf-8");
fos.write(data);
System.out.println("写出完毕.");
fos.close();
}
}
package io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 使用文件输入流读取文件数据
*
* @author YanLy
* @date 2021/5/29 10:48
*/
public class Test02_FISDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
byte[]data = new byte[10000];
int len = fis.read(data);
System.out.println("实际读取到的字节数是: " + len);
String str = new String(data,0,len,"utf-8");
System.out.println(str);
}
}
package io;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* BufferedOutputStream 高级流/缓冲流
* 效率上来讲, BufferedOutputStream > FileOutputStream
* 原因是: BufferedOutputStream 底层维护了一个 byte[] buf 用来缓冲数据,
* 当数组满了,就一次性将数据保存到磁盘里,默认的数组容量是8192字节 相当于 8k
*
* @author YanLy
* @date 2021/5/29 11:24
*/
public class Test03_BOSDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("bos.txt",true);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write(48);
bos.write(49);
bos.write(50);
/*
void flush()
将缓冲流的缓冲区中已经缓存的数据一次性写出。
频繁调用这个方法会降低写数据的效率,但是可以保证写出数据的及时性。
*/
bos.flush();
// 调用close()会自动调用flush() 然后再关闭流
// bos.close();
// 关闭流的时候就把缓冲区里的数据一次性送走,相当于 close + flush
}
}
package io;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* BufferedInputStream 字节缓冲输入流 高级流
*
* 效率上来讲, BufferedInputStream > FileInputStream
* 原因是: BufferedInputStream 底层维护了一个 byte[] buf 用来缓冲数据,
* 当数组满了,就一次性将数据读取出来,默认的数组容量是8192字节 相当于 8k
*
*
* @author YanLy
* @date 2021/5/29 11:46
*/
public class Test04_BISDemo {
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bos.txt"));
// 开始读取
int len; // 定义变量,记录读取到的数据
while( ( len = bis.read() )!=-1){ // 没数据会读到-1 ,结束循环
System.out.println(len); // 打印读取到的数据
// 字符串
// byte[]data = (len+"").getBytes();
// String str = new String(data,"utf-8");
// System.out.println(str);
}
bis.close(); // 释放资源
}
}
package io;
import java.io.*;
/**
* 字符流
* java将流按照读写单位划分为 字节流 和 字符流
* java.io.InputStream 和 java.io.OutputSteam 是所有字节流的超类
* 而 java.io.Reader 和 java.io.Writer 则是所有字符流的超类,
* 它们是平级关系。
*
* Reader 和 Writer 是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法。
* 字符流最小读写单位是字符(char),
* 但是底层实际还是读写字节,只是字符与字节的转换工作由字符流完成。
*
* 转换流:java.io.InputStreamReader 和 java.io.OutputStreamWriter
* 它们是一对高级流,实际开发中我们在读写字符流而组建流连接时,
* 它们是非常重要的一环,但是我们不会直接操作这两个流。
* 转换流主要的作用:
* 1.衔接其他高级字符流与字节流
* 2.将字符与字节按照指定字符集进行转换 -- 字符集就是编码集
*
* @author YanLy
* @date 2021/5/29 14:05
*/
public class Test05_OSWDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("osw.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
osw.write("改革春风吹满地,");
osw.write("中国人民真争气~");
System.out.println("写出完毕!");
osw.close();
}
}
package io;
import java.io.*;
/**
* 使用转换流的输入流来读取文本数据
*
* @author YanLy
* @date 2021/5/29 14:29
*/
public class Test06_ISRDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("osw.txt");
InputStreamReader isr = new InputStreamReader(fis, "utf-8");
int d;
while((d=isr.read())!=-1){
System.out.print((char)d);
}
isr.close();
}
}
package io;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
/**
* 缓冲字符流输出流
* java.io.BufferedWriter
* 内部有缓冲区,可以块写文本数据来加快写出数据的速度。
*
* java.io.PrintWriter
* 具有自动行刷新的缓冲字符输出流,内部总是连接着BufferedWriter 作为缓冲加速功能,更常用。
*
*
* @author YanLy
* @date 2021/5/29 14:35
*/
public class Test07_BW_PWDemo {
public static void main(String[] args) throws Exception {
/*
PrintWriter 提供了直接对文件进行写操作的构造方法:
PrintWriter(String fileName)
PrintWriter(File file)
内部会自行完成流连接操作,对文件进行写文本。
PrintWriter(String fileName,String csn)
PrintWriter(File file,String csn)
创建的同时还可以指定字符集,推荐使用这样的方式创建。
实际开发中我们写出文本数据时都应当确定字符集,而不使用系统默认的。
只有写字符串写文本的时候 可以使用 PrintWriter
因为 PrintWriter 底层把所有的数据类型都转成了String
但是如果想要写其他数据类型,就不能使用 PrintWriter
可以使用多层嵌套... 因为多层嵌套传的是 二进制
*/
PrintWriter pw = new PrintWriter("pw.txt","utf-8");
pw.println("改革春风吹满地,中国人民真争气");
pw.println("这个世界太疯狂,老鼠想给猫当伴娘");
System.out.println("写出完成");
pw.close();
}
}
package io;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
/**
* java.io.BufferedReader 缓冲字符输入流
* 块读文本数据,并且可以按行读取字符串
*
*
* @author YanLy
* @date 2021/5/29 14:53
*/
public class Test08_BRDemo {
public static void main(String[] args) throws Exception {
// 字节流
FileInputStream fis = new FileInputStream("pw.txt");
// 转换流 : 连接字节流和字符流,设置编码集
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
// 字符流
BufferedReader br = new BufferedReader(isr);
String d;
/*
String readLine()
读取一行字符串并返回,返回的字符串中不含有这一行最后的换行符,
若某一行是空行(只有一个换行符) 则返回一个空字符串。
当返回值是 null 时,表示流读取到了末尾。
注:缓冲字符流第一次调用readLine()时并非只读取了第一行内容,
而是一次性读取若干字符并存入内部的缓冲区,然后仅将第一行内容进行返回而已,
再次调用则返回第二行内容,以此类推。
*/
while((d= br.readLine())!=null){
System.out.println(d);
}
br.close();
}
}
package io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/**
* 使用文件流完成文件的复制操作
* 流程:
* 1. 创建一个文件输入流,用于读取源文件
* 2. 创建一个文件输出流,用于写出复制的文件
* 3. 循环从原文件中读取字节写入到复制文件中完成复制操作
*
* @author YanLy
* @date 2021/5/29 15:58
*/
public class Test09_CopyDemo {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("API.CHM");
FileOutputStream fos = new FileOutputStream("API_copy.CHM");
byte[]data = new byte[1024*10];
int len;
while((len =fis.read(data)) != -1){
fos.write(data,0,len);
}
System.out.println("复制完成");
fos.close();
fis.close();
}
}
package io;
import java.io.*;
/**
* 使用流连接创建PrintWriter并完成文本数据的写出操作
*
* @author YanLy
* @date 2021/5/29 16:34
*/
public class Test10_PWDemo2 {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("pw2.txt",true);
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw);
pw.println("嵌套真烦,好麻烦~");
pw.println("还有一个多小时就放学啦好开心呀");
System.out.println("写出完成");
pw.close();
}
}
package io;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
/**
* @author YanLy
* @date 2021/5/29 16:43
*/
public class Test11_BRDemo2 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("pw2.txt");
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
BufferedReader br = new BufferedReader(isr);
String len;
while((len=br.readLine())!=null){
System.out.println(len);
}
br.close();
}
}
package io;
import java.io.*;
import java.util.Scanner;
/**
* 简易记事本:
* 实现简易记事本
* 程序启动后要求用户输入文件名,然后对文件进行写操作,
* 之后用户输入的每一行字符串都要按行写入到文件中
* 当用户单独输入 "exit" 时程序退出
*
* 要求:使用PrintWriter 并且自行创建流连接完成
*
* @author YanLy
* @date 2021/5/29 17:28
*/
public class Test12_NoteDemo {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("欢迎使用简易记事本:");
System.out.println("请输入文件名: ");
String fileName = scanner.nextLine();
System.out.println("请输入文件内容:");
FileOutputStream fos = new FileOutputStream(fileName+".txt",true);
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
BufferedWriter bw = new BufferedWriter(osw);
/*
当创建PrintWriter时第一个参数为 流,还可以再传入一个boolean类型的参数,
如果这个参数值为true,则当前PrintWrite具有自动行刷新功能,即:
每当我们调用println() 后会自动 flush
*/
PrintWriter pw = new PrintWriter(bw,true);
while(true){
String info = scanner.nextLine();
if ("exit".equals(info)){
break;
}
pw.println(info);
}
System.out.println("欢迎下次使用~");
pw.close();
}
}
package io;
import java.io.*;
import java.util.Scanner;
/**
* @author YanLy
* @date 2021/5/29 17:38
*/
public class Test13_NoteDemo2 {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("欢迎使用简易记事本:");
System.out.println("请输入你要查看内容的文件名: ");
String fileName = scanner.next();
FileInputStream fis = new FileInputStream(fileName+".txt");
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
BufferedReader br = new BufferedReader(isr);
String len;
while((len=br.readLine())!=null){
System.out.println(len);
}
br.close();
}
}