package cn.onloc.utils.IO;
import java.io.*;
//public class CharIO {
/** 字符流
*
* Unicode 和 utf-8
* 都知道计算机是只能处理二进制的,在计算机的操作中,主要就是输入处理和输出,如果输入的是一个数字能够直接用一个二进制进行表示,那么如果输入的是一个字符呢,或者是一个字符数字呢
* 因为最先出来的计算机是处理英文的,所有定义了一个ASCll的编码表,用来表示所有的英文字母和键盘上的所有符号,所以一个ASCll码只需要一个字节就能表示。但是后来引入了中文,中文的字面量是很大的
* 一个字节已经远远不能满足了,所有对ASCll进行了扩充,提出了Unicode,它只是对每一个字符进行一个编码,但是他并不能很好的将这个编码在计算机里进行传输,所以提出了UTF-8,utF-8可以说是对
* Unicode的一种实现,他也是在?Unicode编码的基础上,对相关的二进制码在次进行编码,用来减少其在内存和磁盘中所占内存大小。
* https://zhidao.baidu.com/question/55064977.html?qbl=relate_question_0&word=unicode%BA%CDutf8%B5%C4%B9%D8%CF%B5
*
* 所以如果非得说一个字符在内存占有几个字节,这个主要是根据编码方式的不同而不同的,常用的UTF-8是占据2个字节,如果太生僻的字,是可能占据三个字节的,这个在进行utf-8编码时,已经自动处理。
*
* 开始字符流学习:
* 1、为什么要有字符流?
* 在字节流的读取中,是逐个子节逐个字节的读取的,但是都知道在各种编码中,对于中文的支持大多都是用两个字节或者更多字节来表示的,一次读取一个字节,首先在效率上肯定是慢的,还有最主要的原因
* 是这样读取出来的字节我们还要通用相同的编码方式去解析出来才能拼装为我们需要的字符,所以提出了字符流的概念,一次传递一个字符。
*
* 记住一点,流的传送都是以二进制或者说是以字节的形式传送的,所谓的字符流也是在字节流上的一个封装,所有以设备为基础直接实现的流只有FileOutputStream 和FileInputStream
* 所有在对字符流的类进行使用的时候,也必须像所有过滤流一样,通过一个具体的OutputStream实现类来创建。
* 针对刚才的这个不能对IO设备直接操作的问题,在整个字符流的操作中,对OutputStreamWriter进行了一个封装,FileWriter,使得可以直接通过FileWriter创建并操作字符流。
*
* 还有一点,一个字节流的操作是字节对文件的操作,而一个字符流,因为是对字节流的一个封装,所以在实现的时候,给整个字符流加了一个缓冲区,他会把你要写入的数据先放入到一个内存
* 的缓冲区中,当我们调用Flush()或者把字符流关闭的时候,才会把内容写入到文件中。这是对性能的一个提升考虑。
*
* 输出字符流:把程序中的字符按照相关的编码方式解析为二进制写入到文件中。
* 输入字符流:把文件中的内容,通过字符流的方式写入到程序中。
*
* 输出流:
* public abstract class writer: 顶层抽象类
* 实现类: OutputStreamWriter
* 缓冲流:BufferedWriter
*
* 区分BufferedWriter 和 OutputStreamWriter
* 先摘抄一段网上的知识:
* PrintWriter无追加模式,若写入已有文件,将清空原文件,重新写入;
* 其println自动换行;
* OutputStreamWriter与BufferedWriter有追加模式,append设置为true时,在已有文件末尾追加;append=false时,从已有文件第一行开始覆盖写入,若写入内容比原有文件短,则只覆盖部分内容;
* BufferedWriter需手动换行,bw.newLine();
* OutputStreamWriter和BufferedWriter的缺省buffersize,OutputStreamWriter是8k bytes,BufferedWriter是8k chars。
* 其次,OutputStreamWriter,PrintWriter能控制编码,BufferedWriter不能。OutputStreamWriter底层使用的是StreamEncoder,也就是对charset进行了编码,
* 举个例子,你是完全可以本地采用比如gb2312的编码而写到一个utf-8文件里去的,这个时候你会用OutputStreamWriter。当然缺省的话是使用本地的charset。
* 即使使用缺省的charset,OutputStreamWriter是会把没法转码的字符转成malformedsurrogate,而BufferedWriter是不会的;
* 再次,BufferedWriter能控制封包大小,OutputStreamWriter,PrintWriter不能。假设你操作socket,采用buffer可以使得封包大小更合理;
* 最后,BufferedWriter封装的是writer,也就是当buffer满了让别的writer去处理输出,而OutputStreamWriter封装的事数据流(OutputStream),它是让数据流去处理输出。
* stream和writer的不同不用说,一个是二进制数据,一个是字符数据,这两个根本就不一样了。
*
* 自己组织一下:
* 1、首先缓冲的内容类型是不同的,OutputStreamWriter 默认缓存的是8k字节, bufferedWriter 默认缓存的是8k字符。
* 2、对编码的处理方式上是不同的,OutputStreamWriter是能处理编码的,
* 3、bufferWriter能修改缓存区大小
*
* 字符输入流:
* InputStreamReader
*
*
*
*/
public static void main(String[] args) {
{
//字符输出流 OutputStreamWriter
try {
File file = new File("D://新建文件夹/outWriter.txt");
OutputStream fs = new FileOutputStream(file);
Writer ow = new OutputStreamWriter(fs);
String str = "你好, chinese";
ow.write(str);
ow.flush();
ow.close();
fs.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
{
//封装了字节流的字符流 FileWriter
try {
FileWriter fw = new FileWriter("D://新建文件夹/fileWriter.txt");
String str = "我爱你,chinese";
fw.write(str);
fw.flush();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
{
//字符缓存流 BufferedWriter
try {
File file = new File("D://新建文件夹/bufferedWriter1.txt");
OutputStream os = new FileOutputStream(file);
Writer w = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(w);
String str = "我爱你,chinese";
bw.write(str);
bw.flush();
bw.close();
w.close();
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
{
// 字符缓存流 BufferedWriter
try {
Writer w = new FileWriter("D://新建文件夹/bufferedWriter2.txt");
BufferedWriter bw = new BufferedWriter(w);
String str = "我爱你,chinese";
bw.write(str);
bw.flush();
bw.close();
w.close();
} catch (IOException e) {
e.printStackTrace();
}
}
{
//字符输入流 InputStreamReader
try {
File file = new File("D://新建文件夹/outWriter.txt");
InputStream is = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(is);
int a = 0;
while( a != -1) {
a = isr.read();
System.out.print( (char)a);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
{
//字符输入缓存流流 BufferedReader
try {
File file = new File("D://新建文件夹/outWriter.txt");
InputStream is = new FileInputStream(file);
Reader isr = new BufferedReader(new InputStreamReader(is));
int a = 0;
while( (a = isr.read()) != -1) {
System.out.print( (char)a);
}
System.out.println();
isr.close();
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
{
//字符输入流 FileReader
try {
Reader fr = new FileReader("D://新建文件夹/outWriter.txt");
int a = 0;
while( (a = fr.read()) != -1) {
System.out.print( (char)a);
}
System.out.println();
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
{
/** 总结:
* 基础数据类型,在创建的时候,先创建一个变量a,然后在内存(可能是堆,可能是栈,这里是栈中,因为在方法内)创建一个区域吧97这个值存放进去。
* 当在一个创建一个char类型的b时,会先去检查内存中有没有一块区域的值为97, 有,则把该块内存的地址复制给b.所以a == b; 但是当 a 指向的这块内存值改变时,
* 会去新的内存里存放改变的值,所以这时a != b,而且b的地址是没变的,只有a的地址值变化了。
*
* aaa == a?
* 这里可以很好的证明所以数据在内存中存放的都是二进制码,或者说都是一个个的字节,所以在新建变量 aa 的时候,会发现内存中有这么一块区域的值为 97 的字节码,所以
* aa 就认为这块区域就是和我要存的值一样,就把地址指向了这块区域,所以 aaa == a;
*/
//char
char a = 97;
System.out.println("---- : " + a);// ---- : a
char b = 'a';
System.out.println(" ----b: " + b);// ----b: a
System.out.println( a == b);// true
int aa = 2;
int bb = 2;
System.out.println( aa == bb);//true
int aaa = 97;
System.out.println( a == aaa); //true
}
}
//}
字符流学习
最新推荐文章于 2023-12-29 19:00:45 发布