Java27字节/字符流:IO流(内存为中心)
Posted 码农编程录
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java27字节/字符流:IO流(内存为中心)相关的知识,希望对你有一定的参考价值。
文章目录
1.FileOutputStream两个构造:OIWR
8个电子元件组在一起表示字符a即一个byte,一般bit不会用就像一分钱一样不用,所以一般最小单位字节
。
jdk8前接口里方法都是抽象
方法。jdk8后加入静态和默认方法,除了函数式编程很少见到接口里静态和默认方法。抽象类不能实例化,没法创建对象,没法调它的普通方法
。所以在四个抽象类下面各学4个子类File…(因为java里数据用File类来表示)。
package com.itheima01.outputstream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/*
* FileOutStream的构造方法。这里的stream和lambda里stream没有一点关系
* 1. FileOutputStream(File file)
2. FileOutputStream(String name) throws FileNotFoundException
fos创建的时候需要跟一个路径进行绑定(将会写出数据)
构造的特点: 1. 如果路径文件不存在,则新建
2. 如果路径文件存在,则覆盖(无论路径文件是否存在,创建一个新的覆盖)
异常处理 -> 待会详细的写一遍
3. 如果路径的父目录不存在, 就会抛出FileNotFoundException
结论: 1. 一般使用FileOutputStream(String name)构造,快捷
2. 但是如果不能保证父目录是否存在,就用FileOutputStream(File file)
*/
public class Demo01 {
public static void main(String[] args) throws FileNotFoundException {
// FileOutputStream fos = new FileOutputStream("dir/a.txt");
//如下解决上面父路径不存在不能创建缺点
File file = new File("aaa/dir/a.txt"); //1. 判断file的父目录aaa/dir/是否存在
File parentFile = file.getParentFile();
if(!parentFile.exists()){
parentFile.mkdirs(); //2. 如果不存在,则创建多级目录
}
FileOutputStream fos = new FileOutputStream(file); //必须有这一行才创建出文件
System.out.println("创建成功");
}
}
//两种创建文件方式
//1.
File file = new File("d:/a.txt"); //只创建File类路径实例
file.createNewFile(); //必须要执行才创建
//2.
File file = new File("d:/a.txt");
FileOutputStream outputStream =new FileOutputStream(file); //这行可以创建出一个空文件了
outputStream.write(123);
outputStream.close();
outputStream.flush();//必须刷新文件才有内容
2.OutputStream的基本方法:int4,char2,追加和换行
package com.itheima01.outputstream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 1. OutputStream 抽象类,是表示输出字节流的所有类的超类
1. close() :关闭此输出流并释放与此流相关联的任何系统资源。
2. write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。
3. write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
4. write(int b) :将指定的字节输出流
*/
public class Demo02 {
public static void main(String[] args) throws IOException { //FileNotFoundException父类是IOException
FileOutputStream fos = new FileOutputStream("a.txt");
fos.write(97); // ASCII码表,a.txt内容里多了一个a。 //1. write(int b) : 一次写一个字节
fos.write('a'); //aa
byte[] array = {65,66,67,68,69}; //2. write(byte[] b) : 一次写一个字节数组
fos.write(array); //aaABCDE
fos.write(array,1,3); //aaABCDEBCD (最后多了BCD 3个字母) (1是array从66即B开始) //3.write(byte[] b, int offset, int len): 一次写一个字节数组的一部分 //offset(偏移量):从第几个开始
fos.close(); //close()本身有个io编译异常,流用完要关掉, 释放资源,流横跨内存和硬盘开销大,所以要关
}
}
Java:因为是跨平台的,无论在哪里,int都是四个字节。因为字符是用Unicode编码的,所以char是两个字节(C/C++中char始终都是一个字节)。
package com.itheima01.outputstream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
/*
FileOutputStream(String name, boolean append) : 数据追加
1. append = true : 往原文件追加内容,不会覆盖了
换行
1. windows : \\r\\n
2. unix : \\n
System.lineSeparator() : 根据不同的系统,返回不同的换行符 (跨平台)
*/
public class Demo03 {
public static void main(String[] args) throws IOException {
// FileOutputStream fos = new FileOutputStream("a.txt"); //会覆盖原内容
FileOutputStream fos = new FileOutputStream("a.txt",true); //不覆盖原内容
// fos.write(48); //尾部追加一个0
//1111111111111111111111111111111111111111111111111111111111111111111111111111
// fos.write("\\r\\n".getBytes()); //win
String line = System.lineSeparator();
fos.write(line.getBytes());
//111111111111111111111111111111111111111111111111111111111111111111111111111
String str = "hello,byebye!";
byte[] bytes = str.getBytes();
fos.write(bytes);
fos.close();
}
}
3.FileInputStream两个构造:一次读一个字节或字节数组
package com.itheima02.intputstream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/*
FileInputStream 构造 (读:硬盘流到内存),以内存为中心,如果文件不存在, 则抛出FileNotFoundException
1. FileInputStream(File file)
2. FileInputStream(String name)
*/
public class Demo01 {
public static void main(String[] args) throws FileNotFoundException {
// FileInputStream fis = new FileInputStream("a.txt"); //a.txt在FileOutputStream已创建
FileInputStream fis = new FileInputStream(new File("a.txt"));//不会创建文件,和上行一样
System.out.println(fis); //java.io.FileInputStream@6d6f6e28
}
}
package com.itheima02.intputstream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* InputStream 抽象类是表示字节输入流的所有类的超类
1. void close() :关闭此输入流并释放与此流相关联的任何系统资源。
2. int read() : 从输入流读取数据的下一个字节。
3. int read(byte[] b) : 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
*/
public class Demo02 {
public static void main(String[] args) throws IOException {
// method01();
FileInputStream fis = new FileInputStream("a.txt");
/* int content = -1 ; //=0也可以,都会被覆盖掉
while(content != -1){
content = fis.read();
System.out.println(content);
}*/
int content = -1;
while((content = fis.read()) != -1){ //这样和上面区别是,这不会多打印-1
System.out.println(content);
}
fis.close();
}
//11111111111111111111111111111111111111111111111111111111111111111111111111111111
private static void method01() throws IOException {
FileInputStream fis = new FileInputStream("a.txt");//已存在a.txt且里面有abc
int content = 0 ;
content = fis.read();//向后移动一位,并返回当前元素(迭代器) //int read() : 一次读一个字节
System.out.println(content);//97
content = fis.read();
System.out.println(content);//98
content = fis.read();
System.out.println(content);//99
content = fis.read(); // 如果后面已经到文件的末尾,不会再移动直接返回-1
System.out.println(content);//-1 //-1不在ascii表上,-1表示没有意义
fis.close();
}
}
package com.itheima02.intputstream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
/*
* int read(byte[] b) : 一次读一个字节数组
* 1. 参数 byte[] : 用来存放字节流读取到的数据
* 2. 返回值 int : 本次读取到的字节个数
* 返回值 = 数组长度 < 文件剩余的字节数量 ? 数组长度 : 文件剩余字节数量
* 迭代器
*/
public class Demo03 {
public static void main(String[] args) throws IOException {
// method01();
FileInputStream fis = new FileInputStream("a.txt");
byte[] buffer = new byte[3];// {0,0,0}
int length = 0;
/*while(length != -1){ //A
length = fis.read(buffer);
System.out.println(length + "->" + Arrays.toString(buffer));
}*/
while((length = fis.read(buffer)) != -1){
// System.out.println(length + "->" + Arrays.toString(buffer)); //B
String str = new String(buffer, 0, length); //C
System.out.println(str);
}
fis.close();
}
//111111111111111111111111111111111111111111111111111111111111111111111111111111111111
private static void method01() throws IOException {
FileInputStream fis = new FileInputStream("a.txt"); //a.txt里内容:abcdefg
byte[] buffer = new byte[3];//{0,0,0} //System.out.println(Arrays.toString(buffer)); //[0,0,0] //Arrays工具类
int length = -1;
length = fis.read(buffer); //框子只有3个位置
System.out.println(length + "->" + Arrays.toString(buffer)); //3->[97,98,99]
length = fis.read(buffer);
System.out.println(length + "->" + Arrays.toString(buffer));// length=3,def
length = fis.read(buffer);
System.out.println(length + "->" + Arrays.toString(buffer));//length=1,gef,ef还是上面的没覆盖
length = fis.read(buffer);
System.out.println(length + "->" + Arrays.toString(buffer));// length=-1,gef
fis.close();
}
}
4.文件复制(重要):fis.read,fos.write
package com.itheima03.copy;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 文件复制: 先读后写
* 1. 先创建一个输入流 指向 原文件
* 2. 再创建一个输出流 指向 副本
* 一个读,另一个写
* A. 一次读写一个字节
* B. 一次读写一个字节数组
*/
public class CopyDemo01 {
public static void main(String[] args) throws IOException {
// method01(); // 1148ms
method02();//59ms
//1111111111111111111111111111111111111111111111111111111111111111111111111
/* long startTime = System.currentTimeMillis();
for (int i = 0; i < 1024*4000; i++) { //循环不耗时,打印耗时,打印就是IO流
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime); // 2ms*/
}
//111111111111111111111111111111111111111111111111111111111一次读写一个字节数组 (重要)
private static void method02() throws IOException {
long startTime = System.currentTimeMillis();
FileInputStream fis = new FileInputStream("柳岩.jpg");
FileOutputStream fos = new FileOutputStream("ly2.jpg");
byte[] buffer = new byte[1024]; //1kb
int length = -1;
while((length = fis.read(buffer)) != -1){
fos.write(buffer,0,length);
}
fos.close();
fis.close();
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
//1111111111111111111111111111111111111111111111111111111111111一次读写一个字节
private static void method01() throws IOException {
long startTime = System.currentTimeMillis();
FileInputStream fis = new FileInputStream("柳岩.jpg"); //已存在
FileOutputStream fos = new FileOutputStream("ly.jpg");
int content = -1;
while((content = fis.read()) != -1){
fos.write(content);
}
fos.close();
fis.close(); //先打开的后关闭
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
}
5.编码表与字符流:编码解码和乱码
将如上"啊"改为"瞭",并放开gb2312和gbk,如下打印3F就是ascii码中63即?即解码失败。
如下:1.用文件浏览器(编码B)或IDE(编码B)打开一个文件(编码A)会乱码。
2.程序读取编码A的数据并且将转成字符串,但是使用的编码B转,也会乱码。
3.网页浏览器,服务端请求的数据的编码是A,但是浏览器展示用的编码B,也会乱码。
1.
如下在浏览器地址栏ctrl+c再ctrl+v。
2.
如下按gb2312拿字节码,用utf-8生成文字,强制编码出错。
3.
如下1.txt中10个"啊",utf8中每个汉字对应3字节,所以30个字节。
byte数组长度刚好把一个字切开了,如果是英文文件就无所谓,因为一个英文ascii码就是一个字节。
4.
如下是爬网页数据。
如下改进,未出现乱码。
package com.itheima04.chard;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
* 字符流 = 字节流 + 编码表【为什么有了编码表后有了动态判断能力?】
* FileReader = FileInputStream + 编码表 (字典:碰到中文1次读3个字节)
*
* 编码表: 计算机底层0和1 -> 字符(像素..)。字符集charset(字符编码表): 二进制和字符 相互转换的一种规则。
* 1. ASCII码表 : 128个数字(0~127,2的7次方=128)。0 000 0000 ~ 0 111 1111 (一个字节后7位占了)
* 2. ISO-8859-1 : 欧码(拉丁码) 256个。0000 0000 ~ 1111 1111 (一个字节)。Tomcat软件 默认编码表
*
* 3. GBK (国标扩)是GB2312的扩展:
* 兼容ASCII码表即承认英文字母占一个字节, 一个汉字占两个字节(2的16次方,0 ~ 65535)。
*
* 4. 国际 Unicode (universal code):utf-8 : 兼容ASCII表, 其次 归纳其他主流文字
* 1. 一个英文一个字节
* 2. 一个中文三个字节(如果有1000个字用GBK只有2kb的大小,用utf-8占3kb)
*
* 总结: ASCII码表 : 0,A,a
* GBK: windows中文简体默认(GBK)
* UTF-8: 开发常用!!!(ideal里默认UTF-8)
*/
public class CharDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt"); //字节流:一个英文一个字节 , 一个中文3个字节。如“中国人”显示9个数字
// FileReader fis = new FileReader("a.txt"); //字符流:一次读一个字符(英文只读1字节, 中文只读3个字节,动态判断)。如“中国人”显示3个数字
int content = -1;
while((content = fis.read()) != -1){
System.out.println(content); //打印换行
}
fis.close();
}
}
package com.itheima04.chard;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//字符流: 赋值文本文件,不能复制图片。
public class CharDemo02 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("a.txt"); //已存在
FileWriter fw = new FileWriter("b.txt");
int length = -1;
char[] buffer = new char[1024];
while((length = fr.read(buffer)) != -1){
fw.write(buffer,0,length);
}
fw.close();
fr.close(); //结果:b.txt和a.txt一样,原来没有b.txt这个文件
}
}以上是关于Java27字节/字符流:IO流(内存为中心)的主要内容,如果未能解决你的问题,请参考以下文章