个人网站设计成品免费推广产品的平台
在字节流中,文件中的中文显示的是乱码。
在计算机存储体系中,以字节为最小存储单位,一个英文占一字节。
字符集类型
- ASCII字符集,又叫编码表,编码表中有128个数据,其中大小写字母、符号、数字等。
- GB2312字符集:1981年5月1日实施的简体中文汉字编码国家标准,收录了7445个图形字符,其中包括6763个简体汉字。
- BIG5字符集:台湾地区繁体中文标准字符集,共收录13053个中文字,1984年实施。
- GBK字符集:2000.3.17发布,收录21003个汉字。包含国家标准GB13000-1中的全部中日韩汉字,和BIG编码中的所有汉字。(简体中文Windows系统默认使用GBK,系统显示ANSI)
- Unicode字符集:国家标准字符集,它将世界各种语言的每一个字符定义一个唯一的编码,以满足跨语言、跨平台文本信息转换。
GBK 存储规则:
GBK存储英文,完全兼容ASCII码。
存储中文
扩展:解码都是直接转为十进制
Unicode万国码存储规则
UTF存储英文:有三个规则:UTF-8编码规则、UTF-16规则、UTF-32规则
UTF存储中文:
乱码出现原因:
- 读取数据时未读完整个汉字,当利用字节流读取文字时,一个汉字会被分为3个字节读取
- 编码和解码时的方式不统一,eg
防止乱码出现办法:
- 不要用字节流读取文本文件
- 编码解码使用同一个码表,同一个编码方式
编码与解码方法
编码:将我们要存储的数据根据一定的规则编译为计算机能够存储的字节数据
public byte[ ] getBytes() | 使用默认方式进行编码 |
public byte[ ] getBytes(String charsetName) | 使用指定方式进行编码 |
解码:
String(byte[ ] bytes) | 使用默认方式进行解码 |
String(byte[ ] bytes,String charsetName) | 使用指定方式进行编码 |
字符流
字符流的底层是字节流:
字符流=字节流+字符集
特点:
- 输入流:一次读一个字节,遇到中文时,一次读多个字节(与字符集有关)
- 输出流:底层会把数据按照指定的编码方式进行编码,变成字节在写到文件中
适合纯文本文件的读写操作。
字符流:Reader(字符输入流) Writer(字符输出流)
FileReader
使用步骤:
1.创建字符输入流对象
public FileReader(File fille) | 创建字符输入流关联本地文件 |
public FileReader(String pathname) | 创建字符输入流关联本地文件 |
File对象表示的文件路径以及字符串表示的文件路径,如果文件不存在就会报错
2.读取数据
public int read() | 读取数据,读到末尾返回-1 |
public int read(char[ ] buffer) | 读取多个数据,读到末尾返回-1 |
- 空参读取:按字节进行读取,遇到中文,一次读多个字节,读取后解码,返回一个整数(read返回的十进制,是字符集上的数字)
- 读到文件末尾,read方法返回-1
3.释放资源
public int close() //释放资源/关流
空参read()方法的使用:
有参read()方法的使用:
FileWriter
FileWrite构造方法:
public FileWriter(File file ) | 创建字符输出流关联本地文件 |
public FileWriter(String pathname) | 创建字符输出流关联本地文件 |
public FileWriter(File file,boolean append) | 创建字符输出流关联本地文件,续写 |
public FileWriter(String pathname,boolean append) | 创建字符输出流关联本地文件,续写 |
FileWrite成员方法:
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) | 写出字符数组的一部分 |
使用流程:
1.创建字符输出流对象
- 参数是字符串表示的路径或者File对象
- 如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
- 如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关
2.写数据
- 如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符
3.释放资源
- 每次使用完流都要释放资源
使用步骤代码实现:
StringBuilder类
对字符串拼接原理:(String类在Java流程控制中有说明)
利用StringBuilder可变字符串序列,解决浪费内容问题。
String和StringBuilder的区别:
- String:内容不可变
- StringBuilder:内容可变
StringBuilder主要构造方法:
StringBuilder() | 无参构造,创建一个空白可变字符串对象 |
StringBuilder(String str) | 指定字符串内容的构造方法 |
代码演示:
StringBuilder方法
public StringBuilder append(任意类型) | 添加数据,并返回对象本身 |
public StringBuilder reverse() | 返回相关的字符序列 |
代码演示:
所以在添加数据时,可以不创建另一个对象存数据。
反转,顾名思义,将sb中的内容从后往前输出。
StringBuilder和String相互转换
StringBuilder转换为String
public String toString():通过toString()就可以实现
String转换为StringBuilder
public StringBuilder(String s)
代码演示:
拼接字符串
定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,在控制台输出结果。eg:int[ ] arr={1,2,3}l,执行方法后输出结果:[1,2,3]
综合练习
拷贝
字节流:任意类型的文件
字符流:读取纯文本文件中的数据,往纯文本文件中写出数据
拷贝一个文件夹加,考虑子文件夹
//拷贝文件夹下所有内容
public class Test1 {public static void main(String[] args) throws IOException {//创建对象,数据源File src=new File("D:\\test");//目的地File dest=new File("D:\\dest");//调用方法开始拷贝copydir(src,dest);}//创建拷贝方法private static void copydir(File src, File dest) throws IOException {//dest不存在,创建dest文件夹dest.mkdirs();//1.进入数据源File[] files = src.listFiles();//记录文件夹中的文件及路//2.遍历数组for (File file:files){//增强for循环,将数组files中的每一项赋值给fileif (file.isFile()){//3.判断文件,拷贝 文件开始,文件结束,dest是文件夹FileInputStream fis=new FileInputStream(file);//要拷贝的文件FileOutputStream fos=new FileOutputStream(new File(dest,file.getName()));//文件的目的地byte[] bytes=new byte[1024];//一个读取1024个字节int len;while ((len=fis.read(bytes))!=-1){fos.write(bytes,0,len);}fos.close();//4.关闭资源,先开的后关fis.close();}else{//4.判断文件夹,递归copydir(file,new File(dest,file.getName()));//要拷贝的文件夹,目的地}}}
}
文件加密
为了保证文件的安全性,需要对原始文件进行加密存储,再使用的时候在对其进行解密处理。
加密原理:对原始文件中的每一个字节数据进行更改,然后将更改以后的数据存储到新的文件中。
解密原理:读取加密之后的文件,按照加密的规则反向操作,变成原始文件。
//文件加密
public class Test2 {public static void main(String[] args) throws IOException {//异或:^ 相同为0 不同为1//eg:100^10=110 110^10=100FileInputStream fis=new FileInputStream("C_S\\b.png");FileOutputStream fos=new FileOutputStream("C_S\\b1.png");//加密处理int b;while ((b=fis.read())!=-1){fos.write(b^2);}fos.close();fis.close();}
}
修改文件中的数据
文本文件中有以下的数据:2-1-9-4-7-8
将文件中的数据进行排序,变成以下的数据:1-2-4-7-8-9
代码实现:
//更改文件内容
public class Test3 {public static void main(String[] args) throws IOException {//1.读取数据FileReader fr=new FileReader("C_S\\a.txt");//数据读入程序StringBuilder sb=new StringBuilder();//StringBuilder功能:拼接读取到的数据int ch;while ((ch=fr.read())!=-1){sb.append((char)ch);//将读取到的数据拼接到sb中}fr.close();System.out.println(sb);//2.排序String str=sb.toString();//将sb内容变成字符串形式String[] arrstr=str.split("-");//根据-进行切割,得到字符串类型的219478ArrayList<Integer> list=new ArrayList<>();for(String s:arrstr){//遍历字符串数组int i = Integer.parseInt(s);//一次能够将一个字符串类型整数变成int性整数list.add(i);//将转换后的数字保存在list集合中}System.out.println(list);//测试集合是否有数字Collections.sort(list);//集合中的排序方法,默认从小到大System.out.println(list.size());//3.写出FileWriter fw=new FileWriter("C_S\\a.txt");for (int i = 0; i < list.size(); i++) {//遍历集合listif (i==list.size()-1){//如果说集合中最后一位,则直接输出fw.write(list.get(i)+"");//不能直接写i,write会将其转换对应ASII码// ,+“”,将其转换为字符串输出}else {//不是最后一位,加-输出fw.write(list.get(i)+"-");}}fw.close();}
}