编码和解码的方法
编码是将字符(如Unicode字符)转换成字节的过程,而解码则是将字节转换回字符的过程。
String构造函数可以接受字节数组和字符数组。使用字节数组时,可以指定字符编码
//编码
//默认字符集UTF-8
String s = "黑马程序员";
byte[] bytes = s.getBytes();
System.out.println(Arrays.toString(bytes));
//指定字符集
byte[] bytes1 = s.getBytes("GBK");
System.out.println(Arrays.toString(bytes1));
//解码
byte[] utf8Bytes = {-23, -69, -111, -23, -87, -84, -25, -88, -117, -27, -70, -113, -27, -111, -104};
byte[] gbkBytes = {-70, -38, -62, -19, -77, -52, -48, -14, -44, -79};
//用默认字符集UTF-8解码
String s1 = new String(utf8Bytes);
System.out.println(s1);
//用GBK字符集解码
String s2 = new String(gbkBytes, "GBK");
System.out.println(s2);
字符流写数据
方法名 | 说明 |
---|---|
public void write(int c) | 写入单个字符 |
public void write(char[] cbuf) | 写入字符数组 |
public void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
public void write(String str) | 写入字符串 |
public void write(String str, int off, int len) | 写入字符串的一部分。 |
//代码演示
//字符流-写出数据的构造方法
FileWriter fw1 = new FileWriter(new File("a.txt"));//方法1
FileWriter fw = new FileWriter("a.txt");//方法二
//写一个字符
fw.write(97);
//写一个字符数组
char[] chars = {97, 98, 99, 100, 101, 102};
fw.write(chars);
//写出字符数组的一部分
fw.write(chars, 0 , 3);
//写一个字符串
String s = "黑马程序员";
fw.write(s);
//写字符串的一部分
fw.write(s, 0, 3);
//释放资源
fw.close();
字符流读数据
一次只读取一个字符
字符在Java底层实际上是一个无符号的 16 位整数。
这意味着它的值范围从 0 到 65535(即 0xFFFF),用来表示 Unicode 字符集中的字符。
强制转换 (char) 实际上是将整数的 16 位二进制表示解释为一个字符的 Unicode 代码单元。
一次只读一个字符
//单次读一个数据
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("a.txt");
int b;
while ((b = fr.read()) != -1){
System.out.println((char) b);
}
}
一次读1024个字符
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("a.txt");
int length;
char[] c = new char[1024];
while ((length = fr.read(c)) != -1){
System.out.println(new String(c, 0, length));
}
}
字符缓冲流(和字节缓冲流基本上一模一样)
字符缓冲输入流
//复制
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("honglou.txt"));
char[] chars = new char[1024];
int len;
while ((len = br.read(chars)) != -1){
bw.write(chars, 0, len);
}
br.close();
bw.close();
}
//字符缓冲输出流
void write(char[] cbuf, int off, int len) //写入字符数组的一部分
void write(int c) //写入单个字符
void write(String s, int off, int len) //写入字符串的一部分
字符缓冲流当中的两个特有方法
void newLine() :写入行分隔符(所有操作系统通用)
String readLine() :读取一行文本。
转换流
在Java11以前只能使用这种方法在字符流中指定字符集
InputStreamReader(InputStream in, String charsetName)//创建一个使用指定字符集的 InputStreamReader。
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"), "UTF-8");
OutputStreamWriter(OutputStream out, String charsetName)//创建一个使用指定字符集的 OutputStreamWriter。
Java11以后字符流推出了一个新的构造用来指定编码表
FileReader(String fileName, Charset charset) //创建一个新的 FileReader ,给定要读取的文件的名称和 charset
FileReader fr = new FileReader("a.txt", Charset.forName("GBK"));
对象操作输出流(序列化)
序列化是将对象的状态转换为字节流的过程,以便可以将对象保存到文件或通过网络传输
//对象操作流序列化代码展示
User user = new User("zhangsan", "qwertyop");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
oos.writeObject(user);
oos.close();
对象操作输入流(反格式化)
Student student =(Student) ois.readObject();
序列号
把对象所属的类的序列号设置成一个常量:
给对象所属的类加一个serialVersionUlD
private static final long serialVersionUlD = 42L;
如果一个对象中的某个成员变量的值不想被序列化: 给该成员变量加transient关键字修饰, 这样用了该关键字标记的成员变量就不会参与序列化过程了
private transient int age;
转换流和对象流的构造方法里都用的是 FileInputStream
Properties
Properties概述:
- 是一个Map体系的集合类
- Properties中有和IO相关的方法
- 只存String
Properties基本使用:
public static void main(String[] args) {
//构造:Properties虽然是Map的实现类但不需要指定泛型 但一般只会在里面添加String类型
Properties prop = new Properties();
//增
prop.put("黄乘明", "刘慧");
prop.put("小龙女", "杨过");
prop.put("孤独时代", "陈一发儿");
//删
prop.remove("黄乘明");
prop.clear();
//改
prop.put("黄乘明", "尹志平");
System.out.println(prop);
//查
prop.containsKey("黄乘明");
prop.containsValue("尹志平");
//遍历
Set<Object> key = prop.keySet();
for (Object o : key) {
System.out.println(o + "----" + prop.get(o));
}
Set<Map.Entry<Object, Object>> entries = prop.entrySet();
for (Map.Entry<Object, Object> entry : entries) {
System.out.println(entry.getKey() + "----" + entry.getValue());
}
}
Properties作为Map集合的实现类三个特有的方法
方法名 | 说明 |
---|---|
setProperty(String key, String value) | 居调用 Hashtable 方法 put |
getProperty(String key) | 在此属性列表中搜索具有指定键的属性。 |
stringPropertyNames() | 从此属性列表返回一组不可修改的键 |
public static void main(String[] args) {
Properties prop = new Properties();
prop.put("黄乘明", "刘慧");
prop.put("小龙女", "杨过");
prop.put("孤独时代", "陈一发儿");
prop.setProperty("吃屎", "喝尿");//相当于put方法
String s = prop.getProperty("吃屎");//相当于get方法
System.out.println(s);
Set<String> keysset = prop.stringPropertyNames();//相当于keySet方法
for (String key : keysset) {
System.out.println(key + "=" + prop.getProperty(key));
}
}
load properties文件
FileReader fr = new FileReader("D:\\JavaWorkSpace\\characterstream\\properties\\prop.properties");
Properties prop = new Properties();
prop.load(fr);
System.out.println(prop);
store properties文件
Properties prop = new Properties();
prop.put("zhanghsan", "123");
prop.put("lisi", "4556");
FileWriter fw = new FileWriter("D:\\JavaWorkSpace\\characterstream\\properties\\prop.properties");
prop.store(fw,"??");
fw.close();
转换流, 对象流的构造方式都是需要字节流
但Properties需要字符流