IO处理
I/O:input/Output, 输入/输出。
BufferedReader br = new BuffereReader(new InputStreamReader(System.in));
br.red();
1. 什么是输入流 ,输出流
将自己编写的程序外部数据输入到程序内部。
将程序内部定义的数据传出程序的外部。
输入 ——>InputStream 字符流 Reader
输出 ——>OutputStream 字符流 Writer
中文编码 UTF-8 gb2312,
从数据的流向可以分为:输入流和输出流从数据的单位可以分为:字节流和字符流
按功能不同分为:节点流(单功能)、处理流(复合功能)
File类:
1.File类在java.io包中。
2.File类用来表示磁盘文件信息的对象,它定义了一些与平台无关的方法了操纵文件。
3.File类是直接操纵文件本身的,因此它不是一个基于流的类,不能使用File类来修改文件的内容。
4.调用File类提供的各种方法,能够创建、重命名、删除文件、判断文件是否存在、设置和查询文件各个 属性等等。
5.磁盘上的文件目录也是一个File对象,通过该对象可以浏览子目录的所有文件。
文件和目录(文件夹) ——>路径名的抽象表示形式。
文件或者是目录(文件夹)的对象在Java中就是使用File类的对象来表示的。
// 1. 文本文档的路径
String path = "D:\\test\\io1.txt";
// 2. 根据文本文档的路径获取文件的对象?
File ioTest = new File(path);
// 3. 测试File中的方法
// 3.1 判断txt文件是否是只读
boolean b = ioTest.canWrite();
System.out.println(b?"可写":"只读");
// 3.2 判断某个文件是否存在
boolean exists = ioTest.exists()
// 3.3 创建一个文件
boolean newFileFlag = ioTest.createNewFile();
// 3.4 删除一个文件
// - 根据路径字符串创建文件的对象
// - 判断这个文件是否存在
// - 删除
String path1 = "D:/test/io1.txt";
File f1 = new File(path1);
f1.delete();
/*
mkdir: 创建单层文件夹
mkdirs : 创建嵌套的文件夹
*/
f3.mkdirs();
String sep = System.getProperty("file.separator");
// 3.5 绝对路径与相对路径
String ioPath = "io.txt"; // 相对路径
File f2 = new File(ioPath);
System.out.println("文件名:" + f2.getName());
// 绝对路径 : 项目所在的文件路径
System.out.println(f2.getAbsoluteFile());
String dirPath = "d:/test/io/io1/io2/io3" ;
File f3 = new File(dirPath);
注意:File类的对象,不能操作文件当中的数据,只能操作文件的外部属性。
10/10/2022
递归:
就是方法调用方法本身,它的执行逻辑。
注意:其实递归就是一个循环,在循环中,是要有循环变量、循环控制条件、循环体三大要素的。
递归:在Java中使用最多的一个应用就是遍历文件夹,网盘、硬盘。凡是树状结构的数据,都可以采用递归来遍历。导航栏,
递归其实就是调用该方法本身,比如说我们现在进行的文件夹的相关操作都是一样的,就可以将这个逻辑写在一个方法中,进行递归即可。
import java.io.File;
public class Test {
public static void createDir() throws Exception {
String path = "d:/test/io/";
int index = 1 ;
File file = null ;
for(int i = 1; i <= 3 ;i ++) {
File dir = new File(path + "io" + i);
dir.mkdirs();
file = new File((path + "io" + i + "/test" + index + ".txt"));
file.createNewFile();
index ++ ;
file = new File((path + "io" + i + "/test" + index + ".txt"));
file.createNewFile();
index ++ ;
}
}
public static void forEachDir(String path , int level) {
StringBuilder space = new StringBuilder("");
for(int i = 0 ; i < level ; i ++) {
space.append(" ");
}
File file = new File(path) ;
File[] files = file.listFiles(); // 获取file目录下的所有子文件及子文件夹
for(File f : files) {
String name = f.getName();
if(f.isDirectory()) {
System.out.println(space + name);
// 进行递归
forEachDir(path + "\\" + name , level + 1);
} else {
// 直接打印
System.out.println(space + name);
}
}
}
public static void main(String[] args) throws Exception{
createDir(); // 创建目标文件夹结构
forEachDir("d:/test/", 0);
}
}
5.IO流
1字节输入流(InputStream)
InputStream是一个抽象类
所有的流对象,都会占用计算机资源,在使用完之后需要手动关闭。则需要调用流对象的close().
每一个流的类都实现Closeable接口,并重写了这个接口中的close()方法。
节点流:
5.1.1.1 : FileInputStream
文件字节输入流。如果这个流,程序就会创建一根管道,管道输出方向是从文件–>程序内部。
FileInputStream
从文件系统中的文件获取输入字节。什么文件可用取决于主机环境。
FileInputStream
用于读取诸如图像数据的原始字节流。 要阅读字符串,请考虑使用FileReader
。
FileInputStream(File file)
通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
FileInputStream(FileDescriptor fdObj)
创建 FileInputStream通过使用文件描述符 fdObj ,其表示在文件系统中的现有连接到一个实际的文件。
FileInputStream(String name)
通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
5.1.1.2: PipedInputstream
线程与线程之间进行通讯,当前程序在其他线程中读取数据。(了解)
public static void main(String[] args) throws IOException {
//读取一个文件
// 1.找到文件:路径d : /test/io/Test.java
string path = "d: /ltest/io/Test.java" ;
// 2.创建了连接相关路径指向的文件的流对象,相当于打开了文件和程序的
Inputstream is = new FileInputStream(path);
// 3.按字节读取文件中的数揖
int b = 0 ;
//当is.read()读取到文件最末尾的一个字节时,再往下面read返回-1//正常read返回的是字符的ascii码。
while((b = is.read()) >= 0) {
system.out.print((char) b);
}
//4.关闭输入流
is.close();
}
5.1.1.3: ByteArraylnputStream
A ByteArrayInputStream
包含一个内部缓冲区,其中包含可以从流中读取的字节。内部计数器跟踪read
方法要提供的下一个字节。
关闭ByteArrayInputStream
没有任何效果。 在关闭流之后,可以调用此类中的方法,而不生成IOException
。
处理流
BufferedInputStream 缓冲
之前FileInputStream是连接的硬盘中的文件,ByteArrayInputStream是连接的字节类型的数组。JVM内存当中的。
缓冲字节输入流
可以采用缓冲流的方式解决两个问题:
1.磁盘IO的次数减少
⒉.减少(不是避免)中文乱码的问题
string path = "d : : itesti l ioi iTest.java";
//节点流:—个字节一个字节读
//硬盘读写。效率非常低,读取次数越多对硬盘伤害就越大。
//应尽量减少对硬盘的读写操作次数。
FileInputStream is = new FileInputstream(path);
//处理流->为FileInputStream添加缓冲区
BufferedInputStream bis = new BufferedInputstream(is);
byte[] bytes = new byte[1024];
while( bis .read(bytes) != -1){
string str = new string(bytes);
system. out. print(str);
}
bis.close();
is.close();
available():返回数组中的可读的字节数
SequenceInputStream 序列字节输出流
DataInputStream 数据输入流
数据输入流允许应用程序以独立于机器的方式从底层输入流读取原始Java数据类型。应用程序使用数据输出流来写入稍后可以被数据输入流读取的数据。
DataInputStream对于多线程访问来说不一定是安全的。 线程安全是可选的,是本课程中用户的责任。
ObjectlnputStream 反序列化字节输入流
字符输入流
代码
public static void main(String[] args) throws Exception{
//1.获取路径,指向一个文件
String path = "d:/test/io/io1/test.java";
//2.创建链接到这个文件的管道(字节、字符流)
Reader reader = new FileReader(path);
//3. read方法,循环读取。
// 字节: byte
//字符: char
int c = 0;
while ((c = reader.read()) != -1){
System.out.println((char) c);
}
//关闭流对象
reader.close();
}
字符输入流中的抽象类为Reader。就跟InputStream一样,在API中,InputStream这个抽象类所拥有的子类,在Reader中也有一套。它们的方法基本相同,只是处理的数据格式不同。
lnputStream的子类对象处理的是字节。
Reader的子类对象处理的是字符。
InputStream已知直接子类:
AudioInputStream , ByteArrayInputStream , FileInputStream , FilterInputStream , InputStream , ObjectInputStream , PipedInputStream , SequenceInputStream , StringBufferInputStream
InputStream另请参见:
BufferedInputStream
, ByteArrayInputStream
, DataInputStream
, FilterInputStream
, read()
, OutputStream
, PushbackInputStream
Reader已知直接子类:
BufferedReader , CharArrayReader , FilterReader , InputStreamReader , PipedReader , StringReader
Reader另请参见:
BufferedReader
, LineNumberReader
, CharArrayReader
, InputStreamReader
, FileReader
, FilterReader
, PushbackReader
, PipedReader
, StringReader
, Writer
字节输出流
抽象类:OutputStream
OutputStream已知直接子类:
ByteArrayOutputStream , FileOutputStream , FilterOutputStream , ObjectOutputStream , OutputStream , PipedOutputStream
字符输出流
抽象类: writer
string data ="你好,中国!! ! ";
// 1.路径
String path = "d : \ ltestilioi ihe11o.txt";
//2.管道
writer writer = new Filewriter(path);
// 3.写
writer. write(data) ;
//4.清空缓冲区,并将缓冲区的数据进行输出
writer.flush();
//5.关闭管道
writer.close();
注意:在使用输出流的时候,一定要先去flush一下缓冲区,再对输出流进行关闭。
方向流
5.2.2转换流
lnputStreamReader
OutputStreamWriter
InputStreamReader和OutputStreamWriter用于字节数据到字符数据的转换
InputStreamReader需要和InputStream“套接”
QutputStreamWri.ter需要和OutputStream“套接”
转换流在构造时可以指定其编码集合,如
InputStream isr = new InputStreamReader(System.in , “IS08850_1”);
转换字符编码集
UTF-8:国际标准编码集;
GB2312:中文编码;
ISO8859-1:英语编码。
try{
outputstreamwriter osw = new outputstreamwriter(new
Fi7leoutputstream("d : /test/char.txt"));
osw.write("微软,快来救我! ");
system.out.print1n(osw. getEncoding();osw.close();
// true不覆盖掉
// iso8859_1指定编码格式西欧语言latin-1
osw = new outputstreamwriter(new Fileoutputstream("d:/test/char.txt " ,true),
"IS08859_1");
system.out.print1n(osw. getEncoding();
osw.write("微软,快来救我! ");
osw.close();
}catch(IOException ex){
ex.printstackTrace();
}
缓冲流
BufferedReader
在BufferedReader这个类中,提供了一个方法: readLine(): 一次可以读取一行数据,并保存在String对 象中。
在BufferedWriter中,增强了write方法,使write可以直接写字符串。
5.2.3数据流
套接流可以套在节点流上面,也可以套在处理流上面。数据流是套接流的一种,可以读取相应的类型数据
readByte() ->读一字节
readLong()->读一字节,并自动提升long类型
readUTF() ->读一个字节,以UTF的编码格式返回。
string str ="你好,重托! ";
byte[] bs = str. getBytes();
DataInputstream dis = new DataInputstream(new ByteArrayInputstream(bs));
BufferedInputstream bis = new BufferedInputstream(dis);
byte b = 0 ;
for(byte by : bs) {
b = dis.readByte(;
system.out.print((char)b);
}
dis.c1ose();
显示乱码:原因是数据流,套接的是字节数组的节点流。
ByteArrayOutputStream:本身包含一个字节数组,在创建输出流的时候,默认连接的就是这个字节数组。我们的write操作,都会将数据保存到这个字节数组当中。|
打印流
在System类中有一个输出流对象,输入流对象,错误流对象。其中输出流对象和错误流对象的类型都是PrintStream,这个PrintStream是打印流。
这些流对象的初始化是在registerNatives()中执行的。
private static native void registerNatives();
static { registerNatives(); }
native关键字,隐藏当前方法的实现细节,实现细节是调用的其他开发语言开发的软件包中。
Object流
在java中,使用Obj流实现对象对序列化与反序列化。
序列化:数据()从内存—>硬盘的过程。
反序列化:数据(对象)从硬盘—>内存的过程。
如果想实现序列化与反序列化 ,有一些要求。要求数据是以对象进行包装,这个对象必须实现Serializable。
装饰器设计模式?
本身Serializable接口中什么都没有,只是一个Interface。别的类通过实现这个接口,再联合另一个关键字instanceof 实现确定某个对象是否属于某个范畴的功能。