一、字节和字符

在java中有输入、输出两种io流,每种输入、输出流又分为字节流、字符流两大类。关于字节,每个字节(byte)有8bit组成。关于字符,代表一个汉字或者英文字母。

字节、字符的关系

java采用unicode编码,2个字节表示1个字符,一个中文或者英文字符的unicode编码都占用2个字节。但如果采用其他编码格式,就不尽相同了。

举栗解释

String类是按照unicode编码的,当使用String(byte []bytes,String encoding)构造字符串时,encoding指的是bytes中的数据按照那种方式编码,而非是最后产生的String的编码格式。
getBytes(String charsetName)使用指定的编码格式将此String编码为byte序列,并将结果存放到一个新的byte数组中。若不指定,则使用默认编码格式。

public class Hello {
    public static void main(String []args){
        String str = "你好hello";
        int byte_len = str.getBytes().length;
        int length = str.length();
        System.out.println("字节长度:"+byte_len);
        System.out.println("字符长度:"+length);
        System.out.println("默认编码方式:"+System.getProperty("file.encoding"));
    }
}

二、File类

File是java.io包下代表与平台无关的文件和目录。

1.构造函数

//构造
        File f1 = new File("c:\\abc\\1.txt");

        File f2 = new File("c:\\abc","2.txt");

        File file = new File("c:"+File.separator+"abc");
        File f3 = new File(file,"3.txt");

关于路径分隔符,在windows下“/”和“\”都可以,但是linux/unix下只能“/”。最好是用“/”或者跨平台分隔符File.separator,因为在java中“\”代表转义字符

2.创建、删除方法

boolean createNewFile();//文件存在返回false,否则创建返回true
        boolean mkdir();//创建file对象对应的目录,只创建最后一级目录,上级目录不存在就抛异常成功返回true
        boolean mkdirs();//创建file对象对应的目录,创建多级目录,创建路径中不存在的目录成功返回true
        boolean delete();//文件存在就删除并返回true
        boolean deleteOnExit();//在虚拟机终止时,删除

3.判断方法

boolean canExecute();//是否可执行
        boolean canRead();//是否刻度
        boolean canWrite();//是否可写
        boolean exists();//是否存在
        boolean isDirectory();//是否是目录
        boolean isFile();//是否是文件
        boolean isHidden();//是否是隐藏文件、目录
        boolean isAbsolute();//是否是绝对路径

4.获取方法

String getName();//返回文件、目录名称
        String getPath();//返回路径
        String getAbsolutePath();//返回绝对路径
        String getParent();//返回父目录
        long lastModified();//返回最后一次修改时间
        long length();//返回文件长度
        File[] listRoots();//列出所有根目录
        String[] list();//返回字符串数组
        String[] list(FilenameFilter filter);//返回满足文件过滤器要求的字符串数组
        File[] listFiles();//返回一个文件对象数组
        File[] listFiles(FilenameFilter filter);//返回满足文件过滤器要求的文件对象数组

FilenameFilter接口是一个文件过滤器,包含了一个accept(File dir,String name)方法,依次对指定File的所有子目录、文件进行迭代,按照制定规则过滤。

File[] files = file.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File file, String s) {
                return s.endsWith(".mp3");
            }
        });

三、IO流的概念

IO流是实现输入、输出的基础,可以方便的实现数据的输入、输出操作。流是一组有顺序、起点和终点的字节集合,是对数据传输的总成或抽象。数据在两个设备间的传输称之为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类。
流有输入和输出,输入时是从数据源到程序,输出是从程序到数据源。这里的数据源,可以是内存、文件、网络或者程序等。

四、IO流的分类

1.输入流和输出流

根据数据流向不同分为:输入流(只能读不能写)和输出流(只能写不能读)。

2.字节流和字符流

字节流和字符流的用法差不多,区别在于:a.读写单位上,字节流以字节(8bit)为单位,字符流以字符为单位。b.处理对象上,字节流能处理所有类型的数据,字符流只能处理字符类型的数据。

3.节点流和处理流

根据流的角色来分,有节点流和处理流。
可以from/to一个特定IO设备(磁盘、网络等)读/写数据的流,叫节点流,也被称为低级流。
对一个已存在的流进行连接和封装,通过封装后的流实现数据读写,叫处理流,也被称为高级流。

//节点流,直接传入的参数是IO设备
        FileInputStream fis = new FileInputStream("test.txt");
        //处理流,传入的参数是流对象
        BufferedInputStream bis = new BufferedInputStream(fis);

Java string 和字节数_IO


当使用处理流来进行输入、输出操作时,程序并不会直接连接到实际的数据源,没有和实际的输入、输出节点连接。好处就是:是要采用相同的处理流,程序就可以用相同的输入、输出代码访问不同的数据源。随着处理流包装的节点流的变化,访问的数据源也会相应的变化。

五、IO流的四大基类

根据流的流向和操作单元的不同,将流分为了InputStream、OutputStream、Reader、Writer。对应不同的实现类,有不同的功能。

1.InputStream

InputStream是所有输入字节流的子类,主要包含有以下3个方法:

int read();//读取一个字节并以整数形式返回(0~255),返回-1已到输入流的末尾
        int read(byte[] buffer);//读取一系列字节并存到buffer数组,返回读取的字节数。到末尾返回-1
        int read(byte[] buffer,int off,int len);//读取length个字节存到buffer数组,从off位置开始,长度len,返回实际读取个数。末尾返回-1

2.OutputStream

OutputStream所有的输出字节流的父类,主要包含有以下4个方法:

void write(int b);//向输入流写入1个字节数据,该字节数据为参数b的低8位
    void write(byte[] b);//将一个字节类型数组的数据,写入输出流
    void write(byte[] b,int off,int len);//将一个字节类型数组中从off位置、长度为len的数据写入输出流
    void flush();//将输出流中的缓冲数据全部写出到目标

3.Reader

Reader是所有输入字符流的父类,主要包含有3个方法:

int read();//读取一个字符并以整数形式返回(0~255),返回-1已到输入流的末尾
        int read(byte[] buffer);//读取一系列字符并存到buffer数组,返回读取的字节数。到末尾返回-1
        int read(byte[] buffer,int off,int len);//读取length个字符存到buffer数组,从off位置开始,长度len,返回实际读取个数。末尾返回-1

这里对比下InputStream,只是操作单元不同。在执行完流操作后,要调用close()方法来关闭输入流。因为打开的IO资源不属于内存,垃圾回收机制无法回收。
另外,InputStream和Reader都支持以下方法来移动流中指针的位置:

void mark(int readlimit);//在此输入流中标记当前位置,readlimit意味着在标记失效前可以读取字节的最大限制
        boolean markSupported();//该输入流是否支持mark方法
        long skip(long n);//跳过、丢弃输入流中的n个字节/字符
        void reset();//将此流重新定位到最后一次调用mark()的位置

4.Writer

Writer是所有输出字符流的父类,包括以下6个方法:

void write(int c);//向输出流写入一个字符,为c的低16位
        void write(char[] cbuf);//将字符类型数组的数据写入输出流
        void write(char[] cbuf,int offset,int length);//将字符类型数组的数据,从offset位置、length长度写入输出流
        void write(String string);//将字符串写入输出流
        void write(String string,int offset,int length);//将字符串offset开始、length长度的字符写入输出流
        void flush();//将输出流的缓存数据写出到目标

和OutputStream对比,Writer多了两个方法,支持写入字符和字符串。