网站如何备案流程,站网站推广,单页面网站 wordpress,wp_query wordpressIO流
概述 生活中#xff0c;你肯定经历过这样的场景。当你编辑一个文本文件#xff0c;忘记了ctrls #xff0c;可能文件就白白编辑了。当你电脑上插入一个U盘#xff0c;可以把一个视频#xff0c;拷贝到你的电脑硬盘里。那么数据都是在哪些设备上的呢#xff1f;键盘…IO流
概述 生活中你肯定经历过这样的场景。当你编辑一个文本文件忘记了ctrls 可能文件就白白编辑了。当你电脑上插入一个U盘可以把一个视频拷贝到你的电脑硬盘里。那么数据都是在哪些设备上的呢键盘、内存、硬盘、外接设备等等。 我们把这种数据的传输可以看做是一种数据的流动按照流动的方向以内存为基准分为输入input 和输出output 即流向内存是输入流流出内存的输出流。 Java中I/O操作主要是指使用java.io包下的内容进行输入、输出操作。输入也叫做读取数据输出也叫做作写出数据 IO的分类 根据数据的流向分为输入流和输出流。 输入流 把数据从其他设备上读取到内存中的流。 程序 - 文件 输出流 把数据从内存 中写出到其他设备上的流。 文件 - 程序 格局数据的类型分为字节流和字符流。 字节流 以字节为单位读写数据的流。 字符流 以字符为单位读写数据的流。 注意 纯文本文件能用Windows自带的记事本打开能读懂的文件 如md和txt IO流的体系 字节流基本用法 FileOutputStream类 当你创建一个流对象时必须传入一个文件路径。该路径下如果没有这个文件会创建该文件。如果有这个文件会清空这个文件的数据。 构造方法 public FileOutputStream(File file)创建文件输出流以写入由指定的 File对象表示的文件。 public FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。 代码示例
public class FileOutputStreamConstructor throws IOException {public static void main(String[] args) {// 使用File对象创建流对象File file new File(a.txt);FileOutputStream fos new FileOutputStream(file);// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(b.txt);}
} 写出数据的三种方法 写出字节数据 write(int b) 方法 代码演示 public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(fos.txt); // 写出数据fos.write(97); // 写出第1个字节fos.write(98); // 写出第2个字节fos.write(99); // 写出第3个字节// 关闭资源fos.close();}
}
输出结果
abc 1.创建字节输出流对象细节 细节1参数是字符串表示的路径或者是file对象都是可以的 细节2如果文件不存在会创建一个新的文件但是要保障父级路径是存在的 细节3如果文件已经存在则会清空文件 2.写数据 细节write方法的参数是整数但是实际上写到本地文件中的是整数在ASCII上对应的字符 3.释放资源 每次使用完流之后都要释放资源不然文件一直处于占用状态 写出字节数组write(byte[] b)
public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(fos.txt); // 字符串转换为字节数组byte[] b 黑马程序员.getBytes();// 写出字节数组数据fos.write(b);// 关闭资源fos.close();}
}
输出结果
黑马程序员 写出指定长度字节数组write(byte[] b, int off, int len)
public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(fos.txt); // 字符串转换为字节数组byte[] b abcde.getBytes();// 写出从索引2开始2个字节。索引2是c两个字节也就是cd。fos.write(b,2,2);// 关闭资源fos.close();}
}
输出结果
cd 数据追加续写 经过以上的演示每次程序运行创建输出流对象都会清空目标文件中的数据。如何保留目标文件中数据还能继续添加新数据呢 public FileOutputStream(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。 public FileOutputStream(String name, boolean append) 创建文件输出流以指定的名称写入文件。 这两个构造方法参数中都需要传入一个boolean类型的值true 表示追加数据false 表示清空原有数据。这样创建的输出流对象就可以指定是否追加续写了 代码演示 public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(fos.txttrue); // 字符串转换为字节数组byte[] b abcde.getBytes();// 写出从索引2开始2个字节。索引2是c两个字节也就是cd。fos.write(b);// 关闭资源fos.close();}
}
文件操作前cd
文件操作后cdabcde 写出换行 换行符 Windows\r\n Linux系统\n Mac: \r 细节 在windows系统中Java对回车换行进行了优化 虽然完整的是\r\n但是我们写其中一个\r或者\n, java也可以实现换行因为Java在底层会自动补全 建议 不要省略还是写全 代码演示 public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(fos.txt); // 定义字节数组byte[] words {97,98,99,100,101};// 遍历数组for (int i 0; i words.length; i) {// 写出一个字节fos.write(words[i]);// 写出一个换行, 换行符号转成数组写出fos.write(\r\n.getBytes());}// 关闭资源fos.close();}
}输出结果
a
b
c
d
e FileInputStream类 java.io.FileInputStream 类是文件输入流从文件中读取字节。 构造方法 FileInputStream(File file) 通过打开与实际文件的连接来创建一个 FileInputStream 该文件由文件系统中的 File对象 file命名。 FileInputStream(String name) 通过打开与实际文件的连接来创建一个 FileInputStream 该文件由文件系统中的路径名 name命名。 当你创建一个流对象时必须传入一个文件路径。该路径下如果没有该文件,会抛出FileNotFoundException。 代码演示 public class FileInputStreamConstructor throws IOException{public static void main(String[] args) {// 使用File对象创建流对象File file new File(a.txt);FileInputStream fos new FileInputStream(file);// 使用文件名称创建流对象FileInputStream fos new FileInputStream(b.txt);}
} 读取字节数据 字节输入流的细节 1.创建字节输入流对象 细节1如果文件不存在就直接报错 Java为什么会这么设计呢 输出流不存在创建 把数据写到文件当中 输入流不存在则是报错呢 读取的时候数据在文件当中 所以Java就没有这种无意义的逻辑文件不存在直接报错 程序中最重要的是数据 2.写数据 细节1一次读一个字节读出来的是数据在ASCII上对应的数字 细节2读到文件末尾了read方法返回-1 3.释放资源 细节每次使用完流之后都要释放资源 read方法 读一次数据就移动一次指针指向下一个元素 代码演示 public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名称创建流对象FileInputStream fis new FileInputStream(read.txt);// 读取数据返回一个字节int read fis.read();System.out.println((char) read);read fis.read();System.out.println((char) read);read fis.read();System.out.println((char) read);read fis.read();System.out.println((char) read);read fis.read();System.out.println((char) read);// 读取到末尾,返回-1read fis.read();System.out.println( read);// 关闭资源fis.close();}
}
输出结果
a
b
c
d
e
-1 循环改进读取方式代码使用演示 public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名称创建流对象FileInputStream fis new FileInputStream(read.txt);// 定义变量保存数据int b // 循环读取while ((b fis.read())!-1) {System.out.println((char)b);}// 关闭资源fis.close();}
}
输出结果
a
b
c
d
e 小贴士 1. 虽然读取了一个字节但是会自动提升为int类型。 2. 流操作完毕后必须释放系统资源调用close方法千万记得。 使用字节数组读取read(byte[] b) 每次读取b的长度个字节到数组中返回读取到的有效字节个数读取到末尾时返回-1 代码演示 public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名称创建流对象.FileInputStream fis new FileInputStream(read.txt); // 文件中为abcde// 定义变量作为有效个数int len // 定义字节数组作为装字节数据的容器 byte[] b new byte[2];// 循环读取while (( len fis.read(b))!-1) {// 每次读取后,把数组变成字符串打印System.out.println(new String(b));}// 关闭资源fis.close();}
}输出结果
ab
cd
ed 错误数据d是由于最后一次读取时只读取一个字节e数组中上次读取的数据没有被完全替换所以要通过len 获取有效的字节代码使用演示 public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名称创建流对象.FileInputStream fis new FileInputStream(read.txt); // 文件中为abcde// 定义变量作为有效个数int len // 定义字节数组作为装字节数据的容器 byte[] b new byte[2];// 循环读取while (( len fis.read(b))!-1) {// 每次读取后,把数组的有效字节部分变成字符串打印System.out.println(new String(b0len));// len 每次读取的有效字节个数}// 关闭资源fis.close();}
}输出结果
ab
cd
e 小贴士 使用数组读取每次读取多个字节减少了系统间的IO操作次数从而提高了读写的效率建议开发中使用。 练习小文件拷贝 FileOutputStream fos new FileOutputStream(a.txt);FileInputStream fis new FileInputStream(b.txt);byte[] bytes new byte[1024];int len;long start System.currentTimeMillis();while((len fis.read(bytes)) ! -1) {fos.write(bytes, 0, len);}fos.close();fis.close();//统计拷贝时间long end System.currentTimeMillis();System.out.println(拷贝时间 (end - start) ms); 小贴士 流的关闭原则先开后关后开先关。 字符集
字符集GBK 字符集Unicode 为什么会有乱码 原因1 读取数据时未读完整个汉字 原因2 编码和解码时的方式不一样 如何不产生乱码 1、不要用字节流读取文本文件 2、编码解码时使用同一个码表同一个编码方式 扩展 疑问字节流读取中文会乱码但是为什么拷贝不会乱码呢 因为拷贝时数据源没有丢失用记事本采用对应的解码方式打开不会出现乱码 Java中的编码和解码 字符流 字符流的底层其实就是字节流 字符流字节流字符集 特点 输入流一次读一个字节。遇到中文时一次读多个字节 输出流底层会把数据按照指定的编码方式进行编码变成字节再写到文件中 使用场景 对于出纯文本文件进行读写操作 FileReader 无参read代码演示 FileReader fileReader new FileReader(a.txt);//读取数据read//字符流的底层也是字节流默认也是一个字节一个字节的读取的//如果遇到中文就会一次读取多个GBK一次读两个字节UTF-8一次读3个字节//read细节//在读取之后方法的底层还会进行解码并转成十进制// 最终把这个十进制作为返回值// 这个十进制的数据也表示在字符集上的数字// 英文文件里面二进制数据 0110 0001// read方法进行读取转成十进制97// 中文文件里面二进制数据 11100110 10110001 10001001// read方法进行读取转成十进制27721// 我想看到中文汉字就是把这些十进制数据再进行强转就行了int ch 0;while ((ch fileReader.read()) ! -1) {System.out.print((char)ch);}fileReader.close();
有参read代码演示 FileReader fileReader new FileReader(a.txt);int len;char[] chars new char[1024];while((lenfileReader.read(chars))!-1){System.out.println(new String(chars,0,len));}fileReader.close();注意 无参的ch表示拿到的字符的十进制 有参的len表示读取到字符的个数 FileWriter 基本写出数据 write(int b) 方法每次可以写出一个字符数据代码使用演示 FileWriter fw new FileWriter(fw.txt); // 写出数据fw.write(97); // 写出第1个字符fw.write(b); // 写出第2个字符fw.write(C); // 写出第3个字符fw.write(30000); // 写出第4个字符中文编码表中30000对应一个汉字。/*【注意】关闭资源时,与FileOutputStream不同。如果不关闭,数据只是保存到缓冲区并未保存到文件。*/// fw.close();输出结果
abC田 小贴士 1. 虽然参数为int类型四个字节但是只会保留一个字符的信息写出。 2. 未调用close方法数据只是保存到了缓冲区并未写出到文件中。 关闭和刷新 因为内置缓冲区的原因如果不关闭输出流无法写出字符到文件中。但是关闭的流对象是无法继续写出数据的。如果我们既想写出数据又想继续使用流就需要flush 方法了。 * flush 刷新缓冲区流对象可以继续使用。 * close :先刷新缓冲区然后通知系统释放资源。流对象不可以再被使用了。 代码演示 public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw new FileWriter(fw.txt);// 写出数据通过flushfw.write(刷); // 写出第1个字符fw.flush();fw.write(新); // 继续写出第2个字符写出成功fw.flush();// 写出数据通过closefw.write(关); // 写出第1个字符fw.close();fw.write(闭); // 继续写出第2个字符,【报错】java.io.IOException: Stream closedfw.close();}
} 小贴士即便是flush方法写出了数据操作的最后还是要调用close方法释放系统资源。 写出其他数据 1. **写出字符数组** write(char[] cbuf) 和 write(char[] cbuf, int off, int len) 每次可以写出字符数组中的数据用法类似FileOutputStream代码使用演示 public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw new FileWriter(fw.txt); // 字符串转换为字节数组char[] chars 黑马程序员.toCharArray();// 写出字符数组fw.write(chars); // 黑马程序员// 写出从索引2开始2个字节。索引2是程两个字节也就是程序。fw.write(b,2,2); // 程序// 关闭资源fos.close();}
} 2. **写出字符串**write(String str) 和 write(String str, int off, int len) 每次可以写出字符串中的数据更为方便代码使用演示 public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw new FileWriter(fw.txt); // 字符串String msg 黑马程序员;// 写出字符数组fw.write(msg); //黑马程序员// 写出从索引2开始2个字节。索引2是程两个字节也就是程序。fw.write(msg,2,2); // 程序// 关闭资源fos.close();}
} 续写和换行 public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象可以续写数据FileWriter fw new FileWriter(fw.txttrue); // 写出字符串fw.write(黑马);// 写出换行fw.write(\r\n);// 写出字符串fw.write(程序员);// 关闭资源fw.close();}
}
输出结果:
黑马
程序员 小贴士字符流只能操作文本文件不能操作图片视频等非文本文件。 当我们单纯读或者写文本文件时 使用字符流 其他情况使用字节流 字符流综合练习 练习1拷贝 需求拷贝一个文件夹考虑子文件夹 public class Test01 {public static void main(String[] args) throws IOException {//拷贝一个文件夹考虑子文件夹//1.创建对象表示数据源File src new File(D:\\aaa\\src);//2.创建对象表示目的地File dest new File(D:\\aaa\\dest);//3.调用方法开始拷贝copydir(src,dest);}/** 作用拷贝文件夹* 参数一数据源* 参数二目的地** */private static void copydir(File src, File dest) throws IOException {dest.mkdirs();//递归//1.进入数据源File[] files src.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文件加密 需求为了保证文件的安全性就需要对原始文件进行加密存储再使用的时候再对其进行解密处理。 加密原理对原始文件中的每一个字节数据进行更改然后将更改以后的数据存储到新的文件夹中 解密原理读取加密之后的文件按照加密的规则反向操作变成原始文件 public class Test02 {public static void main(String[] args) throws IOException {/*为了保证文件的安全性就需要对原始文件进行加密存储再使用的时候再对其进行解密处理。加密原理对原始文件中的每一个字节数据进行更改然后将更改以后的数据存储到新的文件中。解密原理读取加密之后的文件按照加密的规则反向操作变成原始文件。^ : 异或两边相同false两边不同true0false1true100:110010010: 10101100100^ 0001010__________1101110^ 0001010__________1100100*/}public static void encryptionAndReduction(File src, File dest) throws IOException {FileInputStream fis new FileInputStream(src);FileOutputStream fos new FileOutputStream(dest);int b;while ((b fis.read()) ! -1) {fos.write(b ^ 2);}//4.释放资源fos.close();fis.close();}}练习3修改文件中的数据 文本文件中有以下的数据 2-1-9-4-7-8 将文件中的数据进行排序变成以下的数据 1-2-4-7-8-9 public class test {public static void main(String[] args) throws IOException {//读取数据FileReader fileReader new FileReader(a.txt);StringBuilder stringBuildernew StringBuilder();int ch;while ((chfileReader.read())!-1){stringBuilder.append((char)ch);}fileReader.close();//排序String strstringBuilder.toString();String[] str1str.split(-);ArrayListInteger listnew ArrayList();for (String s : str1) {int iInteger.parseInt(s);list.add(i);}Collections.sort(list);System.out.println(list);//写出FileWriter fileWriternew FileWriter(b.txt);for (int i 0; i list.size(); i) {if(ilist.size()-1){fileWriter.write(list.get(i));}else {fileWriter.write(list.get(i)-);}}fileWriter.close();}
}简化写法 //排序Integer[] integers Arrays.stream(stringBuilder.toString().split(-)).map(Integer::parseInt).sorted().toArray(Integer[]::new);System.out.println();//写出FileWriter fileWriter new FileWriter(b.txt);String s Arrays.toString(integers).replace(, ,-);String result s.substring(1, s.length() - 1);System.out.println(result);fileWriter.write(result);fileWriter.close(); 细节1 文件中的数据不要换行 细节2bom头